# HG changeset patch # User duke # Date 1499280090 -7200 # Node ID 9b3a9d72f07b40c648de79961679f42283af1bb5 # Parent 6230c3f39d293b7b2841618ac9c28caa5a585c21# Parent b050dcca193f08d46c9ffdf7d63c6c25b7abd35d Merge diff -r b050dcca193f -r 9b3a9d72f07b .hgtags-top-repo --- a/.hgtags-top-repo Wed Jul 05 20:40:53 2017 +0200 +++ b/.hgtags-top-repo Wed Jul 05 20:41:30 2017 +0200 @@ -314,3 +314,4 @@ 1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69 eed77fcd77711fcdba05f18fc22f37d86efb243c jdk9-b70 c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71 +8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b corba/.hgtags --- a/corba/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/corba/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -314,3 +314,4 @@ de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69 e7cf01990ed366bd493080663259281e91ce223b jdk9-b70 cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71 +f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b hotspot/.hgtags --- a/hotspot/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -474,3 +474,4 @@ ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69 8672e9264db30c21504063932dbc374eabc287a1 jdk9-b70 07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71 +c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/aarch64/vm/aarch64.ad --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Jul 05 20:41:30 2017 +0200 @@ -865,6 +865,42 @@ V31, V31_H ); +// Class for all 64bit vector registers +reg_class vectord_reg( + V0, V0_H, + V1, V1_H, + V2, V2_H, + V3, V3_H, + V4, V4_H, + V5, V5_H, + V6, V6_H, + V7, V7_H, + V8, V8_H, + V9, V9_H, + V10, V10_H, + V11, V11_H, + V12, V12_H, + V13, V13_H, + V14, V14_H, + V15, V15_H, + V16, V16_H, + V17, V17_H, + V18, V18_H, + V19, V19_H, + V20, V20_H, + V21, V21_H, + V22, V22_H, + V23, V23_H, + V24, V24_H, + V25, V25_H, + V26, V26_H, + V27, V27_H, + V28, V28_H, + V29, V29_H, + V30, V30_H, + V31, V31_H +); + // Class for all 128bit vector registers reg_class vectorx_reg( V0, V0_H, V0_J, V0_K, @@ -2133,40 +2169,48 @@ if (bottom_type()->isa_vect() != NULL) { uint len = 4; + uint ireg = ideal_reg(); + assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector"); if (cbuf) { MacroAssembler _masm(cbuf); - uint ireg = ideal_reg(); assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity"); - assert(ireg == Op_VecX, "sanity"); if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { // stack->stack int src_offset = ra_->reg2offset(src_lo); int dst_offset = ra_->reg2offset(dst_lo); assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset"); len = 8; - if (src_offset < 512) { - __ ldp(rscratch1, rscratch2, Address(sp, src_offset)); - } else { + if (ireg == Op_VecD) { __ ldr(rscratch1, Address(sp, src_offset)); - __ ldr(rscratch2, Address(sp, src_offset+4)); - len += 4; - } - if (dst_offset < 512) { - __ stp(rscratch1, rscratch2, Address(sp, dst_offset)); + __ str(rscratch1, Address(sp, dst_offset)); } else { - __ str(rscratch1, Address(sp, dst_offset)); - __ str(rscratch2, Address(sp, dst_offset+4)); - len += 4; + if (src_offset < 512) { + __ ldp(rscratch1, rscratch2, Address(sp, src_offset)); + } else { + __ ldr(rscratch1, Address(sp, src_offset)); + __ ldr(rscratch2, Address(sp, src_offset+4)); + len += 4; + } + if (dst_offset < 512) { + __ stp(rscratch1, rscratch2, Address(sp, dst_offset)); + } else { + __ str(rscratch1, Address(sp, dst_offset)); + __ str(rscratch2, Address(sp, dst_offset+4)); + len += 4; + } } } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { - __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ T16B, + __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), + ireg == Op_VecD ? __ T8B : __ T16B, as_FloatRegister(Matcher::_regEncode[src_lo]), as_FloatRegister(Matcher::_regEncode[src_lo])); } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) { - __ str(as_FloatRegister(Matcher::_regEncode[src_lo]), __ Q, + __ str(as_FloatRegister(Matcher::_regEncode[src_lo]), + ireg == Op_VecD ? __ D : __ Q, Address(sp, ra_->reg2offset(dst_lo))); } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) { - __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ Q, + __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), + ireg == Op_VecD ? __ D : __ Q, Address(sp, ra_->reg2offset(src_lo))); } else { ShouldNotReachHere(); @@ -2176,17 +2220,22 @@ // stack->stack int src_offset = ra_->reg2offset(src_lo); int dst_offset = ra_->reg2offset(dst_lo); - if (src_offset < 512) { - st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset); - } else { + if (ireg == Op_VecD) { st->print("ldr rscratch1, [sp, #%d]", src_offset); - st->print("\nldr rscratch2, [sp, #%d]", src_offset+4); - } - if (dst_offset < 512) { - st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset); + st->print("str rscratch1, [sp, #%d]", dst_offset); } else { - st->print("\nstr rscratch1, [sp, #%d]", dst_offset); - st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4); + if (src_offset < 512) { + st->print("ldp rscratch1, rscratch2, [sp, #%d]", src_offset); + } else { + st->print("ldr rscratch1, [sp, #%d]", src_offset); + st->print("\nldr rscratch2, [sp, #%d]", src_offset+4); + } + if (dst_offset < 512) { + st->print("\nstp rscratch1, rscratch2, [sp, #%d]", dst_offset); + } else { + st->print("\nstr rscratch1, [sp, #%d]", dst_offset); + st->print("\nstr rscratch2, [sp, #%d]", dst_offset+4); + } } st->print("\t# vector spill, stack to stack"); } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) { @@ -2638,17 +2687,22 @@ return vector_width_in_bytes(bt)/type2aelembytes(bt); } const int Matcher::min_vector_size(const BasicType bt) { - //return (type2aelembytes(bt) == 1) ? 4 : 2; - // For the moment, only support 1 vector size, 128 bits - return max_vector_size(bt); +// For the moment limit the vector size to 8 bytes + int size = 8 / type2aelembytes(bt); + if (size < 2) size = 2; + return size; } // Vector ideal reg. const int Matcher::vector_ideal_reg(int len) { - return Op_VecX; + switch(len) { + case 8: return Op_VecD; + case 16: return Op_VecX; + } + ShouldNotReachHere(); + return 0; } -// Only lowest bits of xmm reg are used for vector shift count. const int Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecX; } @@ -2660,9 +2714,7 @@ // x86 supports misaligned vectors store/load. const bool Matcher::misaligned_vectors_ok() { - // TODO fixme - // return !AlignVector; // can be changed by flag - return false; + return !AlignVector; // can be changed by flag } // false => size gets scaled to BytesPerLong, ok. @@ -3073,13 +3125,13 @@ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_ldrvS(vecX dst, memory mem) %{ + enc_class aarch64_enc_ldrvS(vecD dst, memory mem) %{ FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::S, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_ldrvD(vecX dst, memory mem) %{ + enc_class aarch64_enc_ldrvD(vecD dst, memory mem) %{ FloatRegister dst_reg = as_FloatRegister($dst$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::D, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -3159,13 +3211,13 @@ as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_strvS(vecX src, memory mem) %{ + enc_class aarch64_enc_strvS(vecD src, memory mem) %{ FloatRegister src_reg = as_FloatRegister($src$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::S, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); %} - enc_class aarch64_enc_strvD(vecX src, memory mem) %{ + enc_class aarch64_enc_strvD(vecD src, memory mem) %{ FloatRegister src_reg = as_FloatRegister($src$$reg); loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::D, $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); @@ -5187,6 +5239,16 @@ interface(REG_INTER); %} +operand vecD() +%{ + constraint(ALLOC_IN_RC(vectord_reg)); + match(VecD); + + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + operand vecX() %{ constraint(ALLOC_IN_RC(vectorx_reg)); @@ -7402,6 +7464,96 @@ ins_pipe(ialu_reg); %} +//---------- Population Count Instructions ------------------------------------- +// + +instruct popCountI(iRegINoSp dst, iRegIorL2I src, vRegF tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "movw $src, $src\n\t" + "mov $tmp, $src\t# vector (1D)\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + __ movw($src$$Register, $src$$Register); // ensure top 32 bits 0 + __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +instruct popCountI_mem(iRegINoSp dst, memory mem, vRegF tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI (LoadI mem))); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "ldrs $tmp, $mem\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + FloatRegister tmp_reg = as_FloatRegister($tmp$$reg); + loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrs, tmp_reg, $mem->opcode(), + as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +// Note: Long.bitCount(long) returns an int. +instruct popCountL(iRegINoSp dst, iRegL src, vRegD tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "mov $tmp, $src\t# vector (1D)\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + +instruct popCountL_mem(iRegINoSp dst, memory mem, vRegD tmp) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL (LoadL mem))); + effect(TEMP tmp); + ins_cost(INSN_COST * 13); + + format %{ "ldrd $tmp, $mem\n\t" + "cnt $tmp, $tmp\t# vector (8B)\n\t" + "addv $tmp, $tmp\t# vector (8B)\n\t" + "mov $dst, $tmp\t# vector (1D)" %} + ins_encode %{ + FloatRegister tmp_reg = as_FloatRegister($tmp$$reg); + loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrd, tmp_reg, $mem->opcode(), + as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp); + __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister); + __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0); + %} + + ins_pipe(pipe_class_default); +%} + // ============================================================================ // MemBar Instruction @@ -13194,7 +13346,7 @@ // ====================VECTOR INSTRUCTIONS===================================== // Load vector (32 bits) -instruct loadV4(vecX dst, vmem mem) +instruct loadV4(vecD dst, vmem mem) %{ predicate(n->as_LoadVector()->memory_size() == 4); match(Set dst (LoadVector mem)); @@ -13205,7 +13357,7 @@ %} // Load vector (64 bits) -instruct loadV8(vecX dst, vmem mem) +instruct loadV8(vecD dst, vmem mem) %{ predicate(n->as_LoadVector()->memory_size() == 8); match(Set dst (LoadVector mem)); @@ -13227,7 +13379,7 @@ %} // Store Vector (32 bits) -instruct storeV4(vecX src, vmem mem) +instruct storeV4(vecD src, vmem mem) %{ predicate(n->as_StoreVector()->memory_size() == 4); match(Set mem (StoreVector mem src)); @@ -13238,7 +13390,7 @@ %} // Store Vector (64 bits) -instruct storeV8(vecX src, vmem mem) +instruct storeV8(vecD src, vmem mem) %{ predicate(n->as_StoreVector()->memory_size() == 8); match(Set mem (StoreVector mem src)); @@ -13259,8 +13411,22 @@ ins_pipe(pipe_class_memory); %} +instruct replicate8B(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (8B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate16B(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (16B)" %} @@ -13270,8 +13436,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate8B_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(8B)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T8B, $con$$constant & 0xff); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate16B_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(16B)" %} @@ -13281,8 +13461,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate4S(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (4S)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T4H, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate8S(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (8S)" %} @@ -13292,8 +13486,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate4S_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(4H)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T4H, $con$$constant & 0xffff); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate8S_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(8H)" %} @@ -13303,8 +13511,21 @@ ins_pipe(pipe_class_default); %} +instruct replicate2I(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2I)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, as_Register($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4I(vecX dst, iRegIorL2I src) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (4I)" %} @@ -13314,8 +13535,21 @@ ins_pipe(pipe_class_default); %} +instruct replicate2I_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector(2I)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T2S, $con$$constant); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4I_imm(vecX dst, immI con) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI con)); ins_cost(INSN_COST); format %{ "movi $dst, $con\t# vector(4I)" %} @@ -13327,6 +13561,7 @@ instruct replicate2L(vecX dst, iRegL src) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (2L)" %} @@ -13338,6 +13573,7 @@ instruct replicate2L_zero(vecX dst, immI0 zero) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI zero)); ins_cost(INSN_COST); format %{ "movi $dst, $zero\t# vector(4I)" %} @@ -13349,8 +13585,22 @@ ins_pipe(pipe_class_default); %} +instruct replicate2F(vecD dst, vRegF src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateF src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2F)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct replicate4F(vecX dst, vRegF src) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateF src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (4F)" %} @@ -13363,6 +13613,7 @@ instruct replicate2D(vecX dst, vRegD src) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateD src)); ins_cost(INSN_COST); format %{ "dup $dst, $src\t# vector (2D)" %} @@ -13375,6 +13626,25 @@ // ====================REDUCTION ARITHMETIC==================================== +instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp, iRegI tmp2) +%{ + match(Set dst (AddReductionVI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP tmp2); + format %{ "umov $tmp, $src2, S, 0\n\t" + "umov $tmp2, $src2, S, 1\n\t" + "addw $dst, $src1, $tmp\n\t" + "addw $dst, $dst, $tmp2\t add reduction2i" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0); + __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ S, 1); + __ addw($dst$$Register, $src1$$Register, $tmp$$Register); + __ addw($dst$$Register, $dst$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2) %{ match(Set dst (AddReductionVI src1 src2)); @@ -13393,6 +13663,25 @@ ins_pipe(pipe_class_default); %} +instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp) +%{ + match(Set dst (MulReductionVI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "umov $tmp, $src2, S, 0\n\t" + "mul $dst, $tmp, $src1\n\t" + "umov $tmp, $src2, S, 1\n\t" + "mul $dst, $tmp, $dst\t mul reduction2i\n\t" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0); + __ mul($dst$$Register, $tmp$$Register, $src1$$Register); + __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 1); + __ mul($dst$$Register, $tmp$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2) %{ match(Set dst (MulReductionVI src1 src2)); @@ -13418,6 +13707,26 @@ ins_pipe(pipe_class_default); %} +instruct reduce_add2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) +%{ + match(Set dst (AddReductionVF src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fadds $dst, $src1, $src2\n\t" + "ins $tmp, S, $src2, 0, 1\n\t" + "fadds $dst, $dst, $tmp\t add reduction2f" + %} + ins_encode %{ + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($src2$$reg), 0, 1); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_add4F(vRegF dst, vRegF src1, vecX src2, vecX tmp) %{ match(Set dst (AddReductionVF src1 src2)); @@ -13450,6 +13759,26 @@ ins_pipe(pipe_class_default); %} +instruct reduce_mul2F(vRegF dst, vRegF src1, vecD src2, vecD tmp) +%{ + match(Set dst (MulReductionVF src1 src2)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fmuls $dst, $src1, $src2\n\t" + "ins $tmp, S, $src2, 0, 1\n\t" + "fmuls $dst, $dst, $tmp\t add reduction4f" + %} + ins_encode %{ + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($src2$$reg), 0, 1); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct reduce_mul4F(vRegF dst, vRegF src1, vecX src2, vecX tmp) %{ match(Set dst (MulReductionVF src1 src2)); @@ -13526,8 +13855,24 @@ // --------------------------------- ADD -------------------------------------- +instruct vadd8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (AddVB src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (AddVB src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (16B)" %} @@ -13539,8 +13884,24 @@ ins_pipe(pipe_class_default); %} +instruct vadd4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (AddVS src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (AddVS src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (8H)" %} @@ -13552,8 +13913,23 @@ ins_pipe(pipe_class_default); %} +instruct vadd2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (AddVI src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (4S)" %} @@ -13567,6 +13943,7 @@ instruct vadd2L(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (AddVL src1 src2)); ins_cost(INSN_COST); format %{ "addv $dst,$src1,$src2\t# vector (2L)" %} @@ -13578,8 +13955,23 @@ ins_pipe(pipe_class_default); %} +instruct vadd2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fadd $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fadd(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vadd4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (AddVF src1 src2)); ins_cost(INSN_COST); format %{ "fadd $dst,$src1,$src2\t# vector (4S)" %} @@ -13606,8 +13998,24 @@ // --------------------------------- SUB -------------------------------------- +instruct vsub8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (SubVB src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (SubVB src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (16B)" %} @@ -13619,8 +14027,24 @@ ins_pipe(pipe_class_default); %} +instruct vsub4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (SubVS src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (SubVS src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (8H)" %} @@ -13632,8 +14056,23 @@ ins_pipe(pipe_class_default); %} +instruct vsub2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVI src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (SubVI src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (4S)" %} @@ -13647,6 +14086,7 @@ instruct vsub2L(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (SubVL src1 src2)); ins_cost(INSN_COST); format %{ "subv $dst,$src1,$src2\t# vector (2L)" %} @@ -13658,8 +14098,23 @@ ins_pipe(pipe_class_default); %} +instruct vsub2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fsub $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fsub(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsub4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (SubVF src1 src2)); ins_cost(INSN_COST); format %{ "fsub $dst,$src1,$src2\t# vector (4S)" %} @@ -13673,6 +14128,7 @@ instruct vsub2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (SubVD src1 src2)); ins_cost(INSN_COST); format %{ "fsub $dst,$src1,$src2\t# vector (2D)" %} @@ -13686,8 +14142,24 @@ // --------------------------------- MUL -------------------------------------- +instruct vmul4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (MulVS src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (MulVS src1 src2)); ins_cost(INSN_COST); format %{ "mulv $dst,$src1,$src2\t# vector (8H)" %} @@ -13699,8 +14171,23 @@ ins_pipe(pipe_class_default); %} +instruct vmul2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVI src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (MulVI src1 src2)); ins_cost(INSN_COST); format %{ "mulv $dst,$src1,$src2\t# vector (4S)" %} @@ -13712,8 +14199,23 @@ ins_pipe(pipe_class_default); %} +instruct vmul2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fmul $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fmul(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vmul4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (MulVF src1 src2)); ins_cost(INSN_COST); format %{ "fmul $dst,$src1,$src2\t# vector (4S)" %} @@ -13727,6 +14229,7 @@ instruct vmul2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (MulVD src1 src2)); ins_cost(INSN_COST); format %{ "fmul $dst,$src1,$src2\t# vector (2D)" %} @@ -13740,8 +14243,23 @@ // --------------------------------- DIV -------------------------------------- +instruct vdiv2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fdiv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fdiv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vdiv4F(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (DivVF src1 src2)); ins_cost(INSN_COST); format %{ "fdiv $dst,$src1,$src2\t# vector (4S)" %} @@ -13755,6 +14273,7 @@ instruct vdiv2D(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (DivVD src1 src2)); ins_cost(INSN_COST); format %{ "fdiv $dst,$src1,$src2\t# vector (2D)" %} @@ -13768,8 +14287,24 @@ // --------------------------------- AND -------------------------------------- +instruct vand8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (AndV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ andr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vand16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (AndV src1 src2)); ins_cost(INSN_COST); format %{ "and $dst,$src1,$src2\t# vector (16B)" %} @@ -13783,8 +14318,24 @@ // --------------------------------- OR --------------------------------------- +instruct vor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (OrV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ orr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vor16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (OrV src1 src2)); ins_cost(INSN_COST); format %{ "orr $dst,$src1,$src2\t# vector (16B)" %} @@ -13798,8 +14349,24 @@ // --------------------------------- XOR -------------------------------------- +instruct vxor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (XorV src1 src2)); + ins_cost(INSN_COST); + format %{ "xor $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vxor16B(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); match(Set dst (XorV src1 src2)); ins_cost(INSN_COST); format %{ "xor $dst,$src1,$src2\t# vector (16B)" %} @@ -13833,7 +14400,23 @@ ins_pipe(pipe_class_default); %} +instruct vsll8B(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); @@ -13846,7 +14429,22 @@ ins_pipe(pipe_class_default); %} +instruct vsrl8B(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (16B)" %} @@ -13858,7 +14456,28 @@ ins_pipe(pipe_class_default); %} +instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (16B)" %} @@ -13876,7 +14495,24 @@ ins_pipe(pipe_class_default); %} +instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) sh = 7; + sh = -sh & 7; + __ sshr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} @@ -13890,7 +14526,28 @@ ins_pipe(pipe_class_default); %} +instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), -sh & 7); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} @@ -13908,7 +14565,23 @@ ins_pipe(pipe_class_default); %} +instruct vsll4S(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); @@ -13921,7 +14594,22 @@ ins_pipe(pipe_class_default); %} +instruct vsrl4S(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (8H)" %} @@ -13933,7 +14621,28 @@ ins_pipe(pipe_class_default); %} +instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (8H)" %} @@ -13951,7 +14660,24 @@ ins_pipe(pipe_class_default); %} +instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) sh = 15; + sh = -sh & 15; + __ sshr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} @@ -13965,7 +14691,28 @@ ins_pipe(pipe_class_default); %} +instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant & 31; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), -sh & 15); + } + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} @@ -13983,7 +14730,22 @@ ins_pipe(pipe_class_default); %} +instruct vsll2I(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); @@ -13996,7 +14758,21 @@ ins_pipe(pipe_class_default); %} +instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "ushl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (4S)" %} @@ -14008,7 +14784,21 @@ ins_pipe(pipe_class_default); %} +instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ shl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVI src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (4S)" %} @@ -14020,7 +14810,21 @@ ins_pipe(pipe_class_default); %} +instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ sshr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + -(int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} @@ -14032,7 +14836,21 @@ ins_pipe(pipe_class_default); %} +instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ ushr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + -(int)$shift$$constant & 31); + %} + ins_pipe(pipe_class_default); +%} + instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} @@ -14045,6 +14863,7 @@ %} instruct vsll2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); match(Set dst (RShiftVL src shift)); ins_cost(INSN_COST); @@ -14058,6 +14877,7 @@ %} instruct vsrl2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (URShiftVL src shift)); ins_cost(INSN_COST); format %{ "ushl $dst,$src,$shift\t# vector (2D)" %} @@ -14070,6 +14890,7 @@ %} instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); ins_cost(INSN_COST); format %{ "shl $dst, $src, $shift\t# vector (2D)" %} @@ -14082,6 +14903,7 @@ %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (RShiftVL src shift)); ins_cost(INSN_COST); format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} @@ -14094,6 +14916,7 @@ %} instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); match(Set dst (URShiftVL src shift)); ins_cost(INSN_COST); format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -2055,6 +2055,9 @@ INSN(negr, 1, 0b100000101110); INSN(notr, 1, 0b100000010110); INSN(addv, 0, 0b110001101110); + INSN(cls, 0, 0b100000010010); + INSN(clz, 1, 0b100000010010); + INSN(cnt, 0, 0b100000010110); #undef INSN diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -36,6 +36,7 @@ class MacroAssembler: public Assembler { friend class LIR_Assembler; + public: using Assembler::mov; using Assembler::movi; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -199,6 +199,12 @@ UseCRC32Intrinsics = true; } + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) { if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); @@ -251,6 +257,10 @@ UseBarriersForVolatile = (_cpuFeatures & CPU_DMB_ATOMICS) != 0; } + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + UsePopCountInstruction = true; + } + #ifdef COMPILER2 if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -191,6 +191,13 @@ FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + // Adjust RTM (Restricted Transactional Memory) flags. if (!has_tcheck() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/assembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -128,8 +128,11 @@ faligndata_op3 = 0x36, flog3_op3 = 0x36, edge_op3 = 0x36, + fzero_op3 = 0x36, fsrc_op3 = 0x36, + fnot_op3 = 0x36, xmulx_op3 = 0x36, + crc32c_op3 = 0x36, impdep2_op3 = 0x37, stpartialf_op3 = 0x37, jmpl_op3 = 0x38, @@ -231,7 +234,9 @@ sha1_opf = 0x141, sha256_opf = 0x142, - sha512_opf = 0x143 + sha512_opf = 0x143, + + crc32c_opf = 0x147 }; enum op5s { @@ -600,6 +605,11 @@ return x & ((1 << 10) - 1); } + // create a low12 __value__ (not a field) for a given a 32-bit constant + static int low12( int x ) { + return x & ((1 << 12) - 1); + } + // AES crypto instructions supported only on certain processors static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); } @@ -608,6 +618,9 @@ static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); } static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); } + // CRC32C instruction supported only on certain processors + static void crc32c_only() { assert( VM_Version::has_crc32c(), "This instruction only works on SPARC with CRC32C"); } + // instruction only in VIS1 static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); } @@ -1022,6 +1035,7 @@ void nop() { emit_int32( op(branch_op) | op2(sethi_op2) ); } + void sw_count() { emit_int32( op(branch_op) | op2(sethi_op2) | 0x3f0 ); } // pp 202 @@ -1198,8 +1212,14 @@ void faligndata( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(faligndata_op3) | fs1(s1, FloatRegisterImpl::D) | opf(faligndata_opf) | fs2(s2, FloatRegisterImpl::D)); } + void fzero( FloatRegisterImpl::Width w, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fzero_op3) | opf(0x62 - w)); } + void fsrc2( FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fsrc_op3) | opf(0x7A - w) | fs2(s2, w)); } + void fnot1( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fnot_op3) | fs1(s1, w) | opf(0x6C - w)); } + + void fpmerge( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(0x36) | fs1(s1, FloatRegisterImpl::S) | opf(0x4b) | fs2(s2, FloatRegisterImpl::S)); } + void stpartialf( Register s1, Register s2, FloatRegister d, int ia = -1 ) { vis1_only(); emit_int32( op(ldst_op) | fd(d, FloatRegisterImpl::D) | op3(stpartialf_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); } // VIS2 instructions @@ -1224,6 +1244,10 @@ void sha256() { sha256_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); } void sha512() { sha512_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); } + // CRC32C instruction + + void crc32c( FloatRegister s1, FloatRegister s2, FloatRegister d ) { crc32c_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(crc32c_op3) | fs1(s1, FloatRegisterImpl::D) | opf(crc32c_opf) | fs2(s2, FloatRegisterImpl::D)); } + // Creation Assembler(CodeBuffer* code) : AbstractAssembler(code) { #ifdef CHECK_DELAY diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -956,6 +956,7 @@ int hi = (int)(value >> 32); int lo = (int)(value & ~0); + int bits_33to2 = (int)((value >> 2) & ~0); // (Matcher::isSimpleConstant64 knows about the following optimizations.) if (Assembler::is_simm13(lo) && value == lo) { or3(G0, lo, d); @@ -964,6 +965,12 @@ if (low10(lo) != 0) or3(d, low10(lo), d); } + else if ((hi >> 2) == 0) { + Assembler::sethi(bits_33to2, d); // hardware version zero-extends to upper 32 + sllx(d, 2, d); + if (low12(lo) != 0) + or3(d, low12(lo), d); + } else if (hi == -1) { Assembler::sethi(~lo, d); // hardware version zero-extends to upper 32 xor3(d, low10(lo) ^ ~low10(~0), d); @@ -4351,3 +4358,52 @@ cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); nop(); // Separate short branches } + +/** + * Update CRC-32[C] with a byte value according to constants in table + * + * @param [in,out]crc Register containing the crc. + * @param [in]val Register containing the byte to fold into the CRC. + * @param [in]table Register containing the table of crc constants. + * + * uint32_t crc; + * val = crc_table[(val ^ crc) & 0xFF]; + * crc = val ^ (crc >> 8); + */ +void MacroAssembler::update_byte_crc32(Register crc, Register val, Register table) { + xor3(val, crc, val); + and3(val, 0xFF, val); + sllx(val, 2, val); + lduw(table, val, val); + srlx(crc, 8, crc); + xor3(val, crc, crc); +} + +// Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros +void MacroAssembler::reverse_bytes_32(Register src, Register dst, Register tmp) { + srlx(src, 24, dst); + + sllx(src, 32+8, tmp); + srlx(tmp, 32+24, tmp); + sllx(tmp, 8, tmp); + or3(dst, tmp, dst); + + sllx(src, 32+16, tmp); + srlx(tmp, 32+24, tmp); + sllx(tmp, 16, tmp); + or3(dst, tmp, dst); + + sllx(src, 32+24, tmp); + srlx(tmp, 32, tmp); + or3(dst, tmp, dst); +} + +void MacroAssembler::movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2) { + reverse_bytes_32(src, tmp1, tmp2); + movxtod(tmp1, dst); +} + +void MacroAssembler::movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2) { + movdtox(src, tmp1); + reverse_bytes_32(tmp1, dst, tmp2); +} diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp Wed Jul 05 20:41:30 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 @@ -903,6 +903,10 @@ inline void ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d); inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0); + // little-endian + inline void ldxl(Register s1, Register s2, Register d) { ldxa(s1, s2, ASI_PRIMARY_LITTLE, d); } + inline void ldfl(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { ldfa(w, s1, s2, ASI_PRIMARY_LITTLE, d); } + // membar psuedo instruction. takes into account target memory model. inline void membar( Assembler::Membar_mask_bits const7a ); @@ -1436,6 +1440,14 @@ // Use BIS for zeroing void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); + // Update CRC-32[C] with a byte value according to constants in table + void update_byte_crc32(Register crc, Register val, Register table); + + // Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros + void reverse_bytes_32(Register src, Register dst, Register tmp); + void movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2); + void movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2); + #undef VIRTUAL }; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -4910,6 +4910,206 @@ return start; } +#define CHUNK_LEN 128 /* 128 x 8B = 1KB */ +#define CHUNK_K1 0x1307a0206 /* reverseBits(pow(x, CHUNK_LEN*8*8*3 - 32) mod P(x)) << 1 */ +#define CHUNK_K2 0x1a0f717c4 /* reverseBits(pow(x, CHUNK_LEN*8*8*2 - 32) mod P(x)) << 1 */ +#define CHUNK_K3 0x0170076fa /* reverseBits(pow(x, CHUNK_LEN*8*8*1 - 32) mod P(x)) << 1 */ + + /** + * Arguments: + * + * Inputs: + * O0 - int crc + * O1 - byte* buf + * O2 - int len + * O3 - int* table + * + * Output: + * O0 - int crc result + */ + address generate_updateBytesCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction"); + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C"); + address start = __ pc(); + + const Register crc = O0; // crc + const Register buf = O1; // source java byte array address + const Register len = O2; // number of bytes + const Register table = O3; // byteTable + + Label L_crc32c_head, L_crc32c_aligned; + Label L_crc32c_parallel, L_crc32c_parallel_loop; + Label L_crc32c_serial, L_crc32c_x32_loop, L_crc32c_x8, L_crc32c_x8_loop; + Label L_crc32c_done, L_crc32c_tail, L_crc32c_return; + + __ cmp_and_br_short(len, 0, Assembler::lessEqual, Assembler::pn, L_crc32c_return); + + // clear upper 32 bits of crc + __ clruwu(crc); + + __ and3(buf, 7, G4); + __ cmp_and_brx_short(G4, 0, Assembler::equal, Assembler::pt, L_crc32c_aligned); + + __ mov(8, G1); + __ sub(G1, G4, G4); + + // ------ process the misaligned head (7 bytes or less) ------ + __ BIND(L_crc32c_head); + + // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF]; + __ ldub(buf, 0, G1); + __ update_byte_crc32(crc, G1, table); + + __ inc(buf); + __ dec(len); + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pn, L_crc32c_return); + __ dec(G4); + __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_head); + + // ------ process the 8-byte-aligned body ------ + __ BIND(L_crc32c_aligned); + __ nop(); + __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pn, L_crc32c_tail); + + // reverse the byte order of lower 32 bits to big endian, and move to FP side + __ movitof_revbytes(crc, F0, G1, G3); + + __ set(CHUNK_LEN*8*4, G4); + __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pt, L_crc32c_serial); + + // ------ process four 1KB chunks in parallel ------ + __ BIND(L_crc32c_parallel); + + __ fzero(FloatRegisterImpl::D, F2); + __ fzero(FloatRegisterImpl::D, F4); + __ fzero(FloatRegisterImpl::D, F6); + + __ mov(CHUNK_LEN - 1, G4); + __ BIND(L_crc32c_parallel_loop); + // schedule ldf's ahead of crc32c's to hide the load-use latency + __ ldf(FloatRegisterImpl::D, buf, 0, F8); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8, F10); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*24, F14); + __ crc32c(F0, F8, F0); + __ crc32c(F2, F10, F2); + __ crc32c(F4, F12, F4); + __ crc32c(F6, F14, F6); + __ inc(buf, 8); + __ dec(G4); + __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_parallel_loop); + + __ ldf(FloatRegisterImpl::D, buf, 0, F8); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8, F10); + __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12); + __ crc32c(F0, F8, F0); + __ crc32c(F2, F10, F2); + __ crc32c(F4, F12, F4); + + __ inc(buf, CHUNK_LEN*24); + __ ldfl(FloatRegisterImpl::D, buf, G0, F14); // load in little endian + __ inc(buf, 8); + + __ prefetch(buf, 0, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*8, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*16, Assembler::severalReads); + __ prefetch(buf, CHUNK_LEN*24, Assembler::severalReads); + + // move to INT side, and reverse the byte order of lower 32 bits to little endian + __ movftoi_revbytes(F0, O4, G1, G4); + __ movftoi_revbytes(F2, O5, G1, G4); + __ movftoi_revbytes(F4, G5, G1, G4); + + // combine the results of 4 chunks + __ set64(CHUNK_K1, G3, G1); + __ xmulx(O4, G3, O4); + __ set64(CHUNK_K2, G3, G1); + __ xmulx(O5, G3, O5); + __ set64(CHUNK_K3, G3, G1); + __ xmulx(G5, G3, G5); + + __ movdtox(F14, G4); + __ xor3(O4, O5, O5); + __ xor3(G5, O5, O5); + __ xor3(G4, O5, O5); + + // reverse the byte order to big endian, via stack, and move to FP side + __ add(SP, -8, G1); + __ srlx(G1, 3, G1); + __ sllx(G1, 3, G1); + __ stx(O5, G1, G0); + __ ldfl(FloatRegisterImpl::D, G1, G0, F2); // load in little endian + + __ crc32c(F6, F2, F0); + + __ set(CHUNK_LEN*8*4, G4); + __ sub(len, G4, len); + __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_parallel); + __ nop(); + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_done); + + __ BIND(L_crc32c_serial); + + __ mov(32, G4); + __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pn, L_crc32c_x8); + + // ------ process 32B chunks ------ + __ BIND(L_crc32c_x32_loop); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ dec(len, 32); + __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_x32_loop); + + __ BIND(L_crc32c_x8); + __ nop(); + __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pt, L_crc32c_done); + + // ------ process 8B chunks ------ + __ BIND(L_crc32c_x8_loop); + __ ldf(FloatRegisterImpl::D, buf, 0, F2); + __ inc(buf, 8); + __ crc32c(F0, F2, F0); + __ dec(len, 8); + __ cmp_and_br_short(len, 8, Assembler::greaterEqual, Assembler::pt, L_crc32c_x8_loop); + + __ BIND(L_crc32c_done); + + // move to INT side, and reverse the byte order of lower 32 bits to little endian + __ movftoi_revbytes(F0, crc, G1, G3); + + __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_return); + + // ------ process the misaligned tail (7 bytes or less) ------ + __ BIND(L_crc32c_tail); + + // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF]; + __ ldub(buf, 0, G1); + __ update_byte_crc32(crc, G1, table); + + __ inc(buf); + __ dec(len); + __ cmp_and_br_short(len, 0, Assembler::greater, Assembler::pt, L_crc32c_tail); + + __ BIND(L_crc32c_return); + __ nop(); + __ retl(); + __ delayed()->nop(); + + return start; + } + void generate_initial() { // Generates all stubs and initializes the entry points @@ -5001,6 +5201,11 @@ StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress"); StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB"); } + + // generate CRC32C intrinsic code + if (UseCRC32CIntrinsics) { + StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(); + } } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, 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 @@ -41,7 +41,7 @@ enum /* platform_dependent_constants */ { // %%%%%%%% May be able to shrink this a lot code_size1 = 20000, // simply increase if too small (assembler will crash if too small) - code_size2 = 23000 // simply increase if too small (assembler will crash if too small) + code_size2 = 24000 // simply increase if too small (assembler will crash if too small) }; class Sparc { diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -230,7 +230,7 @@ assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size"); char buf[512]; - jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")), (has_hardware_popc() ? ", popc" : ""), (has_vis1() ? ", vis1" : ""), @@ -242,6 +242,7 @@ (has_sha1() ? ", sha1" : ""), (has_sha256() ? ", sha256" : ""), (has_sha512() ? ", sha512" : ""), + (has_crc32c() ? ", crc32c" : ""), (is_ultra3() ? ", ultra3" : ""), (is_sun4v() ? ", sun4v" : ""), (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")), @@ -363,6 +364,23 @@ } } + // SPARC T4 and above should have support for CRC32C instruction + if (has_crc32c()) { + if (UseVIS > 2) { // CRC32C intrinsics use VIS3 instructions + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } else { + if (UseCRC32CIntrinsics) { + warning("SPARC CRC32C intrinsics require VIS3 instruction support. Intrinsics will be disabled."); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + } + } else if (UseCRC32CIntrinsics) { + warning("CRC32C instruction is not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && (cache_line_size > ContendedPaddingWidth)) ContendedPaddingWidth = cache_line_size; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jul 05 20:41:30 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 @@ -53,7 +53,8 @@ aes_instructions = 19, sha1_instruction = 20, sha256_instruction = 21, - sha512_instruction = 22 + sha512_instruction = 22, + crc32c_instruction = 23 }; enum Feature_Flag_Set { @@ -83,6 +84,7 @@ sha1_instruction_m = 1 << sha1_instruction, sha256_instruction_m = 1 << sha256_instruction, sha512_instruction_m = 1 << sha512_instruction, + crc32c_instruction_m = 1 << crc32c_instruction, generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, generic_v9_m = generic_v8_m | v9_instructions_m, @@ -141,6 +143,7 @@ static bool has_sha1() { return (_features & sha1_instruction_m) != 0; } static bool has_sha256() { return (_features & sha256_instruction_m) != 0; } static bool has_sha512() { return (_features & sha512_instruction_m) != 0; } + static bool has_crc32c() { return (_features & crc32c_instruction_m) != 0; } static bool supports_compare_and_exchange() { return has_v9(); } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -699,6 +699,12 @@ FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + if (UseCRC32CIntrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) + warning("CRC32C intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + // Adjust RTM (Restricted Transactional Memory) flags if (!supports_rtm() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -363,6 +363,11 @@ #endif if (av & AV_SPARC_CBCOND) features |= cbcond_instructions_m; +#ifndef AV_SPARC_CRC32C +#define AV_SPARC_CRC32C 0x20000000 /* crc32c instruction supported */ +#endif + if (av & AV_SPARC_CRC32C) features |= crc32c_instruction_m; + #ifndef AV_SPARC_AES #define AV_SPARC_AES 0x00020000 /* aes instrs supported */ #endif diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/ci/ciField.cpp --- a/hotspot/src/share/vm/ci/ciField.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/ci/ciField.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -186,6 +186,10 @@ // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; + // Trust VM anonymous classes. They are private API (sun.misc.Unsafe) and can't be serialized, + // so there is no hacking of finals going on with them. + if (holder->is_anonymous()) + return true; return TrustFinalNonStaticFields; } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/ci/ciInstanceKlass.cpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -58,6 +58,7 @@ _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_default_methods = ik->has_default_methods(); + _is_anonymous = ik->is_anonymous(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily @@ -101,6 +102,7 @@ _has_nonstatic_fields = false; _nonstatic_fields = NULL; _has_injected_fields = -1; + _is_anonymous = false; _loader = loader; _protection_domain = protection_domain; _is_shared = false; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/ci/ciInstanceKlass.hpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -53,6 +53,7 @@ bool _has_subklass; bool _has_nonstatic_fields; bool _has_default_methods; + bool _is_anonymous; ciFlags _flags; jint _nonstatic_field_size; @@ -179,6 +180,10 @@ return _has_default_methods; } + bool is_anonymous() { + return _is_anonymous; + } + ciInstanceKlass* get_canonical_holder(int offset); ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -863,6 +863,12 @@ do_name( updateByteBuffer_name, "updateByteBuffer") \ do_signature(updateByteBuffer_signature, "(IJII)I") \ \ + /* support for java.util.zip.CRC32C */ \ + do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ + do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_name, updateBytes_signature, F_S) \ + do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \ + do_name( updateDirectByteBuffer_name, "updateDirectByteBuffer") \ + \ /* support for sun.misc.Unsafe */ \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ \ diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -962,6 +962,7 @@ (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 || strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 || + strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 || strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 || diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -197,7 +197,7 @@ CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { return generate_method_call(method_id, true, false); } - Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static); + Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls); Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2); Node* make_string_method_node(int opcode, Node* str1, Node* str2); @@ -291,6 +291,9 @@ bool inline_updateCRC32(); bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); + Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class); + bool inline_updateBytesCRC32C(); + bool inline_updateDirectByteBufferCRC32C(); bool inline_multiplyToLen(); bool inline_squareToLen(); bool inline_mulAdd(); @@ -539,6 +542,11 @@ if (!UseCRC32Intrinsics) return NULL; break; + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: + if (!UseCRC32CIntrinsics) return NULL; + break; + case vmIntrinsics::_incrementExactI: case vmIntrinsics::_addExactI: if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL; @@ -947,6 +955,11 @@ case vmIntrinsics::_updateByteBufferCRC32: return inline_updateByteBufferCRC32(); + case vmIntrinsics::_updateBytesCRC32C: + return inline_updateBytesCRC32C(); + case vmIntrinsics::_updateDirectByteBufferCRC32C: + return inline_updateDirectByteBufferCRC32C(); + case vmIntrinsics::_profileBoolean: return inline_profileBoolean(); case vmIntrinsics::_isCompileConstant: @@ -5536,6 +5549,106 @@ return true; } +//------------------------------get_table_from_crc32c_class----------------------- +Node * LibraryCallKit::get_table_from_crc32c_class(ciInstanceKlass *crc32c_class) { + Node* table = load_field_from_object(NULL, "byteTable", "[I", /*is_exact*/ false, /*is_static*/ true, crc32c_class); + assert (table != NULL, "wrong version of java.util.zip.CRC32C"); + + return table; +} + +//------------------------------inline_updateBytesCRC32C----------------------- +// +// Calculate CRC32C for byte[] array. +// int java.util.zip.CRC32C.updateBytes(int crc, byte[] buf, int off, int end) +// +bool LibraryCallKit::inline_updateBytesCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction support"); + assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters"); + assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded"); + // no receiver since it is a static method + Node* crc = argument(0); // type: int + Node* src = argument(1); // type: oop + Node* offset = argument(2); // type: int + Node* end = argument(3); // type: int + + Node* length = _gvn.transform(new SubINode(end, offset)); + + const Type* src_type = src->Value(&_gvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + if (top_src == NULL || top_src->klass() == NULL) { + // failed array check + return false; + } + + // Figure out the size and type of the elements we will be copying. + BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem != T_BYTE) { + return false; + } + + // 'src_start' points to src array + scaled offset + Node* src_start = array_element_address(src, offset, src_elem); + + // static final int[] byteTable in class CRC32C + Node* table = get_table_from_crc32c_class(callee()->holder()); + Node* table_start = array_element_address(table, intcon(0), T_INT); + + // We assume that range check is done by caller. + // TODO: generate range check (offset+length < src.length) in debug VM. + + // Call the stub. + address stubAddr = StubRoutines::updateBytesCRC32C(); + const char *stubName = "updateBytesCRC32C"; + + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + crc, src_start, length, table_start); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + +//------------------------------inline_updateDirectByteBufferCRC32C----------------------- +// +// Calculate CRC32C for DirectByteBuffer. +// int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int end) +// +bool LibraryCallKit::inline_updateDirectByteBufferCRC32C() { + assert(UseCRC32CIntrinsics, "need CRC32C instruction support"); + assert(callee()->signature()->size() == 5, "updateDirectByteBuffer has 4 parameters and one is long"); + assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded"); + // no receiver since it is a static method + Node* crc = argument(0); // type: int + Node* src = argument(1); // type: long + Node* offset = argument(3); // type: int + Node* end = argument(4); // type: int + + Node* length = _gvn.transform(new SubINode(end, offset)); + + src = ConvL2X(src); // adjust Java long to machine word + Node* base = _gvn.transform(new CastX2PNode(src)); + offset = ConvI2X(offset); + + // 'src_start' points to src array + scaled offset + Node* src_start = basic_plus_adr(top(), base, offset); + + // static final int[] byteTable in class CRC32C + Node* table = get_table_from_crc32c_class(callee()->holder()); + Node* table_start = array_element_address(table, intcon(0), T_INT); + + // Call the stub. + address stubAddr = StubRoutines::updateBytesCRC32C(); + const char *stubName = "updateBytesCRC32C"; + + Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + crc, src_start, length, table_start); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + //----------------------------inline_reference_get---------------------------- // public T java.lang.ref.Reference.get(); bool LibraryCallKit::inline_reference_get() { @@ -5571,18 +5684,28 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, - bool is_exact=true, bool is_static=false) { - - const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); - assert(tinst != NULL, "obj is null"); - assert(tinst->klass()->is_loaded(), "obj is not loaded"); - assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); - - ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName), - ciSymbol::make(fieldTypeString), - is_static); + bool is_exact=true, bool is_static=false, + ciInstanceKlass * fromKls=NULL) { + if (fromKls == NULL) { + const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr(); + assert(tinst != NULL, "obj is null"); + assert(tinst->klass()->is_loaded(), "obj is not loaded"); + assert(!is_exact || tinst->klass_is_exact(), "klass not exact"); + fromKls = tinst->klass()->as_instance_klass(); + } else { + assert(is_static, "only for static field access"); + } + ciField* field = fromKls->get_field_by_name(ciSymbol::make(fieldName), + ciSymbol::make(fieldTypeString), + is_static); + + assert (field != NULL, "undefined field"); if (field == NULL) return (Node *) NULL; - assert (field != NULL, "undefined field"); + + if (is_static) { + const TypeInstPtr* tip = TypeInstPtr::make(fromKls->java_mirror()); + fromObj = makecon(tip); + } // Next code copied from Parse::do_get_xxx(): diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -851,6 +851,29 @@ return TypeFunc::make(domain, range); } +/** + * int updateBytesCRC32C(int crc, byte* buf, int len, int* table) + */ +const TypeFunc* OptoRuntime::updateBytesCRC32C_Type() { + // create input type (domain) + int num_args = 4; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypeInt::INT; // crc + fields[argp++] = TypePtr::NOTNULL; // buf + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypePtr::NOTNULL; // table + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeInt::INT; // crc result + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields); + return TypeFunc::make(domain, range); +} + // for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning int const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() { // create input type (domain) diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/opto/runtime.hpp --- a/hotspot/src/share/vm/opto/runtime.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/opto/runtime.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -319,6 +319,7 @@ static const TypeFunc* ghash_processBlocks_Type(); static const TypeFunc* updateBytesCRC32_Type(); + static const TypeFunc* updateBytesCRC32C_Type(); // leaf on stack replacement interpreter accessor types static const TypeFunc* osr_end_Type(); diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -183,13 +183,20 @@ break; } + // Ignore nodes with non-primitive type. + BasicType bt; + if (n->is_Mem()) { + bt = n->as_Mem()->memory_type(); + } else { + bt = n->bottom_type()->basic_type(); + } + if (is_java_primitive(bt) == false) { + ignored_loop_nodes[i] = n->_idx; + continue; + } + if (n->is_Mem()) { MemNode* current = n->as_Mem(); - BasicType bt = current->memory_type(); - if (is_java_primitive(bt) == false) { - ignored_loop_nodes[i] = n->_idx; - continue; - } Node* adr = n->in(MemNode::Address); Node* n_ctrl = _phase->get_ctrl(adr); @@ -231,11 +238,12 @@ BasicType bt; Node* n = lpt()->_body.at(i); - if (n->is_Store()) { + if (n->is_Mem()) { bt = n->as_Mem()->memory_type(); } else { bt = n->bottom_type()->basic_type(); } + if (is_java_primitive(bt) == false) continue; int cur_max_vector = Matcher::max_vector_size(bt); diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -3753,8 +3753,12 @@ if (TieredCompilation) { set_tiered_flags(); } else { - // Check if the policy is valid. Policies 0 and 1 are valid for non-tiered setup. - if (CompilationPolicyChoice >= 2) { + int max_compilation_policy_choice = 1; +#ifdef COMPILER2 + max_compilation_policy_choice = 2; +#endif + // Check if the policy is valid. + if (CompilationPolicyChoice >= max_compilation_policy_choice) { vm_exit_during_initialization( "Incompatible compilation policy selected", NULL); } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/compilationPolicy.cpp --- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -512,7 +512,7 @@ RegisterMap reg_map(thread, false); javaVFrame* triggerVF = thread->last_java_vframe(®_map); // triggerVF is the frame that triggered its counter - RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m); + RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m()); if (first->top_method()->code() != NULL) { // called obsolete method/nmethod -- no need to recompile @@ -557,8 +557,8 @@ if( !next ) // No next frame up the stack? break; // Then compile with current frame - methodHandle m = current->top_method(); - methodHandle next_m = next->top_method(); + Method* m = current->top_method(); + Method* next_m = next->top_method(); if (TraceCompilationPolicy && Verbose) { tty->print("[caller: "); @@ -644,7 +644,7 @@ if (TraceCompilationPolicy && Verbose) { tty->print("\n\t check caller: "); next_m->print_short_name(tty); - tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m()), next_m->code_size()); + tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m), next_m->code_size()); } current = next; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -848,6 +848,9 @@ product(bool, UseCRC32Intrinsics, false, \ "use intrinsics for java.util.zip.CRC32") \ \ + product(bool, UseCRC32CIntrinsics, false, \ + "use intrinsics for java.util.zip.CRC32C") \ + \ develop(bool, TraceCallFixup, false, \ "Trace all call fixups") \ \ diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/rframe.cpp --- a/hotspot/src/share/vm/runtime/rframe.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/rframe.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -52,12 +52,12 @@ : RFrame(fr, thread, callee) { RegisterMap map(thread, false); _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); - _method = methodHandle(thread, _vf->method()); + _method = _vf->method(); assert( _vf->is_interpreted_frame(), "must be interpreted"); init(); } -InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m) +InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, Method* m) : RFrame(fr, thread, NULL) { RegisterMap map(thread, false); _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); @@ -140,8 +140,8 @@ _nm = compiledVFrame::cast(vf)->code(); vf = vf->top(); _vf = javaVFrame::cast(vf); - _method = methodHandle(thread(), CodeCache::find_nmethod(_fr.pc())->method()); - assert(_method(), "should have found a method"); + _method = CodeCache::find_nmethod(_fr.pc())->method(); + assert(_method, "should have found a method"); #ifndef PRODUCT _invocations = _method->compiled_invocation_count(); #endif diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/rframe.hpp --- a/hotspot/src/share/vm/runtime/rframe.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/rframe.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -60,7 +60,7 @@ frame fr() const { return _fr; } JavaThread* thread() const { return _thread; } virtual int cost() const = 0; // estimated inlining cost (size) - virtual methodHandle top_method() const = 0; + virtual Method* top_method() const = 0; virtual javaVFrame* top_vframe() const = 0; virtual nmethod* nm() const { ShouldNotCallThis(); return NULL; } @@ -79,7 +79,7 @@ protected: nmethod* _nm; javaVFrame* _vf; // top vframe; may be NULL (for most recent frame) - methodHandle _method; // top method + Method* _method; // top method CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee); void init(); @@ -88,7 +88,7 @@ public: CompiledRFrame(frame fr, JavaThread* thread); // for nmethod triggering its counter (callee == NULL) bool is_compiled() const { return true; } - methodHandle top_method() const { return _method; } + Method* top_method() const { return _method; } javaVFrame* top_vframe() const { return _vf; } nmethod* nm() const { return _nm; } int cost() const; @@ -98,16 +98,16 @@ class InterpretedRFrame : public RFrame { // interpreter frame protected: javaVFrame* _vf; // may be NULL (for most recent frame) - methodHandle _method; + Method* _method; InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee); void init(); friend class RFrame; public: - InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m); // constructor for method triggering its invocation counter + InterpretedRFrame(frame fr, JavaThread* thread, Method* m); // constructor for method triggering its invocation counter bool is_interpreted() const { return true; } - methodHandle top_method() const { return _method; } + Method* top_method() const { return _method; } javaVFrame* top_vframe() const { return _vf; } int cost() const; void print(); diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -137,6 +137,8 @@ address StubRoutines::_updateBytesCRC32 = NULL; address StubRoutines::_crc_table_adr = NULL; +address StubRoutines::_updateBytesCRC32C = NULL; + address StubRoutines::_multiplyToLen = NULL; address StubRoutines::_squareToLen = NULL; address StubRoutines::_mulAdd = NULL; diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:41:30 2017 +0200 @@ -197,6 +197,8 @@ static address _updateBytesCRC32; static address _crc_table_adr; + static address _updateBytesCRC32C; + static address _multiplyToLen; static address _squareToLen; static address _mulAdd; @@ -359,6 +361,8 @@ static address updateBytesCRC32() { return _updateBytesCRC32; } static address crc_table_addr() { return _crc_table_adr; } + static address updateBytesCRC32C() { return _updateBytesCRC32C; } + static address multiplyToLen() {return _multiplyToLen; } static address squareToLen() {return _squareToLen; } static address mulAdd() {return _mulAdd; } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -830,6 +830,7 @@ static_field(StubRoutines, _ghash_processBlocks, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ + static_field(StubRoutines, _updateBytesCRC32C, address) \ static_field(StubRoutines, _multiplyToLen, address) \ static_field(StubRoutines, _squareToLen, address) \ static_field(StubRoutines, _mulAdd, address) \ diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/TEST.groups Wed Jul 05 20:41:30 2017 +0200 @@ -147,12 +147,16 @@ gc/survivorAlignment \ gc/TestGCLogRotationViaJcmd.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ + runtime/NMT/JcmdSummaryDiff.java \ + runtime/RedefineTests/RedefineAnnotations.java serviceability/sa/jmap-hashcode/Test8028623.java \ serviceability/threads/TestFalseDeadLock.java \ compiler/codecache/jmx \ compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java \ compiler/rangechecks/TestRangeCheckSmearing.java \ - serviceability/dcmd + compiler/whitebox/DeoptimizeMultipleOSRTest.java \ + serviceability/dcmd \ + testlibrary_tests/whitebox/vm_flags # Compact 2 adds full VM tests compact2 = \ diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java --- a/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java Wed Jul 05 20:41:30 2017 +0200 @@ -21,6 +21,7 @@ * questions. */ +import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import java.lang.management.MemoryPoolMXBean; import javax.management.Notification; @@ -80,19 +81,42 @@ } /** - * A "non-nmethods" code heap is used by interpreter during bytecode - * execution, thus, it can't be predicted if this code heap usage will be - * increased or not. Same goes for 'All'. + * Checks if the usage of the code heap corresponding to 'btype' can be + * predicted at runtime if we disable compilation. The usage of the + * 'NonNMethod' code heap can not be predicted because we generate adapters + * and buffers at runtime. The 'MethodNonProfiled' code heap is also not + * predictable because we may generate compiled versions of method handle + * intrinsics while resolving methods at runtime. Same applies to 'All'. * * @param btype BlobType to be checked * @return boolean value, true if respective code heap is predictable */ public static boolean isCodeHeapPredictable(BlobType btype) { - return btype == BlobType.MethodNonProfiled - || btype == BlobType.MethodProfiled; + return btype == BlobType.MethodProfiled; } - public static void disableCollectionUsageThresholds(){ + /** + * Verifies that 'newValue' is equal to 'oldValue' if usage of the + * corresponding code heap is predictable. Checks the weaker condition + * 'newValue >= oldValue' if usage is not predictable because intermediate + * allocations may happen. + * + * @param btype BlobType of the code heap to be checked + * @param newValue New value to be verified + * @param oldValue Old value to be verified + * @param msg Error message if verification fails + */ + public static void assertEQorGTE(BlobType btype, long newValue, long oldValue, String msg) { + if (CodeCacheUtils.isCodeHeapPredictable(btype)) { + // Usage is predictable, check strong == condition + Asserts.assertEQ(newValue, oldValue, msg); + } else { + // Usage is not predictable, check weaker >= condition + Asserts.assertGTE(newValue, oldValue, msg); + } + } + + public static void disableCollectionUsageThresholds() { BlobType.getAvailable().stream() .map(BlobType::getMemoryPool) .filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported) diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/GetUsageTest.java --- a/hotspot/test/compiler/codecache/jmx/GetUsageTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -52,10 +52,8 @@ public static void main(String[] args) throws Exception { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - for (int allocSize = 10; allocSize < 100000; allocSize *= 10) { - new GetUsageTest(btype, allocSize).runTest(); - } + for (int allocSize = 10; allocSize < 100000; allocSize *= 10) { + new GetUsageTest(btype, allocSize).runTest(); } } } @@ -87,13 +85,15 @@ for (MemoryPoolMXBean entry : predictableBeans) { long diff = current.get(entry) - initial.get(entry); if (entry.equals(btype.getMemoryPool())) { - Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate, - String.format("Pool %s usage increase was reported " - + "unexpectedly as increased by %d using " - + "allocation size %d", entry.getName(), - diff, allocateSize)); + if (CodeCacheUtils.isCodeHeapPredictable(btype)) { + Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate, + String.format("Pool %s usage increase was reported " + + "unexpectedly as increased by %d using " + + "allocation size %d", entry.getName(), + diff, allocateSize)); + } } else { - Asserts.assertEQ(diff, 0L, + CodeCacheUtils.assertEQorGTE(btype, diff, 0L, String.format("Pool %s usage changed unexpectedly while" + " trying to increase: %s using allocation " + "size %d", entry.getName(), diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/PeakUsageTest.java --- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -52,9 +52,7 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new PeakUsageTest(btype).runTest(); - } + new PeakUsageTest(btype).runTest(); } } @@ -65,7 +63,7 @@ CodeCacheUtils.ALLOCATION_SIZE, btype.id); long newPeakUsage = bean.getPeakUsage().getUsed(); try { - Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getUsage().getUsed(), "Peak usage does not match usage after allocation for " + bean.getName()); } finally { @@ -73,18 +71,18 @@ CodeCacheUtils.WB.freeCodeBlob(addr); } } - Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getPeakUsage().getUsed(), "Code cache peak usage has changed after usage decreased for " + bean.getName()); bean.resetPeakUsage(); - Asserts.assertEQ(bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(), bean.getUsage().getUsed(), "Code cache peak usage is not equal to usage after reset for " + bean.getName()); long addr2 = CodeCacheUtils.WB.allocateCodeBlob( CodeCacheUtils.ALLOCATION_SIZE, btype.id); try { - Asserts.assertEQ(bean.getPeakUsage().getUsed(), + CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(), bean.getUsage().getUsed(), "Code cache peak usage is not equal to usage after fresh " + "allocation for " + bean.getName()); diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java --- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -97,13 +97,11 @@ return false; }); for (BlobType bt : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(bt)) { - int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0; - Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(), - expectedNotificationsAmount, String.format("Unexpected " - + "amount of notifications for pool: %s", - bt.getMemoryPool().getName())); - } + int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0; + CodeCacheUtils.assertEQorGTE(btype, counters.get(bt.getMemoryPool().getName()).get(), + expectedNotificationsAmount, String.format("Unexpected " + + "amount of notifications for pool: %s", + bt.getMemoryPool().getName())); } try { ((NotificationEmitter) ManagementFactory.getMemoryMXBean()). diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java --- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -54,9 +54,7 @@ public static void main(String[] args) { for (BlobType bt : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(bt)) { - new ThresholdNotificationsTest(bt).runTest(); - } + new ThresholdNotificationsTest(bt).runTest(); } } @@ -92,7 +90,9 @@ } Asserts.assertTrue( Utils.waitForCondition( - () -> counter == iterationsCount, WAIT_TIME), + () -> (CodeCacheUtils.isCodeHeapPredictable(btype) ? + (counter == iterationsCount) : (counter >= iterationsCount)), + WAIT_TIME), "Couldn't receive expected notifications count"); try { ((NotificationEmitter) ManagementFactory.getMemoryMXBean()). diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -51,13 +51,9 @@ } public static void main(String[] args) { - int iterationsCount = - Integer.getInteger("jdk.test.lib.iterations", 1); + int iterationsCount = Integer.getInteger("jdk.test.lib.iterations", 1); for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdExceededTest(btype, iterationsCount) - .runTest(); - } + new UsageThresholdExceededTest(btype, iterationsCount).runTest(); } } @@ -67,9 +63,8 @@ for (int i = 0; i < iterations; i++) { CodeCacheUtils.hitUsageThreshold(bean, btype); } - Asserts.assertEQ(bean.getUsageThresholdCount(), oldValue + iterations, + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), oldValue + iterations, "Unexpected threshold usage count"); - System.out.printf("INFO: Scenario finished successfully for %s%n", - bean.getName()); + System.out.printf("INFO: Scenario finished successfully for %s%n", bean.getName()); } } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -27,7 +27,6 @@ /* * @test UsageThresholdIncreasedTest - * @ignore 8129937 * @library /testlibrary /../../test/lib * @modules java.base/sun.misc * java.management @@ -54,14 +53,12 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdIncreasedTest(btype).runTest(); - } + new UsageThresholdIncreasedTest(btype).runTest(); } } private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){ - Asserts.assertEQ(bean.getUsageThresholdCount(), count, + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), count, String.format("Usage threshold was hit: %d times for %s " + "Threshold value: %d with current usage: %d", bean.getUsageThresholdCount(), bean.getName(), diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java --- a/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -50,9 +50,7 @@ public static void main(String[] args) { for (BlobType btype : BlobType.getAvailable()) { - if (CodeCacheUtils.isCodeHeapPredictable(btype)) { - new UsageThresholdNotExceededTest(btype).runTest(); - } + new UsageThresholdNotExceededTest(btype).runTest(); } } @@ -65,13 +63,11 @@ - CodeCacheUtils.getHeaderSize(btype), btype.id); // a gc cycle triggers usage threshold recalculation CodeCacheUtils.WB.fullGC(); - Asserts.assertEQ(bean.getUsageThresholdCount(), initialThresholdCount, - String.format("Usage threshold was hit: %d times for %s. " + CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), initialThresholdCount, + String.format("Usage threshold was hit: %d times for %s. " + "Threshold value: %d with current usage: %d", bean.getUsageThresholdCount(), bean.getName(), bean.getUsageThreshold(), bean.getUsage().getUsed())); - - System.out.println("INFO: Case finished successfully for " - + bean.getName()); + System.out.println("INFO: Case finished successfully for " + bean.getName()); } } diff -r b050dcca193f -r 9b3a9d72f07b hotspot/test/compiler/intrinsics/crc32c/TestCRC32C.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/crc32c/TestCRC32C.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,221 @@ +/* + * 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 8073583 + * @summary C2 support for CRC32C on SPARC + * + * @run main/othervm/timeout=600 -Xbatch TestCRC32C -m + */ + +import java.nio.ByteBuffer; +import java.util.zip.Checksum; +import java.util.zip.CRC32C; + +public class TestCRC32C { + public static void main(String[] args) { + int offset = Integer.getInteger("offset", 0); + int msgSize = Integer.getInteger("msgSize", 512); + boolean multi = false; + int iters = 20000; + int warmupIters = 20000; + + if (args.length > 0) { + if (args[0].equals("-m")) { + multi = true; + } else { + iters = Integer.valueOf(args[0]); + } + if (args.length > 1) { + warmupIters = Integer.valueOf(args[1]); + } + } + + if (multi) { + test_multi(warmupIters); + return; + } + + System.out.println(" offset = " + offset); + System.out.println("msgSize = " + msgSize + " bytes"); + System.out.println(" iters = " + iters); + + byte[] b = initializedBytes(msgSize, offset); + + CRC32C crc0 = new CRC32C(); + CRC32C crc1 = new CRC32C(); + CRC32C crc2 = new CRC32C(); + + crc0.update(b, offset, msgSize); + + System.out.println("-------------------------------------------------------"); + + /* warm up */ + for (int i = 0; i < warmupIters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + } + + /* measure performance */ + long start = System.nanoTime(); + for (int i = 0; i < iters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + } + long end = System.nanoTime(); + double total = (double)(end - start)/1e9; // in seconds + double thruput = (double)msgSize*iters/1e6/total; // in MB/s + System.out.println("CRC32C.update(byte[]) runtime = " + total + " seconds"); + System.out.println("CRC32C.update(byte[]) throughput = " + thruput + " MB/s"); + + /* check correctness */ + for (int i = 0; i < iters; i++) { + crc1.reset(); + crc1.update(b, offset, msgSize); + if (!check(crc0, crc1)) break; + } + report("CRCs", crc0, crc1); + + System.out.println("-------------------------------------------------------"); + + ByteBuffer buf = ByteBuffer.allocateDirect(msgSize); + buf.put(b, offset, msgSize); + buf.flip(); + + /* warm up */ + for (int i = 0; i < warmupIters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + } + + /* measure performance */ + start = System.nanoTime(); + for (int i = 0; i < iters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + } + end = System.nanoTime(); + total = (double)(end - start)/1e9; // in seconds + thruput = (double)msgSize*iters/1e6/total; // in MB/s + System.out.println("CRC32C.update(ByteBuffer) runtime = " + total + " seconds"); + System.out.println("CRC32C.update(ByteBuffer) throughput = " + thruput + " MB/s"); + + /* check correctness */ + for (int i = 0; i < iters; i++) { + crc2.reset(); + crc2.update(buf); + buf.rewind(); + if (!check(crc0, crc2)) break; + } + report("CRCs", crc0, crc2); + + System.out.println("-------------------------------------------------------"); + } + + private static void report(String s, Checksum crc0, Checksum crc1) { + System.out.printf("%s: crc0 = %08x, crc1 = %08x\n", + s, crc0.getValue(), crc1.getValue()); + } + + private static boolean check(Checksum crc0, Checksum crc1) { + if (crc0.getValue() != crc1.getValue()) { + System.err.printf("ERROR: crc0 = %08x, crc1 = %08x\n", + crc0.getValue(), crc1.getValue()); + return false; + } + return true; + } + + private static byte[] initializedBytes(int M, int offset) { + byte[] bytes = new byte[M + offset]; + for (int i = 0; i < offset; i++) { + bytes[i] = (byte) i; + } + for (int i = offset; i < bytes.length; i++) { + bytes[i] = (byte) (i - offset); + } + return bytes; + } + + private static void test_multi(int iters) { + int len1 = 8; // the 8B/iteration loop + int len2 = 32; // the 32B/iteration loop + int len3 = 4096; // the 4KB/iteration loop + + byte[] b = initializedBytes(len3*16, 0); + int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 }; + int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7, + len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7, + len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7, + len2, len2+1, len2+3, len2+5, len2+7, + len2*2, len2*4, len2*8, len2*16, len2*32, len2*64, + len3, len3+1, len3+3, len3+5, len3+7, + len3*2, len3*4, len3*8, + len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7, + len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7, + len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7, + len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3, + len1+len2+len3+5, len1+len2+len3+7, + (len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3, + (len1+len2+len3)*2+5, (len1+len2+len3)*2+7, + (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3, + (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 }; + CRC32C[] crc0 = new CRC32C[offsets.length*sizes.length]; + CRC32C[] crc1 = new CRC32C[offsets.length*sizes.length]; + int i, j, k; + + System.out.printf("testing %d cases ...\n", offsets.length*sizes.length); + + /* set the result from interpreter as reference */ + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + crc0[i*sizes.length + j] = new CRC32C(); + crc1[i*sizes.length + j] = new CRC32C(); + crc0[i*sizes.length + j].update(b, offsets[i], sizes[j]); + } + } + + /* warm up the JIT compiler and get result */ + for (k = 0; k < iters; k++) { + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + crc1[i*sizes.length + j].reset(); + crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]); + } + } + } + + /* check correctness */ + for (i = 0; i < offsets.length; i++) { + for (j = 0; j < sizes.length; j++) { + if (!check(crc0[i*sizes.length + j], crc1[i*sizes.length + j])) { + System.out.printf("offsets[%d] = %d", i, offsets[i]); + System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]); + } + } + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/.hgtags --- a/jaxp/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/jaxp/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -314,3 +314,4 @@ f844a908d3308f47d73cf64e87c98d37d5d76ce8 jdk9-b69 42180703e0a362c1de7cdbf61d2cbc6609e678c4 jdk9-b70 a3200b88f259f904876b9ab13fd4c4ec2726f8ba jdk9-b71 +81e85f3b6174314155991048767452a9931e12e2 jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: Compile.java,v 1.2.4.1 2005/08/31 11:24:13 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline; - -import com.sun.org.apache.xalan.internal.utils.FeatureManager; -import java.io.File; -import java.net.URL; -import java.util.Vector; - -import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOpt; -import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOptsException; -import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; - -/** - * @author Jacek Ambroziak - * @author Santiago Pericas-Geertsen - * @author G. Todd Miller - * @author Morten Jorgensen - */ -public final class Compile { - - // Versioning numbers for the compiler -v option output - private static int VERSION_MAJOR = 1; - private static int VERSION_MINOR = 4; - private static int VERSION_DELTA = 0; - - - - // This variable should be set to false to prevent any methods in this - // class from calling System.exit(). As this is a command-line tool, - // calling System.exit() is normally OK, but we also want to allow for - // this class being used in other ways as well. - private static boolean _allowExit = true; - - - public static void printUsage() { - System.err.println("XSLTC version " + - VERSION_MAJOR + "." + VERSION_MINOR + - ((VERSION_DELTA > 0) ? ("." + VERSION_DELTA) : ("")) + "\n" + - new ErrorMsg(ErrorMsg.COMPILE_USAGE_STR)); - if (_allowExit) System.exit(-1); - } - - /** - * This method implements the command line compiler. See the USAGE_STRING - * constant for a description. It may make sense to move the command-line - * handling to a separate package (ie. make one xsltc.cmdline.Compiler - * class that contains this main() method and one xsltc.cmdline.Transform - * class that contains the DefaultRun stuff). - */ - public static void main(String[] args) { - try { - boolean inputIsURL = false; - boolean useStdIn = false; - boolean classNameSet = false; - final GetOpt getopt = new GetOpt(args, "o:d:j:p:uxhsinv"); - if (args.length < 1) printUsage(); - - final XSLTC xsltc = new XSLTC(true, new FeatureManager()); - xsltc.init(); - - int c; - while ((c = getopt.getNextOption()) != -1) { - switch(c) { - case 'i': - useStdIn = true; - break; - case 'o': - xsltc.setClassName(getopt.getOptionArg()); - classNameSet = true; - break; - case 'd': - xsltc.setDestDirectory(getopt.getOptionArg()); - break; - case 'p': - xsltc.setPackageName(getopt.getOptionArg()); - break; - case 'j': - xsltc.setJarFileName(getopt.getOptionArg()); - break; - case 'x': - xsltc.setDebug(true); - break; - case 'u': - inputIsURL = true; - break; - case 's': - _allowExit = false; - break; - case 'n': - xsltc.setTemplateInlining(true); // used to be 'false' - break; - case 'v': - // fall through to case h - case 'h': - default: - printUsage(); - break; - } - } - - boolean compileOK; - - if (useStdIn) { - if (!classNameSet) { - System.err.println(new ErrorMsg(ErrorMsg.COMPILE_STDIN_ERR)); - if (_allowExit) System.exit(-1); - } - compileOK = xsltc.compile(System.in, xsltc.getClassName()); - } - else { - // Generate a vector containg URLs for all stylesheets specified - final String[] stylesheetNames = getopt.getCmdArgs(); - final Vector stylesheetVector = new Vector(); - for (int i = 0; i < stylesheetNames.length; i++) { - final String name = stylesheetNames[i]; - URL url; - if (inputIsURL) - url = new URL(name); - else - url = (new File(name)).toURI().toURL(); - stylesheetVector.addElement(url); - } - compileOK = xsltc.compile(stylesheetVector); - } - - // Compile the stylesheet and output class/jar file(s) - if (compileOK) { - xsltc.printWarnings(); - if (xsltc.getJarFileName() != null) xsltc.outputToJar(); - if (_allowExit) System.exit(0); - } - else { - xsltc.printWarnings(); - xsltc.printErrors(); - if (_allowExit) System.exit(-1); - } - } - catch (GetOptsException ex) { - System.err.println(ex); - printUsage(); // exits with code '-1' - } - catch (Exception e) { - e.printStackTrace(); - if (_allowExit) System.exit(-1); - } - } - -} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Transform.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Transform.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: Transform.java,v 1.2.4.1 2005/09/12 09:07:33 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline; - -import com.sun.org.apache.xalan.internal.utils.ObjectFactory; -import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM; -import com.sun.org.apache.xalan.internal.xsltc.StripFilter; -import com.sun.org.apache.xalan.internal.xsltc.TransletException; -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; -import com.sun.org.apache.xalan.internal.xsltc.dom.DOMWSFilter; -import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager; -import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; -import com.sun.org.apache.xalan.internal.xsltc.runtime.Constants; -import com.sun.org.apache.xalan.internal.xsltc.runtime.Parameter; -import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory; -import com.sun.org.apache.xml.internal.dtm.DTMWSFilter; -import com.sun.org.apache.xml.internal.serializer.SerializationHandler; -import java.io.FileNotFoundException; -import java.net.MalformedURLException; -import java.net.UnknownHostException; -import java.util.Vector; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.sax.SAXSource; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; - -/** - * @author Jacek Ambroziak - * @author Santiago Pericas-Geertsen - * @author G. Todd Miller - * @author Morten Jorgensen - */ -final public class Transform { - - private SerializationHandler _handler; - - private String _fileName; - private String _className; - private String _jarFileSrc; - private boolean _isJarFileSpecified = false; - private Vector _params = null; - private boolean _uri, _debug; - private int _iterations; - - public Transform(String className, String fileName, - boolean uri, boolean debug, int iterations) { - _fileName = fileName; - _className = className; - _uri = uri; - _debug = debug; - _iterations = iterations; - } - - public String getFileName(){return _fileName;} - public String getClassName(){return _className;} - - public void setParameters(Vector params) { - _params = params; - } - - private void setJarFileInputSrc(boolean flag, String jarFile) { - // TODO: at this time we do not do anything with this - // information, attempts to add the jarfile to the CLASSPATH - // were successful via System.setProperty, but the effects - // were not visible to the running JVM. For now we add jarfile - // to CLASSPATH in the wrapper script that calls this program. - _isJarFileSpecified = flag; - // TODO verify jarFile exists... - _jarFileSrc = jarFile; - } - - private void doTransform() { - try { - final Class clazz = ObjectFactory.findProviderClass(_className, true); - final AbstractTranslet translet = (AbstractTranslet)clazz.newInstance(); - translet.postInitialization(); - - // Create a SAX parser and get the XMLReader object it uses - final SAXParserFactory factory = SAXParserFactory.newInstance(); - try { - factory.setFeature(Constants.NAMESPACE_FEATURE,true); - } - catch (Exception e) { - factory.setNamespaceAware(true); - } - final SAXParser parser = factory.newSAXParser(); - final XMLReader reader = parser.getXMLReader(); - - // Set the DOM's DOM builder as the XMLReader's SAX2 content handler - XSLTCDTMManager dtmManager = - XSLTCDTMManager.createNewDTMManagerInstance(); - - DTMWSFilter wsfilter; - if (translet != null && translet instanceof StripFilter) { - wsfilter = new DOMWSFilter(translet); - } else { - wsfilter = null; - } - - final DOMEnhancedForDTM dom = - (DOMEnhancedForDTM)dtmManager.getDTM( - new SAXSource(reader, new InputSource(_fileName)), - false, wsfilter, true, false, translet.hasIdCall()); - - dom.setDocumentURI(_fileName); - translet.prepassDocument(dom); - - // Pass global parameters - int n = _params.size(); - for (int i = 0; i < n; i++) { - Parameter param = (Parameter) _params.elementAt(i); - translet.addParameter(param._name, param._value); - } - - // Transform the document - TransletOutputHandlerFactory tohFactory = - TransletOutputHandlerFactory.newInstance(); - tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM); - tohFactory.setEncoding(translet._encoding); - tohFactory.setOutputMethod(translet._method); - - if (_iterations == -1) { - translet.transform(dom, tohFactory.getSerializationHandler()); - } - else if (_iterations > 0) { - long mm = System.currentTimeMillis(); - for (int i = 0; i < _iterations; i++) { - translet.transform(dom, - tohFactory.getSerializationHandler()); - } - mm = System.currentTimeMillis() - mm; - - System.err.println("\n"); - } - } - catch (TransletException e) { - if (_debug) e.printStackTrace(); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - e.getMessage()); - } - catch (RuntimeException e) { - if (_debug) e.printStackTrace(); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - e.getMessage()); - } - catch (FileNotFoundException e) { - if (_debug) e.printStackTrace(); - ErrorMsg err = new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, _fileName); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - err.toString()); - } - catch (MalformedURLException e) { - if (_debug) e.printStackTrace(); - ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, _fileName); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - err.toString()); - } - catch (ClassNotFoundException e) { - if (_debug) e.printStackTrace(); - ErrorMsg err= new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR,_className); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - err.toString()); - } - catch (UnknownHostException e) { - if (_debug) e.printStackTrace(); - ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, _fileName); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - err.toString()); - } - catch (SAXException e) { - Exception ex = e.getException(); - if (_debug) { - if (ex != null) ex.printStackTrace(); - e.printStackTrace(); - } - System.err.print(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)); - if (ex != null) - System.err.println(ex.getMessage()); - else - System.err.println(e.getMessage()); - } - catch (Exception e) { - if (_debug) e.printStackTrace(); - System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+ - e.getMessage()); - } - } - - public static void printUsage() { - System.err.println(new ErrorMsg(ErrorMsg.TRANSFORM_USAGE_STR)); - } - - public static void main(String[] args) { - try { - if (args.length > 0) { - int i; - int iterations = -1; - boolean uri = false, debug = false; - boolean isJarFileSpecified = false; - String jarFile = null; - - // Parse options starting with '-' - for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++) { - if (args[i].equals("-u")) { - uri = true; - } - else if (args[i].equals("-x")) { - debug = true; - } - else if (args[i].equals("-j")) { - isJarFileSpecified = true; - jarFile = args[++i]; - } - else if (args[i].equals("-n")) { - try { - iterations = Integer.parseInt(args[++i]); - } - catch (NumberFormatException e) { - // ignore - } - } - else { - printUsage(); - } - } - - // Enough arguments left ? - if (args.length - i < 2) printUsage(); - - // Get document file and class name - Transform handler = new Transform(args[i+1], args[i], uri, - debug, iterations); - handler.setJarFileInputSrc(isJarFileSpecified, jarFile); - - // Parse stylesheet parameters - Vector params = new Vector(); - for (i += 2; i < args.length; i++) { - final int equal = args[i].indexOf('='); - if (equal > 0) { - final String name = args[i].substring(0, equal); - final String value = args[i].substring(equal+1); - params.addElement(new Parameter(name, value)); - } - else { - printUsage(); - } - } - - if (i == args.length) { - handler.setParameters(params); - handler.doTransform(); - } - } else { - printUsage(); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } -} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOpt.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOpt.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: GetOpt.java,v 1.2.4.1 2005/08/31 11:46:04 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt; - -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; - - -/** -* GetOpt is a Java equivalent to the C getopt() library function -* discussed in man page getopt(3C). It provides command line -* parsing for Java applications. It supports the most rules of the -* command line standard (see man page intro(1)) including stacked -* options such as '-sxm' (which is equivalent to -s -x -m); it -* handles special '--' option that signifies the end of options. -* Additionally this implementation of getopt will check for -* mandatory arguments to options such as in the case of -* '-d ' it will throw a MissingOptArgException if the -* option argument '' is not included on the commandline. -* getopt(3C) does not check for this. - * @author G Todd Miller -*/ -public class GetOpt{ - public GetOpt(String[] args, String optString){ - theOptions = new ArrayList(); - int currOptIndex = 0; - theCmdArgs = new ArrayList(); - theOptionMatcher = new OptionMatcher(optString); - // fill in the options list - for(int i=0; i 2){ - // stacked options found, such as '-shm' - // iterate thru the tokens after the dash and - // add them to theOptions list - for(int j=1; j', if current option parsed is 'd' then - * getOptionArg() would return ''. - * @return String - argument for current parsed option. - * @param none - */ - public String getOptionArg(){ - String retval = null; - String tmp = theCurrentOption.getArgument(); - char c = theCurrentOption.getArgLetter(); - if(theOptionMatcher.hasArg(c)){ - retval = tmp; - } - return retval; - } - - /** - * gets list of the commandline arguments. For example, in command - * such as 'cmd -s -d file file2 file3 file4' with the usage - * 'cmd [-s] [-d ] ...', getCmdArgs() would return - * the list {file2, file3, file4}. - * @return String[] - list of command arguments that may appear - * after options and option arguments. - * @params none - */ - public String[] getCmdArgs(){ - String[] retval = new String[theCmdArgs.size()]; - int i=0; - for(ListIterator it=theCmdArgs.listIterator(); it.hasNext();){ - retval[i++] = (String)it.next(); - } - return retval; - } - - - private Option theCurrentOption = null; - private ListIterator theOptionsIterator; - private List theOptions = null; - private List theCmdArgs = null; - private OptionMatcher theOptionMatcher = null; - - /////////////////////////////////////////////////////////// - // - // Inner Classes - // - /////////////////////////////////////////////////////////// - - // inner class to model an option - class Option{ - private char theArgLetter; - private String theArgument = null; - public Option(char argLetter) { theArgLetter = argLetter; } - public void setArg(String arg) { - theArgument = arg; - } - public boolean hasArg() { return (theArgument != null); } - public char getArgLetter() { return theArgLetter; } - public String getArgument() { return theArgument; } - } // end class Option - - - // inner class to query optString for a possible option match, - // and whether or not a given legal option takes an argument. - // - class OptionMatcher{ - public OptionMatcher(String optString){ - theOptString = optString; - } - public boolean match(char c){ - boolean retval = false; - if(theOptString.indexOf(c) != -1){ - retval = true; - } - return retval; - } - public boolean hasArg(char c){ - boolean retval = false; - int index = theOptString.indexOf(c)+1; - if (index == theOptString.length()){ - // reached end of theOptString - retval = false; - } - else if(theOptString.charAt(index) == ':'){ - retval = true; - } - return retval; - } - private String theOptString = null; - } // end class OptionMatcher -}// end class GetOpt diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOptsException.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOptsException.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: GetOptsException.java,v 1.2.4.1 2005/08/31 11:47:06 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt; - -/** - * @author G Todd Miller - */ -public class GetOptsException extends Exception{ - static final long serialVersionUID = 8736874967183039804L; - public GetOptsException(String msg){ - super(msg); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/IllegalArgumentException.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/IllegalArgumentException.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: IllegalArgumentException.java,v 1.2.4.1 2005/08/31 11:47:56 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt; - - -class IllegalArgumentException extends GetOptsException{ - static final long serialVersionUID = 8642122427294793651L; - public IllegalArgumentException(String msg){ - super(msg); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/MissingOptArgException.java --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/MissingOptArgException.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - * $Id: MissingOptArgException.java,v 1.2.4.1 2005/08/31 11:49:21 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt; - - -/** - * @author G Todd Miller - */ -class MissingOptArgException extends GetOptsException{ - static final long serialVersionUID = -1972471465394544822L; - public MissingOptArgException(String msg){ - super(msg); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java --- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java Wed Jul 05 20:41:30 2017 +0200 @@ -49,7 +49,7 @@ * Get the next XMLEvent * @see XMLEvent * @throws XMLStreamException if there is an error with the underlying XML. - * @throws NoSuchElementException iteration has no more elements. + * @throws java.util.NoSuchElementException iteration has no more elements. */ public XMLEvent nextEvent() throws XMLStreamException; diff -r b050dcca193f -r 9b3a9d72f07b jaxp/src/java.xml/share/classes/javax/xml/stream/events/XMLEvent.java --- a/jaxp/src/java.xml/share/classes/javax/xml/stream/events/XMLEvent.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/events/XMLEvent.java Wed Jul 05 20:41:30 2017 +0200 @@ -170,7 +170,7 @@ * infoset expressed. * * @param writer The writer that will output the data - * @throws XMLStreamException if there is a fatal error writing the event + * @throws javax.xml.stream.XMLStreamException if there is a fatal error writing the event */ public void writeAsEncodedUnicode(Writer writer) throws javax.xml.stream.XMLStreamException; diff -r b050dcca193f -r 9b3a9d72f07b jaxws/.hgtags --- a/jaxws/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/jaxws/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -317,3 +317,4 @@ f5911c6155c29ac24b6f9068273207e5ebd3a3df jdk9-b69 94084caa27a3c8a09a7510aef596ebd64e97c569 jdk9-b70 61caeb7061bbf8cc74a767997e5d17cc00712629 jdk9-b71 +1d87054e2d2f405c114f0061b97cbf8214bddf0a jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b jdk/.hgtags --- a/jdk/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -314,3 +314,4 @@ 551323004d0ce2f1d4b0e99552f7e0cdcebc6fca jdk9-b69 a7f731125b7fb0e4b0186172f85a21e2d5139f7e jdk9-b70 e47d3bfbc61accc3fbd372a674fdce2933b54f31 jdk9-b71 +f376824d4940f45719d91838f3f6249f873440db jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/lib/Lib-jdk.internal.le.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/lib/Lib-jdk.internal.le.gmk Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,60 @@ +# +# 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. 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. +# + +include LibCommon.gmk + +################################################################################ + +ifeq ($(OPENJDK_TARGET_OS), windows) + + LIBLE_SRC := $(JDK_TOPDIR)/src/jdk.internal.le/$(OPENJDK_TARGET_OS_TYPE)/native/lible \ + # + LIBLE_CPPFLAGS := \ + $(addprefix -I, $(LIBLE_SRC)) \ + -I$(SUPPORT_OUTPUTDIR)/headers/jdk.internal.le \ + # + + $(eval $(call SetupNativeCompilation,BUILD_LIBLE, \ + LIBRARY := le, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(LIBLE_SRC), \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBJAVA_HEADER_FLAGS)\ + $(LIBLE_CPPFLAGS), \ + LDFLAGS := $(LDFLAGS_JDKLIB), \ + LDFLAGS_SUFFIX := $(LDFLAGS_JDKLIB_SUFFIX) user32.lib, \ + VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ + RC_FLAGS := $(RC_FLAGS) \ + -D "JDK_FNAME=le.dll" \ + -D "JDK_INTERNAL_NAME=le" \ + -D "JDK_FTYPE=0x2L", \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lible, \ + DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) + + TARGETS += $(BUILD_LIBLE) + +endif # OPENJDK_TARGET_OS + +################################################################################ diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/sharing/README.txt --- a/jdk/make/non-build-utils/sharing/README.txt Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -This directory contains tools and tests associated with creating the -class list for class data sharing. - -The class list is produced by running the refWorkload startup3 benchmark with -the -XX:+TraceClassLoadingPreorder option. The -Xshare:off option must also be -used so that bootclasspath classes are loaded from rt.jar. The MakeClasslist -program should be built into the jar file makeclasslist.jar and is run -on one of the logs from each of the benchmarks in the following fashion: - -cd ...//results.startup3 -$JAVA_HOME/bin/java -jar makeclasslist.jar results.Noop/results_1/log results.Framer/results_1/log results.XFramer/results_1/log results.JEdit/results_1/log results.LimeWire/results_1/log results.NetBeans50/results_1/log - -Presently, $JAVA_HOME must be the same path used to run the startup3 benchmark. - -The logs are deliberately concatenated in roughly smallest to largest order -based on application size. The resulting output is redirected into a file -and results in one of classlist.solaris, classlist.linux, classlist.macosx, -or classlist.windows. These files are checked in to the workspace. A -necessary checksum (AddJsum.java) is added to the final classlist -(installed in lib/ or jre/lib/) during the build process by the -makefiles in make/java/redist. - -In a forthcoming JDK build we plan to manually add the dependent -classes for the calendar manager Glow, which pulls in the Preferences -classes and, on Unix platforms, the XML parsing classes. - -The properties file supplied to the refworkload is approximately the -following: - -javahome=/usr/java/j2sdk1.8.0 -resultsdir=classlist-run -iterations=1 -benchmarks=startup3 -globalvmoptions=-client -Xshare:off -XX:+TraceClassLoadingPreorder diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/sharing/tests/GHello.java --- a/jdk/make/non-build-utils/sharing/tests/GHello.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2003, 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. 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. - */ - - -import java.awt.Font; -import java.awt.Frame; -import java.awt.Label; - -public class GHello extends Frame { - - public static void main(String[] args) { - System.out.println("Hello"); - - new GHello().show(); - if (args.length == 1 && args[0].equals("quit")) { - try { - Thread.currentThread().sleep(200); - } catch (InterruptedException e) { - } - System.exit(0); - } - } - - - GHello() { - Label label = new Label("Hello"); - label.setFont(new Font("Monospaced", Font.PLAIN, 144)); - add(label); - pack(); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/sharing/tests/Hello.java --- a/jdk/make/non-build-utils/sharing/tests/Hello.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2003, 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. 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. - */ - - - -public class Hello { - public static void main(String[] args) { - System.out.println("Hello, World!"); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/sharing/tests/JHello.java --- a/jdk/make/non-build-utils/sharing/tests/JHello.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2003, 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. 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. - */ - - -import java.awt.Font; -import javax.swing.JFrame; -import javax.swing.JLabel; - -public class JHello extends JFrame { - - public static void main(String[] args) { - System.out.println("Hello"); - - new JHello().show(); - if (args.length == 1 && args[0].equals("quit")) { - try { - Thread.currentThread().sleep(1000); - } catch (InterruptedException e) { - } - System.exit(0); - } - } - - - JHello() { - JLabel jlabel = new JLabel("Hello"); - jlabel.setFont(new Font("Monospaced", Font.PLAIN, 144)); - getContentPane().add(jlabel); - pack(); - } -} diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/src/build/tools/makeclasslist/MakeClasslist.java --- a/jdk/make/non-build-utils/src/build/tools/makeclasslist/MakeClasslist.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2003, 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. 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 build.tools.makeclasslist; - -import java.io.*; -import java.util.*; -import java.util.jar.*; - -/** Reads a set of files containing the output of java - -XX:+TraceClassLoadingPreorder runs. Finds all classes that were - loaded from the bootstrap class path by comparing the prefix of - the load path to the current JRE's java.home system property. - Prints the names of these classes to stdout. -*/ - -public class MakeClasslist { - public static void main(String[] args) throws IOException { - List classes = new ArrayList<>(); - String origJavaHome = System.getProperty("java.home"); - String javaHome = origJavaHome.toLowerCase(); - if (javaHome.endsWith("jre")) { - origJavaHome = origJavaHome.substring(0, origJavaHome.length() - 4); - javaHome = javaHome.substring(0, javaHome.length() - 4); - } - for (int i = 0; i < args.length; i++) { - try { - File file = new File(args[i]); - BufferedReader reader = new BufferedReader(new FileReader(file)); - String line = null; - while ((line = reader.readLine()) != null) { - StringTokenizer tok = new StringTokenizer(line, "[ \t\n\r\f"); - if (tok.hasMoreTokens()) { - String t = tok.nextToken(); - // Understand only "Loading" from -XX:+TraceClassLoadingPreorder. - // This ignores old "Loaded" from -verbose:class to force correct - // classlist generation on Mustang. - if (t.equals("Loading")) { - t = tok.nextToken(); - t = t.replace('.', '/'); - - // Check to make sure it came from the boot class path - if (tok.hasMoreTokens()) { - String tmp = tok.nextToken(); - if (tmp.equals("from")) { - if (tok.hasMoreTokens()) { - tmp = tok.nextToken().toLowerCase(); - // System.err.println("Loaded " + t + " from " + tmp); - if (tmp.startsWith(javaHome)) { - // OK, remember this class for later - classes.add(t); - } - } - } - } - } - } - } - } catch (IOException e) { - System.err.println("Error reading file " + args[i]); - throw(e); - } - } - - Set seenClasses = new HashSet<>(); - - for (String str : classes) { - if (seenClasses.add(str)) { - System.out.println(str); - } - } - - // Try to complete certain packages - // Note: not using this new code yet; need to consider whether the - // footprint increase is worth any startup gains - // Note also that the packages considered below for completion are - // (obviously) platform-specific - // JarFile rtJar = new JarFile(origJavaHome + File.separator + - // "jre" + File.separator + - // "lib" + File.separator + - // "rt.jar"); - // completePackage(seenClasses, rtJar, "java/awt"); - // completePackage(seenClasses, rtJar, "sun/awt"); - // completePackage(seenClasses, rtJar, "sun/awt/X11"); - // completePackage(seenClasses, rtJar, "java/awt/im/spi"); - // completePackage(seenClasses, rtJar, "java/lang"); - } - - private static void completePackage(Set seenClasses, - JarFile jar, - String packageName) { - int len = packageName.length(); - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - String name = entry.getName(); - if (name.startsWith(packageName) && - name.endsWith(".class") && - name.lastIndexOf('/') == len) { - // Trim ".class" from end - name = name.substring(0, name.length() - 6); - if (seenClasses.add(name)) { - System.out.println(name); - } - } - } - } -} diff -r b050dcca193f -r 9b3a9d72f07b jdk/make/non-build-utils/src/build/tools/makeclasslist/makeClasslist.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/non-build-utils/src/build/tools/makeclasslist/makeClasslist.js Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,62 @@ +/* + * 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. 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. + */ + +/** + * This tool is used to help create the class list for class data sharing. + * + * The classlist is produced internally by first running a select number of + * startup benchmarks with the -XX:DumpLoadedClassList= option, then + * running this tool in the following fashion to produce a complete classlist: + * + * jjs -scripting makeClasslist.js -- list1 list2 list3 > classlist.platform + * + * The lists should be listed in roughly smallest to largest order based on + * application size. + * + * After generating the classlist it's necessary to add a checksum (using + * AddJsum.java) before checking it into the workspace as the corresponding + * platform-specific classlist, such as make/data/classlist/classlist.linux + */ +"use strict"; +var classlist = []; +var seenClasses = {}; + +for (var a in $ARG) { + var arg = $ARG[a]; + + var classes = readFully(arg).replace(/[\r\n]+/g, "\n").split("\n"); + + for (var c in classes) { + var clazz = classes[c]; + if (clazz !== "" && seenClasses[clazz] === undefined) { + seenClasses[clazz] = clazz; + classlist.push(clazz); + } + } +} + +for (c in classlist) { + print(classlist[c]); +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java --- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Wed Jul 05 20:41:30 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 @@ -31,6 +31,7 @@ import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import sun.net.SocksProxy; +import sun.net.spi.DefaultProxySelector; import sun.net.www.ParseUtil; /* import org.ietf.jgss.*; */ @@ -69,12 +70,21 @@ server = ad.getHostString(); serverPort = ad.getPort(); } + useV4 = useV4(proxy); } void setV4() { useV4 = true; } + private static boolean useV4(Proxy proxy) { + if (proxy instanceof SocksProxy + && ((SocksProxy)proxy).protocolVersion() == 4) { + return true; + } + return DefaultProxySelector.socksProxyVersion() == 4; + } + private synchronized void privilegedConnect(final String host, final int port, final int timeout) @@ -398,11 +408,7 @@ // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); - if (p instanceof SocksProxy) { - if (((SocksProxy)p).protocolVersion() == 4) { - useV4 = true; - } - } + useV4 = useV4(p); // Connects to the SOCKS server try { @@ -715,11 +721,7 @@ // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); - if (p instanceof SocksProxy) { - if (((SocksProxy)p).protocolVersion() == 4) { - useV4 = true; - } - } + useV4 = useV4(p); // Connects to the SOCKS server try { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/AccessControlContext.java --- a/jdk/src/java.base/share/classes/java/security/AccessControlContext.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/AccessControlContext.java Wed Jul 05 20:41:30 2017 +0200 @@ -76,7 +76,7 @@ public final class AccessControlContext { - private ProtectionDomain context[]; + private ProtectionDomain[] context; // isPrivileged and isAuthorized are referenced by the VM - do not remove // or change their names private boolean isPrivileged; @@ -89,13 +89,13 @@ private DomainCombiner combiner = null; // limited privilege scope - private Permission permissions[]; + private Permission[] permissions; private AccessControlContext parent; private boolean isWrapped; // is constrained by limited privilege scope? private boolean isLimited; - private ProtectionDomain limitedContext[]; + private ProtectionDomain[] limitedContext; private static boolean debugInit = false; private static Debug debug = null; @@ -123,7 +123,7 @@ * changes to the array will not affect this AccessControlContext. * @throws NullPointerException if {@code context} is {@code null} */ - public AccessControlContext(ProtectionDomain context[]) + public AccessControlContext(ProtectionDomain[] context) { if (context.length == 0) { this.context = null; @@ -282,7 +282,7 @@ * package private constructor for AccessController.getContext() */ - AccessControlContext(ProtectionDomain context[], + AccessControlContext(ProtectionDomain[] context, boolean isPrivileged) { this.context = context; @@ -643,7 +643,7 @@ /* * Combine the current (stack) and assigned domains. */ - private static ProtectionDomain[] combine(ProtectionDomain[]current, + private static ProtectionDomain[] combine(ProtectionDomain[] current, ProtectionDomain[] assigned) { // current could be null if only system code is on the stack; @@ -666,7 +666,7 @@ int n = (skipAssigned) ? 0 : assigned.length; // now we combine both of them, and create a new context - ProtectionDomain pd[] = new ProtectionDomain[slen + n]; + ProtectionDomain[] pd = new ProtectionDomain[slen + n]; // first copy in the assigned context domains, no need to compress if (!skipAssigned) { @@ -695,7 +695,7 @@ } else if (skipAssigned && n == slen) { return current; } - ProtectionDomain tmp[] = new ProtectionDomain[n]; + ProtectionDomain[] tmp = new ProtectionDomain[n]; System.arraycopy(pd, 0, tmp, 0, n); pd = tmp; } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/CodeSource.java --- a/jdk/src/java.base/share/classes/java/security/CodeSource.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java Wed Jul 05 20:41:30 2017 +0200 @@ -65,7 +65,7 @@ /* * The code signers. Certificate chains are concatenated. */ - private transient java.security.cert.Certificate certs[] = null; + private transient java.security.cert.Certificate[] certs = null; // cached SocketPermission used for matchLocation private transient SocketPermission sp; @@ -91,7 +91,7 @@ * @param certs the certificate(s). It may be null. The contents of the * array are copied to protect against subsequent modification. */ - public CodeSource(URL url, java.security.cert.Certificate certs[]) { + public CodeSource(URL url, java.security.cert.Certificate[] certs) { this.location = url; if (url != null) { this.locationNoFragString = URLUtil.urlNoFragString(url); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/Permissions.java --- a/jdk/src/java.base/share/classes/java/security/Permissions.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/Permissions.java Wed Jul 05 20:41:30 2017 +0200 @@ -289,9 +289,9 @@ if (unresolvedPerms == null) return null; - java.security.cert.Certificate certs[] = null; + java.security.cert.Certificate[] certs = null; - Object signers[] = p.getClass().getSigners(); + Object[] signers = p.getClass().getSigners(); int n = 0; if (signers != null) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/SecureRandom.java --- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java Wed Jul 05 20:41:30 2017 +0200 @@ -69,7 +69,7 @@ * *
  *      SecureRandom random = new SecureRandom();
- *      byte bytes[] = new byte[20];
+ *      byte[] bytes = new byte[20];
  *      random.nextBytes(bytes);
  * 
* @@ -77,7 +77,7 @@ * to generate a given number of seed bytes (to seed other random number * generators, for example): *
- *      byte seed[] = random.generateSeed(20);
+ *      byte[] seed = random.generateSeed(20);
  * 
* * Note: Depending on the implementation, the {@code generateSeed} and @@ -186,7 +186,7 @@ * * @param seed the seed. */ - public SecureRandom(byte seed[]) { + public SecureRandom(byte[] seed) { super(0); getDefaultPRNG(true, seed); } @@ -486,7 +486,7 @@ @Override final protected int next(int numBits) { int numBytes = (numBits+7)/8; - byte b[] = new byte[numBytes]; + byte[] b = new byte[numBytes]; int next = 0; nextBytes(b); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/UnresolvedPermission.java --- a/jdk/src/java.base/share/classes/java/security/UnresolvedPermission.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/UnresolvedPermission.java Wed Jul 05 20:41:30 2017 +0200 @@ -130,7 +130,7 @@ */ private String actions; - private transient java.security.cert.Certificate certs[]; + private transient java.security.cert.Certificate[] certs; /** * Creates a new UnresolvedPermission containing the permission @@ -152,7 +152,7 @@ public UnresolvedPermission(String type, String name, String actions, - java.security.cert.Certificate certs[]) + java.security.cert.Certificate[] certs) { super(type); @@ -224,7 +224,7 @@ * try and resolve this permission using the class loader of the permission * that was passed in. */ - Permission resolve(Permission p, java.security.cert.Certificate certs[]) { + Permission resolve(Permission p, java.security.cert.Certificate[] certs) { if (this.certs != null) { // if p wasn't signed, we don't have a match if (certs == null) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java --- a/jdk/src/java.base/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java Wed Jul 05 20:41:30 2017 +0200 @@ -54,7 +54,7 @@ private final BigInteger primeExponentP; private final BigInteger primeExponentQ; private final BigInteger crtCoefficient; - private final RSAOtherPrimeInfo otherPrimeInfo[]; + private final RSAOtherPrimeInfo[] otherPrimeInfo; /** * Creates a new {@code RSAMultiPrimePrivateCrtKeySpec} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/util/ArrayList.java --- a/jdk/src/java.base/share/classes/java/util/ArrayList.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java Wed Jul 05 20:41:30 2017 +0200 @@ -178,7 +178,8 @@ public ArrayList(Collection c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { - // c.toArray might (incorrectly) not return Object[] (see 6260652) + // defend against c.toArray (incorrectly) not returning Object[] + // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/util/Arrays.java --- a/jdk/src/java.base/share/classes/java/util/Arrays.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Wed Jul 05 20:41:30 2017 +0200 @@ -3820,7 +3820,7 @@ @Override public Object[] toArray() { - return a.clone(); + return Arrays.copyOf(a, a.length, Object[].class); } @Override diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/util/Vector.java --- a/jdk/src/java.base/share/classes/java/util/Vector.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/Vector.java Wed Jul 05 20:41:30 2017 +0200 @@ -174,7 +174,8 @@ public Vector(Collection c) { elementData = c.toArray(); elementCount = elementData.length; - // c.toArray might (incorrectly) not return Object[] (see 6260652) + // defend against c.toArray (incorrectly) not returning Object[] + // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, elementCount, Object[].class); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java --- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Wed Jul 05 20:41:30 2017 +0200 @@ -134,7 +134,8 @@ elements = ((CopyOnWriteArrayList)c).getArray(); else { elements = c.toArray(); - // c.toArray might (incorrectly) not return Object[] (see 6260652) + // defend against c.toArray (incorrectly) not returning Object[] + // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) if (elements.getClass() != Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java --- a/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java Wed Jul 05 20:41:30 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, 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 @@ -106,6 +106,15 @@ } } + public static int socksProxyVersion() { + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override public Integer run() { + return NetProperties.getInteger(SOCKS_PROXY_VERSION, 5); + } + }); + } + /** * How to deal with "non proxy hosts": * since we do have to generate a pattern we don't want to do that if @@ -302,8 +311,7 @@ saddr = InetSocketAddress.createUnresolved(phost, pport); // Socks is *always* the last on the list. if (j == (props[i].length - 1)) { - int version = NetProperties.getInteger(SOCKS_PROXY_VERSION, 5).intValue(); - return SocksProxy.create(saddr, version); + return SocksProxy.create(saddr, socksProxyVersion()); } else { return new Proxy(Proxy.Type.HTTP, saddr); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/pkcs/PKCS7.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS7.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS7.java Wed Jul 05 20:41:30 2017 +0200 @@ -507,7 +507,7 @@ // certificates (optional) if (certificates != null && certificates.length != 0) { // cast to X509CertImpl[] since X509CertImpl implements DerEncoder - X509CertImpl implCerts[] = new X509CertImpl[certificates.length]; + X509CertImpl[] implCerts = new X509CertImpl[certificates.length]; for (int i = 0; i < certificates.length; i++) { if (certificates[i] instanceof X509CertImpl) implCerts[i] = (X509CertImpl) certificates[i]; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed Jul 05 20:41:30 2017 +0200 @@ -78,7 +78,7 @@ * data is stored and transmitted losslessly, but no knowledge * about this particular algorithm is available. */ - private PKCS8Key (AlgorithmId algid, byte key []) + private PKCS8Key (AlgorithmId algid, byte[] key) throws InvalidKeyException { this.algid = algid; this.key = key; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java --- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Wed Jul 05 20:41:30 2017 +0200 @@ -154,28 +154,28 @@ private static final Debug debug = Debug.getInstance("pkcs12"); - private static final int keyBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; - private static final int certBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; - private static final int secretBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 5}; + private static final int[] keyBag = {1, 2, 840, 113549, 1, 12, 10, 1, 2}; + private static final int[] certBag = {1, 2, 840, 113549, 1, 12, 10, 1, 3}; + private static final int[] secretBag = {1, 2, 840, 113549, 1, 12, 10, 1, 5}; - private static final int pkcs9Name[] = {1, 2, 840, 113549, 1, 9, 20}; - private static final int pkcs9KeyId[] = {1, 2, 840, 113549, 1, 9, 21}; + private static final int[] pkcs9Name = {1, 2, 840, 113549, 1, 9, 20}; + private static final int[] pkcs9KeyId = {1, 2, 840, 113549, 1, 9, 21}; - private static final int pkcs9certType[] = {1, 2, 840, 113549, 1, 9, 22, 1}; + private static final int[] pkcs9certType = {1, 2, 840, 113549, 1, 9, 22, 1}; - private static final int pbeWithSHAAnd40BitRC2CBC[] = + private static final int[] pbeWithSHAAnd40BitRC2CBC = {1, 2, 840, 113549, 1, 12, 1, 6}; - private static final int pbeWithSHAAnd3KeyTripleDESCBC[] = + private static final int[] pbeWithSHAAnd3KeyTripleDESCBC = {1, 2, 840, 113549, 1, 12, 1, 3}; - private static final int pbes2[] = {1, 2, 840, 113549, 1, 5, 13}; + private static final int[] pbes2 = {1, 2, 840, 113549, 1, 5, 13}; // TODO: temporary Oracle OID /* * { joint-iso-itu-t(2) country(16) us(840) organization(1) oracle(113894) * jdk(746875) crypto(1) id-at-trustedKeyUsage(1) } */ - private static final int TrustedKeyUsage[] = + private static final int[] TrustedKeyUsage = {2, 16, 840, 1, 113894, 746875, 1, 1}; - private static final int AnyExtendedKeyUsage[] = {2, 5, 29, 37, 0}; + private static final int[] AnyExtendedKeyUsage = {2, 5, 29, 37, 0}; private static ObjectIdentifier PKCS8ShroudedKeyBag_OID; private static ObjectIdentifier CertBag_OID; @@ -243,7 +243,7 @@ // A private key entry and its supporting certificate chain private static class PrivateKeyEntry extends KeyEntry { byte[] protectedPrivKey; - Certificate chain[]; + Certificate[] chain; }; // A secret key diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/AuthPolicyFile.java --- a/jdk/src/java.base/share/classes/sun/security/provider/AuthPolicyFile.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/AuthPolicyFile.java Wed Jul 05 20:41:30 2017 +0200 @@ -403,7 +403,7 @@ debug.println(" "+perm); } } catch (ClassNotFoundException cnfe) { - Certificate certs[]; + Certificate[] certs; if (pe.signedBy != null) { certs = getCertificates(keyStore, pe.signedBy); } else { @@ -623,7 +623,7 @@ init(); } - final CodeSource codesource[] = {null}; + final CodeSource[] codesource = {null}; codesource[0] = canonicalizeCodebase(cs, true); @@ -666,7 +666,7 @@ // now see if any of the keys are trusted ids. if (!ignoreIdentityScope) { - Certificate certs[] = codesource[0].getCertificates(); + Certificate[] certs = codesource[0].getCertificates(); if (certs != null) { for (int k=0; k < certs.length; k++) { if (aliasMapping.get(certs[k]) == null && diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java --- a/jdk/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java Wed Jul 05 20:41:30 2017 +0200 @@ -237,7 +237,7 @@ BigInteger offset = ONE; /* Step 11 */ for (counter = 0; counter < 4*valueL; counter++) { - BigInteger V[] = new BigInteger[n + 1]; + BigInteger[] V = new BigInteger[n + 1]; /* Step 11.1 */ for (int j = 0; j <= n; j++) { BigInteger J = BigInteger.valueOf(j); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java --- a/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java Wed Jul 05 20:41:30 2017 +0200 @@ -82,7 +82,7 @@ private static class KeyEntry { Date date; // the creation date of this entry byte[] protectedPrivKey; - Certificate chain[]; + Certificate[] chain; }; // Trusted certificates @@ -604,7 +604,7 @@ * the keystore (such as deleting or modifying key or * certificate entries). */ - byte digest[] = md.digest(); + byte[] digest = md.digest(); dos.write(digest); dos.flush(); @@ -770,9 +770,8 @@ * with */ if (password != null) { - byte computed[], actual[]; - computed = md.digest(); - actual = new byte[computed.length]; + byte[] computed = md.digest(); + byte[] actual = new byte[computed.length]; dis.readFully(actual); for (int i = 0; i < computed.length; i++) { if (computed[i] != actual[i]) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java --- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java Wed Jul 05 20:41:30 2017 +0200 @@ -795,7 +795,7 @@ // an unresolved permission which will be resolved // when implies is called // Add it to entry - Certificate certs[]; + Certificate[] certs; if (pe.signedBy != null) { certs = getCertificates(keyStore, pe.signedBy, @@ -817,7 +817,7 @@ debug.println(" "+perm); } } catch (ClassNotFoundException cnfe) { - Certificate certs[]; + Certificate[] certs; if (pe.signedBy != null) { certs = getCertificates(keyStore, pe.signedBy, @@ -2032,7 +2032,7 @@ * * @serial */ - private Certificate certs[]; + private Certificate[] certs; /** * Creates a new SelfPermission containing the permission @@ -2048,7 +2048,7 @@ * certificate first and the (root) certificate authority last). */ public SelfPermission(String type, String name, String actions, - Certificate certs[]) + Certificate[] certs) { super(type); if (type == null) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java --- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java Wed Jul 05 20:41:30 2017 +0200 @@ -1353,7 +1353,7 @@ } } - public static void main(String arg[]) throws Exception { + public static void main(String[] arg) throws Exception { try (FileReader fr = new FileReader(arg[0]); FileWriter fw = new FileWriter(arg[1])) { PolicyParser pp = new PolicyParser(true); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java --- a/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java Wed Jul 05 20:41:30 2017 +0200 @@ -85,7 +85,7 @@ * * @param seed the seed. */ - private SecureRandom(byte seed[]) { + private SecureRandom(byte[] seed) { init(seed); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/ByteBufferInputStream.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/ByteBufferInputStream.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ByteBufferInputStream.java Wed Jul 05 20:41:30 2017 +0200 @@ -70,7 +70,7 @@ * Increments position(). */ @Override - public int read(byte b[]) throws IOException { + public int read(byte[] b) throws IOException { if (bb == null) { throw new IOException("read on a closed InputStream"); @@ -85,7 +85,7 @@ * Increments position(). */ @Override - public int read(byte b[], int off, int len) throws IOException { + public int read(byte[] b, int off, int len) throws IOException { if (bb == null) { throw new IOException("read on a closed InputStream"); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Wed Jul 05 20:41:30 2017 +0200 @@ -810,7 +810,7 @@ String alias = null; int keytypesTmpSize = keytypesTmp.size(); if (keytypesTmpSize != 0) { - String keytypes[] = + String[] keytypes = keytypesTmp.toArray(new String[keytypesTmpSize]); if (conn != null) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java Wed Jul 05 20:41:30 2017 +0200 @@ -48,7 +48,7 @@ * This value may be empty if it was included in the * client's certificate ... */ - private byte dh_Yc[]; // 1 to 2^16 -1 bytes + private byte[] dh_Yc; // 1 to 2^16 -1 bytes BigInteger getClientPublicKey() { return dh_Yc == null ? null : new BigInteger(1, dh_Yc); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java Wed Jul 05 20:41:30 2017 +0200 @@ -146,7 +146,7 @@ byte[] getBytes8() throws IOException { int len = getInt8(); verifyLength(len); - byte b[] = new byte[len]; + byte[] b = new byte[len]; read(b); return b; @@ -155,7 +155,7 @@ public byte[] getBytes16() throws IOException { int len = getInt16(); verifyLength(len); - byte b[] = new byte[len]; + byte[] b = new byte[len]; read(b); return b; @@ -164,7 +164,7 @@ byte[] getBytes24() throws IOException { int len = getInt24(); verifyLength(len); - byte b[] = new byte[len]; + byte[] b = new byte[len]; read(b); return b; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Wed Jul 05 20:41:30 2017 +0200 @@ -689,8 +689,8 @@ static final class RSA_ServerKeyExchange extends ServerKeyExchange { - private byte rsa_modulus[]; // 1 to 2^16 - 1 bytes - private byte rsa_exponent[]; // 1 to 2^16 - 1 bytes + private byte[] rsa_modulus; // 1 to 2^16 - 1 bytes + private byte[] rsa_exponent; // 1 to 2^16 - 1 bytes private Signature signature; private byte[] signatureBytes; @@ -698,7 +698,7 @@ /* * Hash the nonces and the ephemeral RSA public key. */ - private void updateSignature(byte clntNonce[], byte svrNonce[]) + private void updateSignature(byte[] clntNonce, byte[] svrNonce) throws SignatureException { int tmp; @@ -827,11 +827,11 @@ private final static boolean dhKeyExchangeFix = Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true); - private byte dh_p []; // 1 to 2^16 - 1 bytes - private byte dh_g []; // 1 to 2^16 - 1 bytes - private byte dh_Ys []; // 1 to 2^16 - 1 bytes + private byte[] dh_p; // 1 to 2^16 - 1 bytes + private byte[] dh_g; // 1 to 2^16 - 1 bytes + private byte[] dh_Ys; // 1 to 2^16 - 1 bytes - private byte signature []; + private byte[] signature; // protocol version being established using this ServerKeyExchange message ProtocolVersion protocolVersion; @@ -857,8 +857,8 @@ * with the cert chain which was sent ... for DHE_DSS and DHE_RSA * key exchange. (Constructor called by server.) */ - DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[], - byte svrNonce[], SecureRandom sr, + DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte[] clntNonce, + byte[] svrNonce, SecureRandom sr, SignatureAndHashAlgorithm signAlgorithm, ProtocolVersion protocolVersion) throws GeneralSecurityException { @@ -913,7 +913,7 @@ * DHE_DSS or DHE_RSA key exchange. (Called by client.) */ DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey, - byte clntNonce[], byte svrNonce[], int messageSize, + byte[] clntNonce, byte[] svrNonce, int messageSize, Collection localSupportedSignAlgs, ProtocolVersion protocolVersion) throws IOException, GeneralSecurityException { @@ -948,7 +948,7 @@ } // read the signature - byte signature[]; + byte[] signature; if (dhKeyExchangeFix) { signature = input.getBytes16(); } else { @@ -1004,8 +1004,8 @@ /* * Update sig with nonces and Diffie-Hellman public key. */ - private void updateSignature(Signature sig, byte clntNonce[], - byte svrNonce[]) throws SignatureException { + private void updateSignature(Signature sig, byte[] clntNonce, + byte[] svrNonce) throws SignatureException { int tmp; sig.update(clntNonce); @@ -1268,8 +1268,8 @@ } } - private void updateSignature(Signature sig, byte clntNonce[], - byte svrNonce[]) throws SignatureException { + private void updateSignature(Signature sig, byte[] clntNonce, + byte[] svrNonce) throws SignatureException { sig.update(clntNonce); sig.update(svrNonce); @@ -1334,7 +1334,7 @@ * DER encoded distinguished name. * TLS requires that its not longer than 65535 bytes. */ - byte name[]; + byte[] name; DistinguishedName(HandshakeInStream input) throws IOException { name = input.getBytes16(); @@ -1411,8 +1411,8 @@ private final static byte[] TYPES_ECC = { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign }; - byte types []; // 1 to 255 types - DistinguishedName authorities []; // 3 to 2^16 - 1 + byte[] types; // 1 to 255 types + DistinguishedName[] authorities; // 3 to 2^16 - 1 // ... "3" because that's the smallest DER-encoded X500 DN // protocol version being established using this CertificateRequest message @@ -1424,7 +1424,7 @@ // length of supported_signature_algorithms private int algorithmsLen; - CertificateRequest(X509Certificate ca[], KeyExchange keyExchange, + CertificateRequest(X509Certificate[] ca, KeyExchange keyExchange, Collection signAlgs, ProtocolVersion protocolVersion) throws IOException { @@ -2063,7 +2063,7 @@ if (protocolVersion.useTLS10PlusSpec()) { // TLS 1.0+ try { - byte [] seed; + byte[] seed; String prfAlg; PRF prf; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java Wed Jul 05 20:41:30 2017 +0200 @@ -119,7 +119,7 @@ } } - public void putBytes16(byte b[]) throws IOException { + public void putBytes16(byte[] b) throws IOException { if (b == null) { putInt16(0); } else { @@ -128,7 +128,7 @@ } } - void putBytes24(byte b[]) throws IOException { + void putBytes24(byte[] b) throws IOException { if (b == null) { putInt24(0); } else { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/MAC.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/MAC.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/MAC.java Wed Jul 05 20:41:30 2017 +0200 @@ -52,7 +52,7 @@ final static MAC TLS_NULL = new MAC(false); // Value of the null MAC is fixed - private static final byte nullMAC[] = new byte[0]; + private static final byte[] nullMAC = new byte[0]; // internal identifier for the MAC algorithm private final MacAlg macAlg; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/RandomCookie.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/RandomCookie.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/RandomCookie.java Wed Jul 05 20:41:30 2017 +0200 @@ -38,7 +38,7 @@ */ final class RandomCookie { - byte random_bytes[]; // exactly 32 bytes + byte[] random_bytes; // exactly 32 bytes RandomCookie(SecureRandom generator) { long temp = System.currentTimeMillis() / 1000; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Wed Jul 05 20:41:30 2017 +0200 @@ -986,7 +986,7 @@ ClientKeyExchangeService.find(keyExchange.name) == null) { CertificateRequest m4; - X509Certificate caCerts[]; + X509Certificate[] caCerts; Collection localSignAlgs = null; if (protocolVersion.useTLS12PlusSpec()) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java Wed Jul 05 20:41:30 2017 +0200 @@ -43,7 +43,7 @@ class SessionId { static int MAX_LENGTH = 32; - private byte sessionId []; // max 32 bytes + private byte[] sessionId; // max 32 bytes /** Constructs a new session ID ... perhaps for a rejoinable session */ SessionId (boolean isRejoinable, SecureRandom generator) @@ -56,7 +56,7 @@ } /** Constructs a session ID from a byte array (max size 32 bytes) */ - SessionId (byte sessionId []) + SessionId (byte[] sessionId) { this.sessionId = sessionId; } /** Returns the length of the ID, in bytes */ @@ -64,7 +64,7 @@ { return sessionId.length; } /** Returns the bytes in the ID. May be an empty array. */ - byte [] getId () + byte[] getId () { return sessionId.clone (); } @@ -106,7 +106,7 @@ return false; SessionId s = (SessionId) obj; - byte b [] = s.getId (); + byte[] b = s.getId (); if (b.length != sessionId.length) return false; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java --- a/jdk/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -94,13 +94,13 @@ } @Override - public void checkClientTrusted(X509Certificate chain[], String authType) + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { checkTrusted(chain, authType, (Socket)null, true); } @Override - public void checkServerTrusted(X509Certificate chain[], String authType) + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { checkTrusted(chain, authType, (Socket)null, false); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/util/ManifestDigester.java --- a/jdk/src/java.base/share/classes/sun/security/util/ManifestDigester.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/util/ManifestDigester.java Wed Jul 05 20:41:30 2017 +0200 @@ -37,7 +37,7 @@ public static final String MF_MAIN_ATTRS = "Manifest-Main-Attributes"; /** the raw bytes of the manifest */ - private byte rawBytes[]; + private byte[] rawBytes; /** the offset/length pair for a section */ private HashMap entries; // key is a UTF-8 string @@ -107,7 +107,7 @@ return false; } - public ManifestDigester(byte bytes[]) + public ManifestDigester(byte[] bytes) { rawBytes = bytes; entries = new HashMap<>(); @@ -181,7 +181,7 @@ } } - private boolean isNameAttr(byte bytes[], int start) + private boolean isNameAttr(byte[] bytes, int start) { return ((bytes[start] == 'N') || (bytes[start] == 'n')) && ((bytes[start+1] == 'a') || (bytes[start+1] == 'A')) && @@ -261,11 +261,10 @@ return e; } - public byte[] manifestDigest(MessageDigest md) - { - md.reset(); - md.update(rawBytes, 0, rawBytes.length); - return md.digest(); - } + public byte[] manifestDigest(MessageDigest md) { + md.reset(); + md.update(rawBytes, 0, rawBytes.length); + return md.digest(); + } } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java --- a/jdk/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java Wed Jul 05 20:41:30 2017 +0200 @@ -165,7 +165,7 @@ /** * update the digests for the digests we are interested in */ - public void update(byte buffer[], int off, int len) { + public void update(byte[] buffer, int off, int len) { if (skip) return; for (int i=0; i < digests.size(); i++) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java --- a/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java Wed Jul 05 20:41:30 2017 +0200 @@ -212,7 +212,7 @@ * Constructor, from an array of integers. * Validity check included. */ - public ObjectIdentifier (int values []) throws IOException + public ObjectIdentifier(int[] values) throws IOException { checkCount(values.length); checkFirstComponent(values[0]); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java --- a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jul 05 20:41:30 2017 +0200 @@ -55,7 +55,7 @@ private PKCS7 block; /** the raw bytes of the .SF file */ - private byte sfBytes[]; + private byte[] sfBytes; /** the name of the signature block file, uppercased and without * the extension (.DSA/.RSA/.EC) @@ -84,7 +84,7 @@ public SignatureFileVerifier(ArrayList signerCache, ManifestDigester md, String name, - byte rawBytes[]) + byte[] rawBytes) throws IOException, CertificateException { // new PKCS7() calls CertificateFactory.getInstance() @@ -129,7 +129,7 @@ * used to set the raw bytes of the .SF file when it * is external to the signature block file. */ - public void setSignatureFile(byte sfBytes[]) + public void setSignatureFile(byte[] sfBytes) { this.sfBytes = sfBytes; } @@ -511,7 +511,7 @@ * CodeSigner objects. We do this only *once* for a given * signature block file. */ - private CodeSigner[] getSigners(SignerInfo infos[], PKCS7 block) + private CodeSigner[] getSigners(SignerInfo[] infos, PKCS7 block) throws IOException, NoSuchAlgorithmException, SignatureException, CertificateException { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/AVA.java --- a/jdk/src/java.base/share/classes/sun/security/x509/AVA.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/AVA.java Wed Jul 05 20:41:30 2017 +0200 @@ -967,7 +967,7 @@ previousWhite = false; - byte valueBytes[] = null; + byte[] valueBytes = null; try { valueBytes = Character.toString(c).getBytes("UTF8"); } catch (IOException ie) { @@ -1051,7 +1051,7 @@ // using the hex format below. This will be used only // when the value is not a string type - byte data [] = value.toByteArray(); + byte[] data = value.toByteArray(); retval.append('#'); for (int i = 0; i < data.length; i++) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/AlgIdDSA.java --- a/jdk/src/java.base/share/classes/sun/security/x509/AlgIdDSA.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgIdDSA.java Wed Jul 05 20:41:30 2017 +0200 @@ -117,7 +117,7 @@ * @param q the DSS/DSA parameter "Q" * @param g the DSS/DSA parameter "G" */ - public AlgIdDSA (byte p [], byte q [], byte g []) + public AlgIdDSA (byte[] p, byte[] q, byte[] g) throws IOException { this (new BigInteger (1, p), diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java --- a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java Wed Jul 05 20:41:30 2017 +0200 @@ -648,12 +648,12 @@ /* * COMMON PUBLIC KEY TYPES */ - private static final int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; - private static final int DH_PKIX_data[] = { 1, 2, 840, 10046, 2, 1 }; - private static final int DSA_OIW_data[] = { 1, 3, 14, 3, 2, 12 }; - private static final int DSA_PKIX_data[] = { 1, 2, 840, 10040, 4, 1 }; - private static final int RSA_data[] = { 2, 5, 8, 1, 1 }; - private static final int RSAEncryption_data[] = + private static final int[] DH_data = { 1, 2, 840, 113549, 1, 3, 1 }; + private static final int[] DH_PKIX_data = { 1, 2, 840, 10046, 2, 1 }; + private static final int[] DSA_OIW_data = { 1, 3, 14, 3, 2, 12 }; + private static final int[] DSA_PKIX_data = { 1, 2, 840, 10040, 4, 1 }; + private static final int[] RSA_data = { 2, 5, 8, 1, 1 }; + private static final int[] RSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 1 }; public static final ObjectIdentifier DH_oid; @@ -674,27 +674,27 @@ /* * COMMON SIGNATURE ALGORITHMS */ - private static final int md2WithRSAEncryption_data[] = + private static final int[] md2WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 2 }; - private static final int md5WithRSAEncryption_data[] = + private static final int[] md5WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 4 }; - private static final int sha1WithRSAEncryption_data[] = + private static final int[] sha1WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 5 }; - private static final int sha1WithRSAEncryption_OIW_data[] = + private static final int[] sha1WithRSAEncryption_OIW_data = { 1, 3, 14, 3, 2, 29 }; - private static final int sha224WithRSAEncryption_data[] = + private static final int[] sha224WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 14 }; - private static final int sha256WithRSAEncryption_data[] = + private static final int[] sha256WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 11 }; - private static final int sha384WithRSAEncryption_data[] = + private static final int[] sha384WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 12 }; - private static final int sha512WithRSAEncryption_data[] = + private static final int[] sha512WithRSAEncryption_data = { 1, 2, 840, 113549, 1, 1, 13 }; - private static final int shaWithDSA_OIW_data[] = + private static final int[] shaWithDSA_OIW_data = { 1, 3, 14, 3, 2, 13 }; - private static final int sha1WithDSA_OIW_data[] = + private static final int[] sha1WithDSA_OIW_data = { 1, 3, 14, 3, 2, 27 }; - private static final int dsaWithSHA1_PKIX_data[] = + private static final int[] dsaWithSHA1_PKIX_data = { 1, 2, 840, 10040, 4, 3 }; public static final ObjectIdentifier md2WithRSAEncryption_oid; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java --- a/jdk/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java Wed Jul 05 20:41:30 2017 +0200 @@ -69,7 +69,7 @@ public static final String S_MIME_CA = "s_mime_ca"; public static final String OBJECT_SIGNING_CA = "object_signing_ca"; - private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 }; + private static final int[] CertType_data = { 2, 16, 840, 1, 113730, 1, 1 }; /** * Object identifier for the Netscape-Cert-Type extension. diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/OIDMap.java --- a/jdk/src/java.base/share/classes/sun/security/x509/OIDMap.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/OIDMap.java Wed Jul 05 20:41:30 2017 +0200 @@ -102,7 +102,7 @@ private static final String OCSPNOCHECK = ROOT + "." + OCSPNoCheckExtension.NAME; - private static final int NetscapeCertType_data[] = + private static final int[] NetscapeCertType_data = { 2, 16, 840, 1, 113730, 1, 1 }; /** Map ObjectIdentifier(oid) -> OIDInfo(info) */ diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java --- a/jdk/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java Wed Jul 05 20:41:30 2017 +0200 @@ -49,32 +49,32 @@ */ public class PKIXExtensions { // The object identifiers - private static final int AuthorityKey_data [] = { 2, 5, 29, 35 }; - private static final int SubjectKey_data [] = { 2, 5, 29, 14 }; - private static final int KeyUsage_data [] = { 2, 5, 29, 15 }; - private static final int PrivateKeyUsage_data [] = { 2, 5, 29, 16 }; - private static final int CertificatePolicies_data [] = { 2, 5, 29, 32 }; - private static final int PolicyMappings_data [] = { 2, 5, 29, 33 }; - private static final int SubjectAlternativeName_data [] = { 2, 5, 29, 17 }; - private static final int IssuerAlternativeName_data [] = { 2, 5, 29, 18 }; - private static final int SubjectDirectoryAttributes_data [] = { 2, 5, 29, 9 }; - private static final int BasicConstraints_data [] = { 2, 5, 29, 19 }; - private static final int NameConstraints_data [] = { 2, 5, 29, 30 }; - private static final int PolicyConstraints_data [] = { 2, 5, 29, 36 }; - private static final int CRLDistributionPoints_data [] = { 2, 5, 29, 31 }; - private static final int CRLNumber_data [] = { 2, 5, 29, 20 }; - private static final int IssuingDistributionPoint_data [] = { 2, 5, 29, 28 }; - private static final int DeltaCRLIndicator_data [] = { 2, 5, 29, 27 }; - private static final int ReasonCode_data [] = { 2, 5, 29, 21 }; - private static final int HoldInstructionCode_data [] = { 2, 5, 29, 23 }; - private static final int InvalidityDate_data [] = { 2, 5, 29, 24 }; - private static final int ExtendedKeyUsage_data [] = { 2, 5, 29, 37 }; - private static final int InhibitAnyPolicy_data [] = { 2, 5, 29, 54 }; - private static final int CertificateIssuer_data [] = { 2, 5, 29, 29 }; - private static final int AuthInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 1}; - private static final int SubjectInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 11}; - private static final int FreshestCRL_data [] = { 2, 5, 29, 46 }; - private static final int OCSPNoCheck_data [] = { 1, 3, 6, 1, 5, 5, 7, + private static final int[] AuthorityKey_data = { 2, 5, 29, 35 }; + private static final int[] SubjectKey_data = { 2, 5, 29, 14 }; + private static final int[] KeyUsage_data = { 2, 5, 29, 15 }; + private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 }; + private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 }; + private static final int[] PolicyMappings_data = { 2, 5, 29, 33 }; + private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 }; + private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 }; + private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 }; + private static final int[] BasicConstraints_data = { 2, 5, 29, 19 }; + private static final int[] NameConstraints_data = { 2, 5, 29, 30 }; + private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 }; + private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 }; + private static final int[] CRLNumber_data = { 2, 5, 29, 20 }; + private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 }; + private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 }; + private static final int[] ReasonCode_data = { 2, 5, 29, 21 }; + private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 }; + private static final int[] InvalidityDate_data = { 2, 5, 29, 24 }; + private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 }; + private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 }; + private static final int[] CertificateIssuer_data = { 2, 5, 29, 29 }; + private static final int[] AuthInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 1}; + private static final int[] SubjectInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 11}; + private static final int[] FreshestCRL_data = { 2, 5, 29, 46 }; + private static final int[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7, 48, 1, 5}; /** diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/X500Name.java --- a/jdk/src/java.base/share/classes/sun/security/x509/X500Name.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/X500Name.java Wed Jul 05 20:41:30 2017 +0200 @@ -1119,25 +1119,25 @@ * Includes all those specified in RFC 5280 as MUST or SHOULD * be recognized */ - private static final int commonName_data[] = { 2, 5, 4, 3 }; - private static final int SURNAME_DATA[] = { 2, 5, 4, 4 }; - private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 }; - private static final int countryName_data[] = { 2, 5, 4, 6 }; - private static final int localityName_data[] = { 2, 5, 4, 7 }; - private static final int stateName_data[] = { 2, 5, 4, 8 }; - private static final int streetAddress_data[] = { 2, 5, 4, 9 }; - private static final int orgName_data[] = { 2, 5, 4, 10 }; - private static final int orgUnitName_data[] = { 2, 5, 4, 11 }; - private static final int title_data[] = { 2, 5, 4, 12 }; - private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 }; - private static final int INITIALS_DATA[] = { 2, 5, 4, 43 }; - private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 }; - private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 }; + private static final int[] commonName_data = { 2, 5, 4, 3 }; + private static final int[] SURNAME_DATA = { 2, 5, 4, 4 }; + private static final int[] SERIALNUMBER_DATA = { 2, 5, 4, 5 }; + private static final int[] countryName_data = { 2, 5, 4, 6 }; + private static final int[] localityName_data = { 2, 5, 4, 7 }; + private static final int[] stateName_data = { 2, 5, 4, 8 }; + private static final int[] streetAddress_data = { 2, 5, 4, 9 }; + private static final int[] orgName_data = { 2, 5, 4, 10 }; + private static final int[] orgUnitName_data = { 2, 5, 4, 11 }; + private static final int[] title_data = { 2, 5, 4, 12 }; + private static final int[] GIVENNAME_DATA = { 2, 5, 4, 42 }; + private static final int[] INITIALS_DATA = { 2, 5, 4, 43 }; + private static final int[] GENERATIONQUALIFIER_DATA = { 2, 5, 4, 44 }; + private static final int[] DNQUALIFIER_DATA = { 2, 5, 4, 46 }; - private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; - private static final int DOMAIN_COMPONENT_DATA[] = + private static final int[] ipAddress_data = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; + private static final int[] DOMAIN_COMPONENT_DATA = { 0, 9, 2342, 19200300, 100, 1, 25 }; - private static final int userid_data[] = + private static final int[] userid_data = { 0, 9, 2342, 19200300, 100, 1, 1 }; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java --- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -1086,7 +1086,7 @@ throw new CRLException("Invalid DER-encoded CRL data"); signedCRL = val.toByteArray(); - DerValue seq[] = new DerValue[3]; + DerValue[] seq = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java --- a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java Wed Jul 05 20:41:30 2017 +0200 @@ -142,7 +142,8 @@ public IdentityArrayList(Collection c) { elementData = c.toArray(); size = elementData.length; - // c.toArray might (incorrectly) not return Object[] (see 6260652) + // defend against c.toArray (incorrectly) not returning Object[] + // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Wed Jul 05 20:41:30 2017 +0200 @@ -427,7 +427,7 @@ /* - public static void main(String args[]) throws Exception { + public static void main(String[] args) throws Exception { ServicePermission this_ = new ServicePermission(args[0], "accept"); ServicePermission that_ = diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -75,7 +75,7 @@ } GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name, - int lifetime, Oid mechs[], int usage) + int lifetime, Oid[] mechs, int usage) throws GSSException { init(gssManager); boolean defaultList = false; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -128,7 +128,7 @@ return new GSSNameImpl(this, nameStr, nameType); } - public GSSName createName(byte name[], Oid nameType) + public GSSName createName(byte[] name, Oid nameType) throws GSSException { return new GSSNameImpl(this, name, nameType); } @@ -138,7 +138,7 @@ return new GSSNameImpl(this, nameStr, nameType, mech); } - public GSSName createName(byte name[], Oid nameType, Oid mech) + public GSSName createName(byte[] name, Oid nameType, Oid mech) throws GSSException { return new GSSNameImpl(this, name, nameType, mech); } @@ -155,7 +155,7 @@ } public GSSCredential createCredential(GSSName aName, - int lifetime, Oid mechs[], int usage) + int lifetime, Oid[] mechs, int usage) throws GSSException { return wrap(new GSSCredentialImpl(this, aName, lifetime, mechs, usage)); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jul 05 20:41:30 2017 +0200 @@ -159,7 +159,7 @@ /** * Constructor for Krb5Context to import a previously exported context. */ - public Krb5Context(GSSCaller caller, byte [] interProcessToken) + public Krb5Context(GSSCaller caller, byte[] interProcessToken) throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "GSS Import Context not available"); @@ -905,7 +905,7 @@ * and verifyMIC care about the remote sequence number (peerSeqNumber). */ - public final byte[] wrap(byte inBuf[], int offset, int len, + public final byte[] wrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException { if (DEBUG) { System.out.println("Krb5Context.wrap: data=[" @@ -943,7 +943,7 @@ } } - public final int wrap(byte inBuf[], int inOffset, int len, + public final int wrap(byte[] inBuf, int inOffset, int len, byte[] outBuf, int outOffset, MessageProp msgProp) throws GSSException { @@ -977,7 +977,7 @@ } } - public final void wrap(byte inBuf[], int offset, int len, + public final void wrap(byte[] inBuf, int offset, int len, OutputStream os, MessageProp msgProp) throws GSSException { @@ -1032,7 +1032,7 @@ wrap(data, 0, data.length, os, msgProp); } - public final byte[] unwrap(byte inBuf[], int offset, int len, + public final byte[] unwrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException { @@ -1069,7 +1069,7 @@ return data; } - public final int unwrap(byte inBuf[], int inOffset, int len, + public final int unwrap(byte[] inBuf, int inOffset, int len, byte[] outBuf, int outOffset, MessageProp msgProp) throws GSSException { @@ -1141,7 +1141,7 @@ } } - public final byte[] getMIC(byte []inMsg, int offset, int len, + public final byte[] getMIC(byte[] inMsg, int offset, int len, MessageProp msgProp) throws GSSException { @@ -1166,7 +1166,7 @@ } } - private int getMIC(byte []inMsg, int offset, int len, + private int getMIC(byte[] inMsg, int offset, int len, byte[] outBuf, int outOffset, MessageProp msgProp) throws GSSException { @@ -1236,7 +1236,7 @@ getMIC(data, 0, data.length, os, msgProp); } - public final void verifyMIC(byte []inTok, int tokOffset, int tokLen, + public final void verifyMIC(byte[] inTok, int tokOffset, int tokLen, byte[] inMsg, int msgOffset, int msgLen, MessageProp msgProp) throws GSSException { @@ -1293,7 +1293,7 @@ * @param os the output token will be written to this stream * @exception GSSException */ - public final byte [] export() throws GSSException { + public final byte[] export() throws GSSException { throw new GSSException(GSSException.UNAVAILABLE, -1, "GSS Export Context not available"); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java Wed Jul 05 20:41:30 2017 +0200 @@ -265,7 +265,7 @@ /** * For apps that want simplicity and don't care about buffer copies. */ - public byte[] wrap(byte inBuf[], int offset, int len, + public byte[] wrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException; /** @@ -275,7 +275,7 @@ * * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext * - public int wrap(byte inBuf[], int inOffset, int len, + public int wrap(byte[] inBuf, int inOffset, int len, byte[] outBuf, int outOffset, MessageProp msgProp) throws GSSException; @@ -292,7 +292,7 @@ * * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext * - public void wrap(byte inBuf[], int offset, int len, + public void wrap(byte[] inBuf, int offset, int len, OutputStream os, MessageProp msgProp) throws GSSException; */ @@ -314,7 +314,7 @@ /** * For apps that want simplicity and don't care about buffer copies. */ - public byte[] unwrap(byte inBuf[], int offset, int len, + public byte[] unwrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException; /** @@ -324,7 +324,7 @@ * * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext * - public int unwrap(byte inBuf[], int inOffset, int len, + public int unwrap(byte[] inBuf, int inOffset, int len, byte[] outBuf, int outOffset, MessageProp msgProp) throws GSSException; @@ -356,7 +356,7 @@ MessageProp msgProp) throws GSSException; - public byte[] getMIC(byte []inMsg, int offset, int len, + public byte[] getMIC(byte[] inMsg, int offset, int len, MessageProp msgProp) throws GSSException; /** @@ -372,7 +372,7 @@ public void verifyMIC(InputStream is, InputStream msgStr, MessageProp mProp) throws GSSException; - public void verifyMIC(byte []inTok, int tokOffset, int tokLen, + public void verifyMIC(byte[] inTok, int tokOffset, int tokLen, byte[] inMsg, int msgOffset, int msgLen, MessageProp msgProp) throws GSSException; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java Wed Jul 05 20:41:30 2017 +0200 @@ -372,7 +372,7 @@ } return cStub.wrap(pContext, data, msgProp); } - public void wrap(byte inBuf[], int offset, int len, + public void wrap(byte[] inBuf, int offset, int len, OutputStream os, MessageProp msgProp) throws GSSException { try { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java Wed Jul 05 20:41:30 2017 +0200 @@ -78,7 +78,7 @@ if (DEBUG) err.printStackTrace(); return null; } - String gssLibs[] = new String[0]; + String[] gssLibs = new String[0]; String defaultLib = System.getProperty(LIB_PROP); if (defaultLib == null || defaultLib.trim().equals("")) { String osname = System.getProperty("os.name"); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java Wed Jul 05 20:41:30 2017 +0200 @@ -568,7 +568,7 @@ temp.putInteger(bint); bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp); temp = new DerOutputStream(); - DerValue der[] = new DerValue[nameStrings.length]; + DerValue[] der = new DerValue[nameStrings.length]; for (int i = 0; i < nameStrings.length; i++) { der[i] = new KerberosString(nameStrings[i]).toDerValue(); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Authenticator.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Authenticator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Authenticator.java Wed Jul 05 20:41:30 2017 +0200 @@ -198,7 +198,7 @@ if (authorizationData != null) { v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x08), authorizationData.asn1Encode())); } - DerValue der[] = new DerValue[v.size()]; + DerValue[] der = new DerValue[v.size()]; v.copyInto(der); temp = new DerOutputStream(); temp.putSequence(der); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/AuthorizationData.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/AuthorizationData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/AuthorizationData.java Wed Jul 05 20:41:30 2017 +0200 @@ -120,7 +120,7 @@ */ public byte[] asn1Encode() throws Asn1Exception, IOException { DerOutputStream bytes = new DerOutputStream(); - DerValue der[] = new DerValue[entry.length]; + DerValue[] der = new DerValue[entry.length]; for (int i = 0; i < entry.length; i++) { der[i] = new DerValue(entry[i].asn1Encode()); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncAPRepPart.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncAPRepPart.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncAPRepPart.java Wed Jul 05 20:41:30 2017 +0200 @@ -151,7 +151,7 @@ v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), temp.toByteArray())); } - DerValue der[] = new DerValue[v.size()]; + DerValue[] der = new DerValue[v.size()]; v.copyInto(der); temp = new DerOutputStream(); temp.putSequence(der); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKrbCredPart.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKrbCredPart.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKrbCredPart.java Wed Jul 05 20:41:30 2017 +0200 @@ -129,7 +129,7 @@ subDer = der.getData().getDerValue(); if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x00) { - DerValue derValues[] = subDer.getData().getSequence(1); + DerValue[] derValues = subDer.getData().getSequence(1); ticketInfo = new KrbCredInfo[derValues.length]; for (int i = 0; i < derValues.length; i++) { ticketInfo[i] = new KrbCredInfo(derValues[i]); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddresses.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddresses.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddresses.java Wed Jul 05 20:41:30 2017 +0200 @@ -98,8 +98,8 @@ throw new KrbException(Krb5.KRB_ERR_GENERIC, "Bad name"); String host = components[1]; - InetAddress addr[] = InetAddress.getAllByName(host); - HostAddress hAddrs[] = new HostAddress[addr.length]; + InetAddress[] addr = InetAddress.getAllByName(host); + HostAddress[] hAddrs = new HostAddress[addr.length]; for (int i = 0; i < addr.length; i++) { hAddrs[i] = new HostAddress(addr[i]); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java Wed Jul 05 20:41:30 2017 +0200 @@ -269,7 +269,7 @@ ticketsTemp.write(DerValue.tag_SequenceOf, temp); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), ticketsTemp.toByteArray())); } - DerValue der[] = new DerValue[v.size()]; + DerValue[] der = new DerValue[v.size()]; v.copyInto(der); temp = new DerOutputStream(); temp.putSequence(der); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KrbCredInfo.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KrbCredInfo.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KrbCredInfo.java Wed Jul 05 20:41:30 2017 +0200 @@ -172,7 +172,7 @@ } if (caddr != null) v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), caddr.asn1Encode())); - DerValue der[] = new DerValue[v.size()]; + DerValue[] der = new DerValue[v.size()]; v.copyInto(der); DerOutputStream out = new DerOutputStream(); out.putSequence(der); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java Wed Jul 05 20:41:30 2017 +0200 @@ -200,7 +200,7 @@ @Override public byte[] receive() throws IOException { - byte ibuf[] = new byte[bufSize]; + byte[] ibuf = new byte[bufSize]; dgPacketIn = new DatagramPacket(ibuf, ibuf.length); try { dgSocket.receive(dgPacketIn); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java Wed Jul 05 20:41:30 2017 +0200 @@ -135,7 +135,7 @@ public byte[] asn1Encode() throws Asn1Exception, IOException { DerOutputStream bytes = new DerOutputStream(); DerOutputStream temp = new DerOutputStream(); - DerValue der[] = new DerValue[4]; + DerValue[] der = new DerValue[4]; temp.putInteger(BigInteger.valueOf(tkt_vno)); bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp); bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), sname.getRealm().asn1Encode()); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java Wed Jul 05 20:41:30 2017 +0200 @@ -357,7 +357,7 @@ if (DEBUG) { System.out.println(">>>DEBUG key type: " + key.getEType()); } - long times[] = readTimes(); + long[] times = readTimes(); KerberosTime authtime = new KerberosTime(times[0]); KerberosTime starttime = (times[1]==0) ? null : new KerberosTime(times[1]); @@ -374,9 +374,9 @@ ((renewTill==null)?"null":renewTill.toDate().toString())); } boolean skey = readskey(); - boolean flags[] = readFlags(); + boolean[] flags = readFlags(); TicketFlags tFlags = new TicketFlags(flags); - HostAddress addr[] = readAddr(); + HostAddress[] addr = readAddr(); HostAddresses addrs = null; if (addr != null) { addrs = new HostAddresses(addr); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/crc32.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/crc32.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/crc32.java Wed Jul 05 20:41:30 2017 +0200 @@ -112,7 +112,7 @@ * This version is more efficient than the byte-at-a-time version; * it avoids data copies and reduces per-byte call overhead. */ - protected synchronized void engineUpdate(byte input[], int offset, + protected synchronized void engineUpdate(byte[] input, int offset, int len) { processData(input, offset, len); } diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/KerberosPreMasterSecret.java --- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/KerberosPreMasterSecret.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/KerberosPreMasterSecret.java Wed Jul 05 20:41:30 2017 +0200 @@ -53,8 +53,8 @@ final class KerberosPreMasterSecret { private ProtocolVersion protocolVersion; // preMaster [0,1] - private byte preMaster[]; // 48 bytes - private byte encrypted[]; + private byte[] preMaster; // 48 bytes + private byte[] encrypted; /** * Constructor used by client to generate premaster secret. diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ClientFactoryImpl.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ClientFactoryImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ClientFactoryImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -47,13 +47,13 @@ * @author Rosanna Lee */ final public class ClientFactoryImpl implements SaslClientFactory { - private static final String myMechs[] = { + private static final String[] myMechs = { "EXTERNAL", "CRAM-MD5", "PLAIN", }; - private static final int mechPolicies[] = { + private static final int[] mechPolicies = { // %%% RL: Policies should actually depend on the external channel PolicyUtils.NOPLAINTEXT|PolicyUtils.NOACTIVE|PolicyUtils.NODICTIONARY, PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS, // CRAM-MD5 diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java Wed Jul 05 20:41:30 2017 +0200 @@ -165,7 +165,7 @@ PasswordCallback pcb = new PasswordCallback("CRAM-MD5 password: ", false); cbh.handle(new Callback[]{ncb,pcb}); - char pwChars[] = pcb.getPassword(); + char[] pwChars = pcb.getPassword(); if (pwChars == null || pwChars.length == 0) { // user has no password; OK to disclose to server aborted = true; @@ -190,7 +190,7 @@ clearPassword(); // Check whether digest is as expected - byte [] expectedDigest = digest.getBytes("UTF8"); + byte[] expectedDigest = digest.getBytes("UTF8"); int digestLen = responseData.length - ulen - 1; if (expectedDigest.length != digestLen) { aborted = true; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ServerFactoryImpl.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ServerFactoryImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ServerFactoryImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -41,11 +41,11 @@ * @author Rosanna Lee */ final public class ServerFactoryImpl implements SaslServerFactory { - private static final String myMechs[] = { + private static final String[] myMechs = { "CRAM-MD5", // }; - private static final int mechPolicies[] = { + private static final int[] mechPolicies = { PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS, // CRAM-MD5 }; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java Wed Jul 05 20:41:30 2017 +0200 @@ -272,7 +272,7 @@ */ /** This array maps the characters to their 6 bit values */ - private final static char pem_array[] = { + private final static char[] pem_array = { // 0 1 2 3 4 5 6 7 'A','B','C','D','E','F','G','H', // 0 'I','J','K','L','M','N','O','P', // 1 @@ -1068,7 +1068,7 @@ byte[] hMAC_MD5 = m.doFinal(); /* First 10 bytes of HMAC_MD5 digest */ - byte macBuffer[] = new byte[10]; + byte[] macBuffer = new byte[10]; System.arraycopy(hMAC_MD5, 0, macBuffer, 0, 10); return macBuffer; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/FactoryImpl.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/FactoryImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/FactoryImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -44,9 +44,9 @@ public final class FactoryImpl implements SaslClientFactory, SaslServerFactory{ - private static final String myMechs[] = { "DIGEST-MD5" }; + private static final String[] myMechs = { "DIGEST-MD5" }; private static final int DIGEST_MD5 = 0; - private static final int mechPolicies[] = { + private static final int[] mechPolicies = { PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS}; /** diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java --- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -43,8 +43,8 @@ public final class FactoryImpl implements SaslClientFactory, SaslServerFactory{ - private static final String myMechs[] = { "NTLM" }; - private static final int mechPolicies[] = { + private static final String[] myMechs = { "NTLM" }; + private static final int[] mechPolicies = { PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS }; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java Wed Jul 05 20:41:30 2017 +0200 @@ -66,7 +66,7 @@ class KeyEntry { private Key privateKey; - private X509Certificate certChain[]; + private X509Certificate[] certChain; private String alias; KeyEntry(Key key, X509Certificate[] chain) { diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java Wed Jul 05 20:41:30 2017 +0200 @@ -175,7 +175,7 @@ this.algorithm = algorithm; this.mechanism = mechanism; - String algoParts[] = algorithm.split("/"); + String[] algoParts = algorithm.split("/"); if (algoParts[0].startsWith("AES")) { blockSize = 16; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Wed Jul 05 20:41:30 2017 +0200 @@ -164,7 +164,7 @@ private X509Certificate cert = null; // chain - private X509Certificate chain[] = null; + private X509Certificate[] chain = null; // true if CKA_ID for private key and cert match up private boolean matched = false; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java Wed Jul 05 20:41:30 2017 +0200 @@ -42,7 +42,7 @@ public class CK_AES_CTR_PARAMS { private final long ulCounterBits; - private final byte cb[]; + private final byte[] cb; public CK_AES_CTR_PARAMS(byte[] cb) { ulCounterBits = 128; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java --- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java Wed Jul 05 20:41:30 2017 +0200 @@ -40,7 +40,7 @@ private static final long serialVersionUID = -933864511110035746L; // NOTE: check /usr/include/sys/crypto/common.h for updates - private static final String ERROR_MSG[] = { + private static final String[] ERROR_MSG = { "CRYPTO_SUCCESS", "CRYPTO_CANCEL", "CRYPTO_HOST_MEMORY", diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +// Based on Apache Karaf impl + +/** + * Non-interruptible (via CTRL-C) {@link UnixTerminal}. + * + * @since 2.0 + */ +public class NoInterruptUnixTerminal + extends UnixTerminal +{ + public NoInterruptUnixTerminal() throws Exception { + super(); + } + + @Override + public void init() throws Exception { + super.init(); + getSettings().set("intr undef"); + } + + @Override + public void restore() throws Exception { + getSettings().set("intr ^C"); + super.restore(); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Representation of the input terminal for a platform. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.0 + */ +public interface Terminal +{ + void init() throws Exception; + + void restore() throws Exception; + + void reset() throws Exception; + + boolean isSupported(); + + int getWidth(); + + int getHeight(); + + boolean isAnsiSupported(); + + /** + * When ANSI is not natively handled, the output will have to be wrapped. + */ + OutputStream wrapOutIfNeeded(OutputStream out); + + /** + * When using native support, return the InputStream to use for reading characters + * else return the input stream passed as a parameter. + * + * @since 2.6 + */ + InputStream wrapInIfNeeded(InputStream in) throws IOException; + + /** + * For terminals that don't wrap when character is written in last column, + * only when the next character is written. + * These are the ones that have 'am' and 'xn' termcap attributes (xterm and + * rxvt flavors falls under that category) + */ + boolean hasWeirdWrap(); + + boolean isEchoEnabled(); + + void setEchoEnabled(boolean enabled); + + String getOutputEncoding(); + +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Callable; + +import jdk.internal.jline.internal.Configuration; +import jdk.internal.jline.internal.Log; +import jdk.internal.jline.internal.Preconditions; +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Creates terminal instances. + * + * @author Jason Dillon + * @since 2.0 + */ +public class TerminalFactory +{ + public static final String JLINE_TERMINAL = "jline.terminal"; + + public static final String AUTO = "auto"; + + public static final String UNIX = "unix"; + + public static final String WIN = "win"; + + public static final String WINDOWS = "windows"; + + public static final String NONE = "none"; + + public static final String OFF = "off"; + + public static final String FALSE = "false"; + + private static Terminal term = null; + + public static synchronized Terminal create() { + if (Log.TRACE) { + //noinspection ThrowableInstanceNeverThrown + Log.trace(new Throwable("CREATE MARKER")); + } + + String type = Configuration.getString(JLINE_TERMINAL, AUTO); + if ("dumb".equals(System.getenv("TERM"))) { + type = "none"; + Log.debug("$TERM=dumb; setting type=", type); + } + + Log.debug("Creating terminal; type=", type); + + Terminal t; + try { + String tmp = type.toLowerCase(); + + if (tmp.equals(UNIX)) { + t = getFlavor(Flavor.UNIX); + } + else if (tmp.equals(WIN) | tmp.equals(WINDOWS)) { + t = getFlavor(Flavor.WINDOWS); + } + else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) { + t = new UnsupportedTerminal(); + } + else { + if (tmp.equals(AUTO)) { + String os = Configuration.getOsName(); + Flavor flavor = Flavor.UNIX; + if (os.contains(WINDOWS)) { + flavor = Flavor.WINDOWS; + } + t = getFlavor(flavor); + } + else { + try { + t = (Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance(); + } + catch (Exception e) { + throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e); + } + } + } + } + catch (Exception e) { + Log.error("Failed to construct terminal; falling back to unsupported", e); + t = new UnsupportedTerminal(); + } + + Log.debug("Created Terminal: ", t); + + try { + t.init(); + } + catch (Throwable e) { + Log.error("Terminal initialization failed; falling back to unsupported", e); + return new UnsupportedTerminal(); + } + + return t; + } + + public static synchronized void reset() { + term = null; + } + + public static synchronized void resetIf(final Terminal t) { + if(t == term) { + reset(); + } + } + + public static enum Type + { + AUTO, + WINDOWS, + UNIX, + NONE + } + + public static synchronized void configure(final String type) { + checkNotNull(type); + System.setProperty(JLINE_TERMINAL, type); + } + + public static synchronized void configure(final Type type) { + checkNotNull(type); + configure(type.name().toLowerCase()); + } + + // + // Flavor Support + // + + public static enum Flavor + { + WINDOWS, + UNIX + } + + private static final Map> FLAVORS = new HashMap<>(); + + static { +// registerFlavor(Flavor.WINDOWS, AnsiWindowsTerminal.class); +// registerFlavor(Flavor.UNIX, UnixTerminal.class); + registerFlavor(Flavor.WINDOWS, WindowsTerminal :: new); + registerFlavor(Flavor.UNIX, UnixTerminal :: new); + } + + public static synchronized Terminal get() { + if (term == null) { + term = create(); + } + return term; + } + + public static Terminal getFlavor(final Flavor flavor) throws Exception { + return FLAVORS.getOrDefault(flavor, () -> {throw new InternalError();}).call(); + } + + public static void registerFlavor(final Flavor flavor, final Callable sup) { + FLAVORS.put(flavor, sup); + } + +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import jdk.internal.jline.internal.Log; +import jdk.internal.jline.internal.ShutdownHooks; +import jdk.internal.jline.internal.ShutdownHooks.Task; + +/** + * Provides support for {@link Terminal} instances. + * + * @author Jason Dillon + * @since 2.0 + */ +public abstract class TerminalSupport + implements Terminal +{ + public static final int DEFAULT_WIDTH = 80; + + public static final int DEFAULT_HEIGHT = 24; + + private Task shutdownTask; + + private boolean supported; + + private boolean echoEnabled; + + private boolean ansiSupported; + + protected TerminalSupport(final boolean supported) { + this.supported = supported; + } + + public void init() throws Exception { + if (shutdownTask != null) { + ShutdownHooks.remove(shutdownTask); + } + // Register a task to restore the terminal on shutdown + this.shutdownTask = ShutdownHooks.add(new Task() + { + public void run() throws Exception { + restore(); + } + }); + } + + public void restore() throws Exception { + TerminalFactory.resetIf(this); + if (shutdownTask != null) { + ShutdownHooks.remove(shutdownTask); + shutdownTask = null; + } + } + + public void reset() throws Exception { + restore(); + init(); + } + + public final boolean isSupported() { + return supported; + } + + public synchronized boolean isAnsiSupported() { + return ansiSupported; + } + + protected synchronized void setAnsiSupported(final boolean supported) { + this.ansiSupported = supported; + Log.debug("Ansi supported: ", supported); + } + + /** + * Subclass to change behavior if needed. + * @return the passed out + */ + public OutputStream wrapOutIfNeeded(OutputStream out) { + return out; + } + + /** + * Defaults to true which was the behaviour before this method was added. + */ + public boolean hasWeirdWrap() { + return true; + } + + public int getWidth() { + return DEFAULT_WIDTH; + } + + public int getHeight() { + return DEFAULT_HEIGHT; + } + + public synchronized boolean isEchoEnabled() { + return echoEnabled; + } + + public synchronized void setEchoEnabled(final boolean enabled) { + this.echoEnabled = enabled; + Log.debug("Echo enabled: ", enabled); + } + + public InputStream wrapInIfNeeded(InputStream in) throws IOException { + return in; + } + + public String getOutputEncoding() { + // null for unknown + return null; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +import jdk.internal.jline.internal.Log; +import jdk.internal.jline.internal.TerminalLineSettings; + +/** + * Terminal that is used for unix platforms. Terminal initialization + * is handled by issuing the stty command against the + * /dev/tty file to disable character echoing and enable + * character input. All known unix systems (including + * Linux and Macintosh OS X) support the stty), so this + * implementation should work for an reasonable POSIX system. + * + * @author Marc Prud'hommeaux + * @author Dale Kemp + * @author Jason Dillon + * @author Jean-Baptiste Onofr\u00E9 + * @since 2.0 + */ +public class UnixTerminal + extends TerminalSupport +{ + private final TerminalLineSettings settings = new TerminalLineSettings(); + + public UnixTerminal() throws Exception { + super(true); + } + + protected TerminalLineSettings getSettings() { + return settings; + } + + /** + * Remove line-buffered input by invoking "stty -icanon min 1" + * against the current terminal. + */ + @Override + public void init() throws Exception { + super.init(); + + setAnsiSupported(true); + + // Set the console to be character-buffered instead of line-buffered. + // Make sure we're distinguishing carriage return from newline. + // Allow ctrl-s keypress to be used (as forward search) + settings.set("-icanon min 1 -icrnl -inlcr -ixon"); + settings.set("dsusp undef"); + + setEchoEnabled(false); + } + + /** + * Restore the original terminal configuration, which can be used when + * shutting down the console reader. The ConsoleReader cannot be + * used after calling this method. + */ + @Override + public void restore() throws Exception { + settings.restore(); + super.restore(); + } + + /** + * Returns the value of stty columns param. + */ + @Override + public int getWidth() { + int w = settings.getProperty("columns"); + return w < 1 ? DEFAULT_WIDTH : w; + } + + /** + * Returns the value of stty rows>/tt> param. + */ + @Override + public int getHeight() { + int h = settings.getProperty("rows"); + return h < 1 ? DEFAULT_HEIGHT : h; + } + + @Override + public synchronized void setEchoEnabled(final boolean enabled) { + try { + if (enabled) { + settings.set("echo"); + } + else { + settings.set("-echo"); + } + super.setEchoEnabled(enabled); + } + catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.error("Failed to ", (enabled ? "enable" : "disable"), " echo", e); + } + } + + public void disableInterruptCharacter() + { + try { + settings.set("intr undef"); + } + catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.error("Failed to disable interrupt character", e); + } + } + + public void enableInterruptCharacter() + { + try { + settings.set("intr ^C"); + } + catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.error("Failed to enable interrupt character", e); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +/** + * An unsupported terminal. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.0 + */ +public class UnsupportedTerminal + extends TerminalSupport +{ + public UnsupportedTerminal() { + super(false); + setAnsiSupported(false); + setEchoEnabled(true); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import jdk.internal.jline.internal.Configuration; +import jdk.internal.jline.internal.Log; +//import org.fusesource.jansi.internal.WindowsSupport; +//import org.fusesource.jansi.internal.Kernel32; +//import static org.fusesource.jansi.internal.Kernel32.*; + +import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT; +import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT; +import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT; +import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT; + +/** + * Terminal implementation for Microsoft Windows. Terminal initialization in + * {@link #init} is accomplished by extracting the + * jline_version.dll, saving it to the system temporary + * directoy (determined by the setting of the java.io.tmpdir System + * property), loading the library, and then calling the Win32 APIs SetConsoleMode and + * GetConsoleMode to + * disable character echoing. + *

+ *

+ * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt + * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper + * around {@link FileDescriptor#in}, and if so, will bypass the character reading to + * directly invoke the readc() method in the JNI library. This is so the class + * can read special keys (like arrow keys) which are otherwise inaccessible via + * the {@link System#in} stream. Using JNI reading can be bypassed by setting + * the jline.WindowsTerminal.directConsole system property + * to false. + *

+ * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.0 + */ +public class WindowsTerminal + extends TerminalSupport +{ + public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole"; + + public static final String ANSI = WindowsTerminal.class.getName() + ".ansi"; + + private boolean directConsole; + + private int originalMode; + + public WindowsTerminal() throws Exception { + super(true); + } + + @Override + public void init() throws Exception { + super.init(); + +// setAnsiSupported(Configuration.getBoolean(ANSI, true)); + setAnsiSupported(false); + + // + // FIXME: Need a way to disable direct console and sysin detection muck + // + + setDirectConsole(Configuration.getBoolean(DIRECT_CONSOLE, true)); + + this.originalMode = getConsoleMode(); + setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code); + setEchoEnabled(false); + } + + /** + * Restore the original terminal configuration, which can be used when + * shutting down the console reader. The ConsoleReader cannot be + * used after calling this method. + */ + @Override + public void restore() throws Exception { + // restore the old console mode + setConsoleMode(originalMode); + super.restore(); + } + + @Override + public int getWidth() { + int w = getWindowsTerminalWidth(); + return w < 1 ? DEFAULT_WIDTH : w; + } + + @Override + public int getHeight() { + int h = getWindowsTerminalHeight(); + return h < 1 ? DEFAULT_HEIGHT : h; + } + + @Override + public void setEchoEnabled(final boolean enabled) { + // Must set these four modes at the same time to make it work fine. + if (enabled) { + setConsoleMode(getConsoleMode() | + ENABLE_ECHO_INPUT.code | + ENABLE_LINE_INPUT.code | + ENABLE_PROCESSED_INPUT.code | + ENABLE_WINDOW_INPUT.code); + } + else { + setConsoleMode(getConsoleMode() & + ~(ENABLE_LINE_INPUT.code | + ENABLE_ECHO_INPUT.code | + ENABLE_PROCESSED_INPUT.code | + ENABLE_WINDOW_INPUT.code)); + } + super.setEchoEnabled(enabled); + } + + /** + * Whether or not to allow the use of the JNI console interaction. + */ + public void setDirectConsole(final boolean flag) { + this.directConsole = flag; + Log.debug("Direct console: ", flag); + } + + /** + * Whether or not to allow the use of the JNI console interaction. + */ + public Boolean getDirectConsole() { + return directConsole; + } + + + @Override + public InputStream wrapInIfNeeded(InputStream in) throws IOException { + if (directConsole && isSystemIn(in)) { + return new InputStream() { + private byte[] buf = null; + int bufIdx = 0; + + @Override + public int read() throws IOException { + while (buf == null || bufIdx == buf.length) { + buf = readConsoleInput(); + bufIdx = 0; + } + int c = buf[bufIdx] & 0xFF; + bufIdx++; + return c; + } + }; + } else { + return super.wrapInIfNeeded(in); + } + } + + protected boolean isSystemIn(final InputStream in) throws IOException { + if (in == null) { + return false; + } + else if (in == System.in) { + return true; + } + else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) { + return true; + } + + return false; + } + + @Override + public String getOutputEncoding() { + int codepage = getConsoleOutputCodepage(); + //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html + String charsetMS = "ms" + codepage; + if (java.nio.charset.Charset.isSupported(charsetMS)) { + return charsetMS; + } + String charsetCP = "cp" + codepage; + if (java.nio.charset.Charset.isSupported(charsetCP)) { + return charsetCP; + } + Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")..."); + return super.getOutputEncoding(); + } + + // + // Original code: + // +// private int getConsoleMode() { +// return WindowsSupport.getConsoleMode(); +// } +// +// private void setConsoleMode(int mode) { +// WindowsSupport.setConsoleMode(mode); +// } +// +// private byte[] readConsoleInput() { +// // XXX does how many events to read in one call matter? +// INPUT_RECORD[] events = null; +// try { +// events = WindowsSupport.readConsoleInput(1); +// } catch (IOException e) { +// Log.debug("read Windows console input error: ", e); +// } +// if (events == null) { +// return new byte[0]; +// } +// StringBuilder sb = new StringBuilder(); +// for (int i = 0; i < events.length; i++ ) { +// KEY_EVENT_RECORD keyEvent = events[i].keyEvent; +// //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar); +// if (keyEvent.keyDown) { +// if (keyEvent.uchar > 0) { +// // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC +// // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set +// final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED; +// // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed, +// // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors +// final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED; +// if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z')) +// && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) { +// sb.append('\u001B'); // ESC +// } +// +// sb.append(keyEvent.uchar); +// continue; +// } +// // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx +// // just add support for basic editing keys (no control state, no numpad keys) +// String escapeSequence = null; +// switch (keyEvent.keyCode) { +// case 0x21: // VK_PRIOR PageUp +// escapeSequence = "\u001B[5~"; +// break; +// case 0x22: // VK_NEXT PageDown +// escapeSequence = "\u001B[6~"; +// break; +// case 0x23: // VK_END +// escapeSequence = "\u001B[4~"; +// break; +// case 0x24: // VK_HOME +// escapeSequence = "\u001B[1~"; +// break; +// case 0x25: // VK_LEFT +// escapeSequence = "\u001B[D"; +// break; +// case 0x26: // VK_UP +// escapeSequence = "\u001B[A"; +// break; +// case 0x27: // VK_RIGHT +// escapeSequence = "\u001B[C"; +// break; +// case 0x28: // VK_DOWN +// escapeSequence = "\u001B[B"; +// break; +// case 0x2D: // VK_INSERT +// escapeSequence = "\u001B[2~"; +// break; +// case 0x2E: // VK_DELETE +// escapeSequence = "\u001B[3~"; +// break; +// default: +// break; +// } +// if (escapeSequence != null) { +// for (int k = 0; k < keyEvent.repeatCount; k++) { +// sb.append(escapeSequence); +// } +// } +// } else { +// // key up event +// // support ALT+NumPad input method +// if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) { +// sb.append(keyEvent.uchar); +// } +// } +// } +// return sb.toString().getBytes(); +// } +// +// private int getConsoleOutputCodepage() { +// return Kernel32.GetConsoleOutputCP(); +// } +// +// private int getWindowsTerminalWidth() { +// return WindowsSupport.getWindowsTerminalWidth(); +// } +// +// private int getWindowsTerminalHeight() { +// return WindowsSupport.getWindowsTerminalHeight(); +// } + + // + // Native Bits + // + static { + System.loadLibrary("le"); + initIDs(); + } + + private static native void initIDs(); + + private native int getConsoleMode(); + + private native void setConsoleMode(int mode); + + private byte[] readConsoleInput() { + KEY_EVENT_RECORD keyEvent = readKeyEvent(); + + return convertKeys(keyEvent).getBytes(); + } + + public static String convertKeys(KEY_EVENT_RECORD keyEvent) { + if (keyEvent == null) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + + if (keyEvent.keyDown) { + if (keyEvent.uchar > 0) { + // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC + // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set + final int altState = KEY_EVENT_RECORD.ALT_PRESSED; + // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed, + // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors + final int ctrlState = KEY_EVENT_RECORD.CTRL_PRESSED; + + boolean handled = false; + + if ((keyEvent.controlKeyState & ctrlState) != 0) { + switch (keyEvent.keyCode) { + case 0x43: //Ctrl-C + sb.append("\003"); + handled = true; + break; + } + } + + if ((keyEvent.controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) { + switch (keyEvent.keyCode) { + case 0x09: //Shift-Tab + sb.append("\033\133\132"); + handled = true; + break; + } + } + + if (!handled) { + if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z')) + && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) { + sb.append('\u001B'); // ESC + } + + sb.append(keyEvent.uchar); + } + } else { + // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx + // just add support for basic editing keys (no control state, no numpad keys) + String escapeSequence = null; + switch (keyEvent.keyCode) { + case 0x21: // VK_PRIOR PageUp + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~"); + break; + case 0x22: // VK_NEXT PageDown + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~"); + break; + case 0x23: // VK_END + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~"); + break; + case 0x24: // VK_HOME + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~"); + break; + case 0x25: // VK_LEFT + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD"); + break; + case 0x26: // VK_UP + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA"); + break; + case 0x27: // VK_RIGHT + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC"); + break; + case 0x28: // VK_DOWN + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB"); + break; + case 0x2D: // VK_INSERT + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~"); + break; + case 0x2E: // VK_DELETE + escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[3~", "\u001B[3;%d~"); + break; + default: + break; + } + if (escapeSequence != null) { + for (int k = 0; k < keyEvent.repeatCount; k++) { + sb.append(escapeSequence); + } + } + } + } else { + // key up event + // support ALT+NumPad input method + if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) { + sb.append(keyEvent.uchar); + } + } + return sb.toString(); + } + + private static String escapeSequence(int controlKeyState, String noControlSequence, String withControlSequence) { + int controlNum = 1; + + if ((controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) { + controlNum += 1; + } + + if ((controlKeyState & KEY_EVENT_RECORD.ALT_PRESSED) != 0) { + controlNum += 2; + } + + if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) { + controlNum += 4; + } + + if (controlNum > 1) { + return String.format(withControlSequence, controlNum); + } else { + return noControlSequence; + } + } + + private native KEY_EVENT_RECORD readKeyEvent(); + + public static class KEY_EVENT_RECORD { + public final static int ALT_PRESSED = 0x3; + public final static int CTRL_PRESSED = 0xC; + public final static int SHIFT_PRESSED = 0x10; + public final boolean keyDown; + public final char uchar; + public final int controlKeyState; + public final int keyCode; + public final int repeatCount; + + public KEY_EVENT_RECORD(boolean keyDown, char uchar, int controlKeyState, int keyCode, int repeatCount) { + this.keyDown = keyDown; + this.uchar = uchar; + this.controlKeyState = controlKeyState; + this.keyCode = keyCode; + this.repeatCount = repeatCount; + } + + } + + private native int getConsoleOutputCodepage(); + + private native int getWindowsTerminalWidth(); + + private native int getWindowsTerminalHeight(); + + /** + * Console mode + *

+ * Constants copied wincon.h. + */ + public static enum ConsoleMode + { + /** + * The ReadFile or ReadConsole function returns only when a carriage return + * character is read. If this mode is disable, the functions return when one + * or more characters are available. + */ + ENABLE_LINE_INPUT(2), + + /** + * Characters read by the ReadFile or ReadConsole function are written to + * the active screen buffer as they are read. This mode can be used only if + * the ENABLE_LINE_INPUT mode is also enabled. + */ + ENABLE_ECHO_INPUT(4), + + /** + * CTRL+C is processed by the system and is not placed in the input buffer. + * If the input buffer is being read by ReadFile or ReadConsole, other + * control keys are processed by the system and are not returned in the + * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also + * enabled, backspace, carriage return, and linefeed characters are handled + * by the system. + */ + ENABLE_PROCESSED_INPUT(1), + + /** + * User interactions that change the size of the console screen buffer are + * reported in the console's input buffee. Information about these events + * can be read from the input buffer by applications using + * theReadConsoleInput function, but not by those using ReadFile + * orReadConsole. + */ + ENABLE_WINDOW_INPUT(8), + + /** + * If the mouse pointer is within the borders of the console window and the + * window has the keyboard focus, mouse events generated by mouse movement + * and button presses are placed in the input buffer. These events are + * discarded by ReadFile or ReadConsole, even when this mode is enabled. + */ + ENABLE_MOUSE_INPUT(16), + + /** + * When enabled, text entered in a console window will be inserted at the + * current cursor location and all text following that location will not be + * overwritten. When disabled, all following text will be overwritten. An OR + * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS + * flag to enable this functionality. + */ + ENABLE_PROCESSED_OUTPUT(1), + + /** + * This flag enables the user to use the mouse to select and edit text. To + * enable this option, use the OR to combine this flag with + * ENABLE_EXTENDED_FLAGS. + */ + ENABLE_WRAP_AT_EOL_OUTPUT(2),; + + public final int code; + + ConsoleMode(final int code) { + this.code = code; + } + } + +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.internal.jline.internal.Log; + +/** + * @author St\u00E5le W. Pedersen + */ +public class ConsoleKeys { + + private KeyMap keys; + + private Map keyMaps; + private Map variables = new HashMap(); + + public ConsoleKeys(String appName, URL inputrcUrl) { + keyMaps = KeyMap.keyMaps(); + loadKeys(appName, inputrcUrl); + } + + protected boolean isViEditMode() { + return keys.isViKeyMap(); + } + + protected boolean setKeyMap (String name) { + KeyMap map = keyMaps.get(name); + if (map == null) { + return false; + } + this.keys = map; + return true; + } + + protected Map getKeyMaps() { + return keyMaps; + } + + protected KeyMap getKeys() { + return keys; + } + + protected void setKeys(KeyMap keys) { + this.keys = keys; + } + + protected boolean getViEditMode() { + return keys.isViKeyMap (); + } + + protected void loadKeys(String appName, URL inputrcUrl) { + keys = keyMaps.get(KeyMap.EMACS); + + try { + InputStream input = inputrcUrl.openStream(); + try { + loadKeys(input, appName); + Log.debug("Loaded user configuration: ", inputrcUrl); + } + finally { + try { + input.close(); + } catch (IOException e) { + // Ignore + } + } + } + catch (IOException e) { + if (inputrcUrl.getProtocol().equals("file")) { + File file = new File(inputrcUrl.getPath()); + if (file.exists()) { + Log.warn("Unable to read user configuration: ", inputrcUrl, e); + } + } else { + Log.warn("Unable to read user configuration: ", inputrcUrl, e); + } + } + } + + private void loadKeys(InputStream input, String appName) throws IOException { + BufferedReader reader = new BufferedReader( new java.io.InputStreamReader( input ) ); + String line; + boolean parsing = true; + List ifsStack = new ArrayList(); + while ( (line = reader.readLine()) != null ) { + try { + line = line.trim(); + if (line.length() == 0) { + continue; + } + if (line.charAt(0) == '#') { + continue; + } + int i = 0; + if (line.charAt(i) == '$') { + String cmd; + String args; + for (++i; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++); + int s = i; + for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++); + cmd = line.substring(s, i); + for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++); + s = i; + for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++); + args = line.substring(s, i); + if ("if".equalsIgnoreCase(cmd)) { + ifsStack.add( parsing ); + if (!parsing) { + continue; + } + if (args.startsWith("term=")) { + // TODO + } else if (args.startsWith("mode=")) { + if (args.equalsIgnoreCase("mode=vi")) { + parsing = isViEditMode(); + } else if (args.equals("mode=emacs")) { + parsing = !isViEditMode(); + } else { + parsing = false; + } + } else { + parsing = args.equalsIgnoreCase(appName); + } + } else if ("else".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("$else found without matching $if"); + } + boolean invert = true; + for (boolean b : ifsStack) { + if (!b) { + invert = false; + break; + } + } + if (invert) { + parsing = !parsing; + } + } else if ("endif".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("endif found without matching $if"); + } + parsing = ifsStack.remove( ifsStack.size() - 1 ); + } else if ("include".equalsIgnoreCase(cmd)) { + // TODO + } + continue; + } + if (!parsing) { + continue; + } + boolean equivalency; + String keySeq = ""; + if (line.charAt(i++) == '"') { + boolean esc = false; + for (;; i++) { + if (i >= line.length()) { + throw new IllegalArgumentException("Missing closing quote on line '" + line + "'"); + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == '"') { + break; + } + } + } + for (; i < line.length() && line.charAt(i) != ':' + && line.charAt(i) != ' ' && line.charAt(i) != '\t' + ; i++); + keySeq = line.substring(0, i); + equivalency = (i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '='); + i++; + if (equivalency) { + i++; + } + if (keySeq.equalsIgnoreCase("set")) { + String key; + String val; + for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++); + int s = i; + for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++); + key = line.substring( s, i ); + for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++); + s = i; + for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++); + val = line.substring( s, i ); + setVar( key, val ); + } else { + for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++); + int start = i; + if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) { + char delim = line.charAt(i++); + boolean esc = false; + for (;; i++) { + if (i >= line.length()) { + break; + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == delim) { + break; + } + } + } + for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++); + String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length())); + if (keySeq.charAt(0) == '"') { + keySeq = translateQuoted(keySeq); + } else { + // Bind key name + String keyName = keySeq.lastIndexOf('-') > 0 ? keySeq.substring( keySeq.lastIndexOf('-') + 1 ) : keySeq; + char key = getKeyFromName(keyName); + keyName = keySeq.toLowerCase(); + keySeq = ""; + if (keyName.contains("meta-") || keyName.contains("m-")) { + keySeq += "\u001b"; + } + if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) { + key = (char)(Character.toUpperCase( key ) & 0x1f); + } + keySeq += key; + } + if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) { + keys.bind( keySeq, translateQuoted(val) ); + } else { + String operationName = val.replace('-', '_').toUpperCase(); + try { + keys.bind(keySeq, Operation.valueOf(operationName)); + } catch(IllegalArgumentException e) { + Log.info("Unable to bind key for unsupported operation: ", val); + } + } + } + } catch (IllegalArgumentException e) { + Log.warn("Unable to parse user configuration: ", e); + } + } + } + + private String translateQuoted(String keySeq) { + int i; + String str = keySeq.substring( 1, keySeq.length() - 1 ); + keySeq = ""; + for (i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == '\\') { + boolean ctrl = str.regionMatches(i, "\\C-", 0, 3)|| str.regionMatches(i, "\\M-\\C-", 0, 6); + boolean meta = str.regionMatches(i, "\\M-", 0, 3)|| str.regionMatches(i, "\\C-\\M-", 0, 6); + i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0); + if (i >= str.length()) { + break; + } + c = str.charAt(i); + if (meta) { + keySeq += "\u001b"; + } + if (ctrl) { + c = c == '?' ? 0x7f : (char)(Character.toUpperCase( c ) & 0x1f); + } + if (!meta && !ctrl) { + switch (c) { + case 'a': c = 0x07; break; + case 'b': c = '\b'; break; + case 'd': c = 0x7f; break; + case 'e': c = 0x1b; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = 0x0b; break; + case '\\': c = '\\'; break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = 0; + for (int j = 0; j < 3; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 8); + if (k < 0) { + break; + } + c = (char)(c * 8 + k); + } + c &= 0xFF; + break; + case 'x': + i++; + c = 0; + for (int j = 0; j < 2; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char)(c * 16 + k); + } + c &= 0xFF; + break; + case 'u': + i++; + c = 0; + for (int j = 0; j < 4; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char)(c * 16 + k); + } + break; + } + } + keySeq += c; + } else { + keySeq += c; + } + } + return keySeq; + } + + private char getKeyFromName(String name) { + if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) { + return 0x7f; + } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) { + return '\033'; + } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) { + return '\n'; + } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) { + return '\r'; + } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) { + return ' '; + } else if ("Tab".equalsIgnoreCase(name)) { + return '\t'; + } else { + return name.charAt(0); + } + } + + private void setVar(String key, String val) { + if ("keymap".equalsIgnoreCase(key)) { + if (keyMaps.containsKey(val)) { + keys = keyMaps.get(val); + } + } else if ("editing-mode".equals(key)) { + if ("vi".equalsIgnoreCase(val)) { + keys = keyMaps.get(KeyMap.VI_INSERT); + } else if ("emacs".equalsIgnoreCase(key)) { + keys = keyMaps.get(KeyMap.EMACS); + } + } else if ("blink-matching-paren".equals(key)) { + if ("on".equalsIgnoreCase(val)) { + keys.setBlinkMatchingParen(true); + } else if ("off".equalsIgnoreCase(val)) { + keys.setBlinkMatchingParen(false); + } + } + + /* + * Technically variables should be defined as a functor class + * so that validation on the variable value can be done at parse + * time. This is a stop-gap. + */ + variables.put(key, val); + } + + /** + * Retrieves the value of a variable that was set in the .inputrc file + * during processing + * @param var The variable name + * @return The variable value. + */ + public String getVariable(String var) { + return variables.get (var); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,4006 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +//import java.awt.*; +//import java.awt.datatransfer.Clipboard; +//import java.awt.datatransfer.DataFlavor; +//import java.awt.datatransfer.Transferable; +//import java.awt.datatransfer.UnsupportedFlavorException; +//import java.awt.event.ActionListener; +//import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +//import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +//import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +//import java.util.Map; +import java.util.ResourceBundle; +import java.util.Stack; +import java.util.regex.Pattern; + +import jdk.internal.jline.Terminal; +import jdk.internal.jline.TerminalFactory; +import jdk.internal.jline.UnixTerminal; +import jdk.internal.jline.console.completer.CandidateListCompletionHandler; +import jdk.internal.jline.console.completer.Completer; +import jdk.internal.jline.console.completer.CompletionHandler; +import jdk.internal.jline.console.history.History; +import jdk.internal.jline.console.history.MemoryHistory; +import jdk.internal.jline.internal.Configuration; +import jdk.internal.jline.internal.InputStreamReader; +import jdk.internal.jline.internal.Log; +import jdk.internal.jline.internal.NonBlockingInputStream; +import jdk.internal.jline.internal.Nullable; +import jdk.internal.jline.internal.Urls; +//import org.fusesource.jansi.AnsiOutputStream; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * A reader for console applications. It supports custom tab-completion, + * saveable command history, and command line editing. On some platforms, + * platform-specific commands will need to be issued before the reader will + * function properly. See {@link jline.Terminal#init} for convenience + * methods for issuing platform-specific setup commands. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @author Guillaume Nodet + */ +public class ConsoleReader +{ + public static final String JLINE_NOBELL = "jline.nobell"; + + public static final String JLINE_ESC_TIMEOUT = "jline.esc.timeout"; + + public static final String JLINE_INPUTRC = "jline.inputrc"; + + public static final String INPUT_RC = ".inputrc"; + + public static final String DEFAULT_INPUT_RC = "/etc/inputrc"; + + public static final char BACKSPACE = '\b'; + + public static final char RESET_LINE = '\r'; + + public static final char KEYBOARD_BELL = '\07'; + + public static final char NULL_MASK = 0; + + public static final int TAB_WIDTH = 4; + + private static final ResourceBundle + resources = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName()); + + private final Terminal terminal; + + private final Writer out; + + private final CursorBuffer buf = new CursorBuffer(); + + private String prompt; + private int promptLen; + + private boolean expandEvents = true; + + private boolean bellEnabled = !Configuration.getBoolean(JLINE_NOBELL, true); + + private boolean handleUserInterrupt = false; + + private Character mask; + + private Character echoCharacter; + + private StringBuffer searchTerm = null; + + private String previousSearchTerm = ""; + + private int searchIndex = -1; + + private int parenBlinkTimeout = 500; + + /* + * The reader and the nonBlockingInput go hand-in-hand. The reader wraps + * the nonBlockingInput, but we have to retain a handle to it so that + * we can shut down its blocking read thread when we go away. + */ + private NonBlockingInputStream in; + private long escapeTimeout; + private Reader reader; + + /* + * TODO: Please read the comments about this in setInput(), but this needs + * to be done away with. + */ + private boolean isUnitTestInput; + + /** + * Last character searched for with a vi character search + */ + private char charSearchChar = 0; // Character to search for + private char charSearchLastInvokeChar = 0; // Most recent invocation key + private char charSearchFirstInvokeChar = 0;// First character that invoked + + /** + * The vi yank buffer + */ + private String yankBuffer = ""; + + private KillRing killRing = new KillRing(); + + private String encoding; + + private boolean recording; + + private String macro = ""; + + private String appName; + + private URL inputrcUrl; + + private ConsoleKeys consoleKeys; + + private String commentBegin = null; + + private boolean skipLF = false; + + /** + * Set to true if the reader should attempt to detect copy-n-paste. The + * effect of this that an attempt is made to detect if tab is quickly + * followed by another character, then it is assumed that the tab was + * a literal tab as part of a copy-and-paste operation and is inserted as + * such. + */ + private boolean copyPasteDetection = false; + + /* + * Current internal state of the line reader + */ + private State state = State.NORMAL; + + /** + * Possible states in which the current readline operation may be in. + */ + private static enum State { + /** + * The user is just typing away + */ + NORMAL, + /** + * In the middle of a emacs seach + */ + SEARCH, + FORWARD_SEARCH, + /** + * VI "yank-to" operation ("y" during move mode) + */ + VI_YANK_TO, + /** + * VI "delete-to" operation ("d" during move mode) + */ + VI_DELETE_TO, + /** + * VI "change-to" operation ("c" during move mode) + */ + VI_CHANGE_TO + } + + public ConsoleReader() throws IOException { + this(null, new FileInputStream(FileDescriptor.in), System.out, null); + } + + public ConsoleReader(final InputStream in, final OutputStream out) throws IOException { + this(null, in, out, null); + } + + public ConsoleReader(final InputStream in, final OutputStream out, final Terminal term) throws IOException { + this(null, in, out, term); + } + + public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term) throws IOException { + this(appName, in, out, term, null); + } + + public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term, final @Nullable String encoding) + throws IOException + { + this.appName = appName != null ? appName : "JLine"; + this.encoding = encoding != null ? encoding : Configuration.getEncoding(); + this.terminal = term != null ? term : TerminalFactory.get(); + String outEncoding = terminal.getOutputEncoding() != null? terminal.getOutputEncoding() : this.encoding; + this.out = new OutputStreamWriter(terminal.wrapOutIfNeeded(out), outEncoding); + setInput( in ); + + this.inputrcUrl = getInputRc(); + + consoleKeys = new ConsoleKeys(this.appName, inputrcUrl); + } + + private URL getInputRc() throws IOException { + String path = Configuration.getString(JLINE_INPUTRC); + if (path == null) { + File f = new File(Configuration.getUserHome(), INPUT_RC); + if (!f.exists()) { + f = new File(DEFAULT_INPUT_RC); + } + return f.toURI().toURL(); + } else { + return Urls.create(path); + } + } + + public KeyMap getKeys() { + return consoleKeys.getKeys(); + } + + void setInput(final InputStream in) throws IOException { + this.escapeTimeout = Configuration.getLong(JLINE_ESC_TIMEOUT, 100); + /* + * This is gross and here is how to fix it. In getCurrentPosition() + * and getCurrentAnsiRow(), the logic is disabled when running unit + * tests and the fact that it is a unit test is determined by knowing + * if the original input stream was a ByteArrayInputStream. So, this + * is our test to do this. What SHOULD happen is that the unit + * tests should pass in a terminal that is appropriately configured + * such that whatever behavior they expect to happen (or not happen) + * happens (or doesn't). + * + * So, TODO, get rid of this and fix the unit tests. + */ + this.isUnitTestInput = in instanceof ByteArrayInputStream; + boolean nonBlockingEnabled = + escapeTimeout > 0L + && terminal.isSupported() + && in != null; + + /* + * If we had a non-blocking thread already going, then shut it down + * and start a new one. + */ + if (this.in != null) { + this.in.shutdown(); + } + + final InputStream wrapped = terminal.wrapInIfNeeded( in ); + + this.in = new NonBlockingInputStream(wrapped, nonBlockingEnabled); + this.reader = new InputStreamReader( this.in, encoding ); + } + + /** + * Shuts the console reader down. This method should be called when you + * have completed using the reader as it shuts down and cleans up resources + * that would otherwise be "leaked". + */ + public void shutdown() { + if (in != null) { + in.shutdown(); + } + } + + /** + * Shuts down the ConsoleReader if the JVM attempts to clean it up. + */ + @Override + protected void finalize() throws Throwable { + try { + shutdown(); + } + finally { + super.finalize(); + } + } + + public InputStream getInput() { + return in; + } + + public Writer getOutput() { + return out; + } + + public Terminal getTerminal() { + return terminal; + } + + public CursorBuffer getCursorBuffer() { + return buf; + } + + public void setExpandEvents(final boolean expand) { + this.expandEvents = expand; + } + + public boolean getExpandEvents() { + return expandEvents; + } + + /** + * Enables or disables copy and paste detection. The effect of enabling this + * this setting is that when a tab is received immediately followed by another + * character, the tab will not be treated as a completion, but as a tab literal. + * @param onoff true if detection is enabled + */ + public void setCopyPasteDetection(final boolean onoff) { + copyPasteDetection = onoff; + } + + /** + * @return true if copy and paste detection is enabled. + */ + public boolean isCopyPasteDetectionEnabled() { + return copyPasteDetection; + } + + /** + * Set whether the console bell is enabled. + * + * @param enabled true if enabled; false otherwise + * @since 2.7 + */ + public void setBellEnabled(boolean enabled) { + this.bellEnabled = enabled; + } + + /** + * Get whether the console bell is enabled + * + * @return true if enabled; false otherwise + * @since 2.7 + */ + public boolean getBellEnabled() { + return bellEnabled; + } + + /** + * Set whether user interrupts (ctrl-C) are handled by having JLine + * throw {@link UserInterruptException} from {@link #readLine}. + * Otherwise, the JVM will handle {@code SIGINT} as normal, which + * usually causes it to exit. The default is {@code false}. + * + * @since 2.10 + */ + public void setHandleUserInterrupt(boolean enabled) + { + this.handleUserInterrupt = enabled; + } + + /** + * Get whether user interrupt handling is enabled + * + * @return true if enabled; false otherwise + * @since 2.10 + */ + public boolean getHandleUserInterrupt() + { + return handleUserInterrupt; + } + + /** + * Sets the string that will be used to start a comment when the + * insert-comment key is struck. + * @param commentBegin The begin comment string. + * @since 2.7 + */ + public void setCommentBegin(String commentBegin) { + this.commentBegin = commentBegin; + } + + /** + * @return the string that will be used to start a comment when the + * insert-comment key is struck. + * @since 2.7 + */ + public String getCommentBegin() { + String str = commentBegin; + + if (str == null) { + str = consoleKeys.getVariable("comment-begin"); + if (str == null) { + str = "#"; + } + } + return str; + } + + public void setPrompt(final String prompt) { + this.prompt = prompt; + this.promptLen = ((prompt == null) ? 0 : stripAnsi(lastLine(prompt)).length()); + } + + public String getPrompt() { + return prompt; + } + + /** + * Set the echo character. For example, to have "*" entered when a password is typed: + *

+ *

+     * myConsoleReader.setEchoCharacter(new Character('*'));
+     * 
+ *

+ * Setting the character to + *

+ *

+     * null
+     * 
+ *

+ * will restore normal character echoing. Setting the character to + *

+ *

+     * new Character(0)
+     * 
+ *

+ * will cause nothing to be echoed. + * + * @param c the character to echo to the console in place of the typed character. + */ + public void setEchoCharacter(final Character c) { + this.echoCharacter = c; + } + + /** + * Returns the echo character. + */ + public Character getEchoCharacter() { + return echoCharacter; + } + + /** + * Erase the current line. + * + * @return false if we failed (e.g., the buffer was empty) + */ + protected final boolean resetLine() throws IOException { + if (buf.cursor == 0) { + return false; + } + + StringBuilder killed = new StringBuilder(); + + while (buf.cursor > 0) { + char c = buf.current(); + if (c == 0) { + break; + } + + killed.append(c); + backspace(); + } + + String copy = killed.reverse().toString(); + killRing.addBackwards(copy); + + return true; + } + + int getCursorPosition() { + // FIXME: does not handle anything but a line with a prompt absolute position + return promptLen + buf.cursor; + } + + /** + * Returns the text after the last '\n'. + * prompt is returned if no '\n' characters are present. + * null is returned if prompt is null. + */ + private String lastLine(String str) { + if (str == null) return ""; + int last = str.lastIndexOf("\n"); + + if (last >= 0) { + return str.substring(last + 1, str.length()); + } + + return str; + } + + String stripAnsi(String str) { + if (str == null) return ""; + return ANSI_CODE_PATTERN.matcher(str).replaceAll(""); +// try { +// ByteArrayOutputStream baos = new ByteArrayOutputStream(); +// AnsiOutputStream aos = new AnsiOutputStream(baos); +// aos.write(str.getBytes()); +// aos.flush(); +// return baos.toString(); +// } catch (IOException e) { +// return str; +// } + } + //where: + private static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[^@-~]*[@-~]"); + + /** + * Move the cursor position to the specified absolute index. + */ + public final boolean setCursorPosition(final int position) throws IOException { + if (position == buf.cursor) { + return true; + } + + return moveCursor(position - buf.cursor) != 0; + } + + /** + * Set the current buffer's content to the specified {@link String}. The + * visual console will be modified to show the current buffer. + * + * @param buffer the new contents of the buffer. + */ + private void setBuffer(final String buffer) throws IOException { + // don't bother modifying it if it is unchanged + if (buffer.equals(buf.buffer.toString())) { + return; + } + + // obtain the difference between the current buffer and the new one + int sameIndex = 0; + + for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1) + && (i < l2); i++) { + if (buffer.charAt(i) == buf.buffer.charAt(i)) { + sameIndex++; + } + else { + break; + } + } + + int diff = buf.cursor - sameIndex; + if (diff < 0) { // we can't backspace here so try from the end of the buffer + moveToEnd(); + diff = buf.buffer.length() - sameIndex; + } + + backspace(diff); // go back for the differences + killLine(); // clear to the end of the line + buf.buffer.setLength(sameIndex); // the new length + putString(buffer.substring(sameIndex)); // append the differences + } + + private void setBuffer(final CharSequence buffer) throws IOException { + setBuffer(String.valueOf(buffer)); + } + + private void setBufferKeepPos(final String buffer) throws IOException { + int pos = buf.cursor; + setBuffer(buffer); + setCursorPosition(pos); + } + + private void setBufferKeepPos(final CharSequence buffer) throws IOException { + setBufferKeepPos(String.valueOf(buffer)); + } + + /** + * Output put the prompt + the current buffer + */ + public final void drawLine() throws IOException { + String prompt = getPrompt(); + if (prompt != null) { + print(prompt); + } + + print(buf.buffer.toString()); + + if (buf.length() != buf.cursor) { // not at end of line + back(buf.length() - buf.cursor - 1); + } + // force drawBuffer to check for weird wrap (after clear screen) + drawBuffer(); + } + + /** + * Clear the line and redraw it. + */ + public final void redrawLine() throws IOException { + print(RESET_LINE); +// flush(); + drawLine(); + } + + /** + * Clear the buffer and add its contents to the history. + * + * @return the former contents of the buffer. + */ + final String finishBuffer() throws IOException { // FIXME: Package protected because used by tests + String str = buf.buffer.toString(); + String historyLine = str; + + if (expandEvents) { + try { + str = expandEvents(str); + // all post-expansion occurrences of '!' must have been escaped, so re-add escape to each + historyLine = str.replace("!", "\\!"); + // only leading '^' results in expansion, so only re-add escape for that case + historyLine = historyLine.replaceAll("^\\^", "\\\\^"); + } catch(IllegalArgumentException e) { + Log.error("Could not expand event", e); + beep(); + buf.clear(); + str = ""; + } + } + + // we only add it to the history if the buffer is not empty + // and if mask is null, since having a mask typically means + // the string was a password. We clear the mask after this call + if (str.length() > 0) { + if (mask == null && isHistoryEnabled()) { + history.add(historyLine); + } + else { + mask = null; + } + } + + history.moveToEnd(); + + buf.buffer.setLength(0); + buf.cursor = 0; + + return str; + } + + /** + * Expand event designator such as !!, !#, !3, etc... + * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html + */ + @SuppressWarnings("fallthrough") + protected String expandEvents(String str) throws IOException { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + switch (c) { + case '\\': + // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character + // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character + // otherwise, add the escape + if (i + 1 < str.length()) { + char nextChar = str.charAt(i+1); + if (nextChar == '!' || (nextChar == '^' && i == 0)) { + c = nextChar; + i++; + } + } + sb.append(c); + break; + case '!': + if (i + 1 < str.length()) { + c = str.charAt(++i); + boolean neg = false; + String rep = null; + int i1, idx; + switch (c) { + case '!': + if (history.size() == 0) { + throw new IllegalArgumentException("!!: event not found"); + } + rep = history.get(history.index() - 1).toString(); + break; + case '#': + sb.append(sb.toString()); + break; + case '?': + i1 = str.indexOf('?', i + 1); + if (i1 < 0) { + i1 = str.length(); + } + String sc = str.substring(i + 1, i1); + i = i1; + idx = searchBackwards(sc); + if (idx < 0) { + throw new IllegalArgumentException("!?" + sc + ": event not found"); + } else { + rep = history.get(idx).toString(); + } + break; + case '$': + if (history.size() == 0) { + throw new IllegalArgumentException("!$: event not found"); + } + String previous = history.get(history.index() - 1).toString().trim(); + int lastSpace = previous.lastIndexOf(' '); + if(lastSpace != -1) { + rep = previous.substring(lastSpace+1); + } else { + rep = previous; + } + break; + case ' ': + case '\t': + sb.append('!'); + sb.append(c); + break; + case '-': + neg = true; + i++; + // fall through + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i1 = i; + for (; i < str.length(); i++) { + c = str.charAt(i); + if (c < '0' || c > '9') { + break; + } + } + idx = 0; + try { + idx = Integer.parseInt(str.substring(i1, i)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found"); + } + if (neg) { + if (idx > 0 && idx <= history.size()) { + rep = (history.get(history.index() - idx)).toString(); + } else { + throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found"); + } + } else { + if (idx > history.index() - history.size() && idx <= history.index()) { + rep = (history.get(idx - 1)).toString(); + } else { + throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found"); + } + } + break; + default: + String ss = str.substring(i); + i = str.length(); + idx = searchBackwards(ss, history.index(), true); + if (idx < 0) { + throw new IllegalArgumentException("!" + ss + ": event not found"); + } else { + rep = history.get(idx).toString(); + } + break; + } + if (rep != null) { + sb.append(rep); + } + } else { + sb.append(c); + } + break; + case '^': + if (i == 0) { + int i1 = str.indexOf('^', i + 1); + int i2 = str.indexOf('^', i1 + 1); + if (i2 < 0) { + i2 = str.length(); + } + if (i1 > 0 && i2 > 0) { + String s1 = str.substring(i + 1, i1); + String s2 = str.substring(i1 + 1, i2); + String s = history.get(history.index() - 1).toString().replace(s1, s2); + sb.append(s); + i = i2 + 1; + break; + } + } + sb.append(c); + break; + default: + sb.append(c); + break; + } + } + String result = sb.toString(); + if (!str.equals(result)) { + print(result); + println(); + flush(); + } + return result; + + } + + /** + * Write out the specified string to the buffer and the output stream. + */ + public final void putString(final CharSequence str) throws IOException { + buf.write(str); + if (mask == null) { + // no masking + print(str); + } else if (mask == NULL_MASK) { + // don't print anything + } else { + print(mask, str.length()); + } + drawBuffer(); + } + + /** + * Redraw the rest of the buffer from the cursor onwards. This is necessary + * for inserting text into the buffer. + * + * @param clear the number of characters to clear after the end of the buffer + */ + private void drawBuffer(final int clear) throws IOException { + // debug ("drawBuffer: " + clear); + if (buf.cursor == buf.length() && clear == 0) { + } else { + char[] chars = buf.buffer.substring(buf.cursor).toCharArray(); + if (mask != null) { + Arrays.fill(chars, mask); + } + if (terminal.hasWeirdWrap()) { + // need to determine if wrapping will occur: + int width = terminal.getWidth(); + int pos = getCursorPosition(); + for (int i = 0; i < chars.length; i++) { + print(chars[i]); + if ((pos + i + 1) % width == 0) { + print(32); // move cursor to next line by printing dummy space + print(13); // CR / not newline. + } + } + } else { + print(chars); + } + clearAhead(clear, chars.length); + if (terminal.isAnsiSupported()) { + if (chars.length > 0) { + back(chars.length); + } + } else { + back(chars.length); + } + } + if (terminal.hasWeirdWrap()) { + int width = terminal.getWidth(); + // best guess on whether the cursor is in that weird location... + // Need to do this without calling ansi cursor location methods + // otherwise it breaks paste of wrapped lines in xterm. + if (getCursorPosition() > 0 && (getCursorPosition() % width == 0) + && buf.cursor == buf.length() && clear == 0) { + // the following workaround is reverse-engineered from looking + // at what bash sent to the terminal in the same situation + print(32); // move cursor to next line by printing dummy space + print(13); // CR / not newline. + } + } + } + + /** + * Redraw the rest of the buffer from the cursor onwards. This is necessary + * for inserting text into the buffer. + */ + private void drawBuffer() throws IOException { + drawBuffer(0); + } + + /** + * Clear ahead the specified number of characters without moving the cursor. + * + * @param num the number of characters to clear + * @param delta the difference between the internal cursor and the screen + * cursor - if > 0, assume some stuff was printed and weird wrap has to be + * checked + */ + private void clearAhead(final int num, int delta) throws IOException { + if (num == 0) { + return; + } + + if (terminal.isAnsiSupported()) { + int width = terminal.getWidth(); + int screenCursorCol = getCursorPosition() + delta; + // clear current line + printAnsiSequence("K"); + // if cursor+num wraps, then we need to clear the line(s) below too + int curCol = screenCursorCol % width; + int endCol = (screenCursorCol + num - 1) % width; + int lines = num / width; + if (endCol < curCol) lines++; + for (int i = 0; i < lines; i++) { + printAnsiSequence("B"); + printAnsiSequence("2K"); + } + for (int i = 0; i < lines; i++) { + printAnsiSequence("A"); + } + return; + } + + // print blank extra characters + print(' ', num); + + // we need to flush here so a "clever" console doesn't just ignore the redundancy + // of a space followed by a backspace. +// flush(); + + // reset the visual cursor + back(num); + +// flush(); + } + + /** + * Move the visual cursor backwards without modifying the buffer cursor. + */ + protected void back(final int num) throws IOException { + if (num == 0) return; + if (terminal.isAnsiSupported()) { + int width = getTerminal().getWidth(); + int cursor = getCursorPosition(); + int realCursor = cursor + num; + int realCol = realCursor % width; + int newCol = cursor % width; + int moveup = num / width; + int delta = realCol - newCol; + if (delta < 0) moveup++; + if (moveup > 0) { + printAnsiSequence(moveup + "A"); + } + printAnsiSequence((1 + newCol) + "G"); + return; + } + print(BACKSPACE, num); +// flush(); + } + + /** + * Flush the console output stream. This is important for printout out single characters (like a backspace or + * keyboard) that we want the console to handle immediately. + */ + public void flush() throws IOException { + out.flush(); + } + + private int backspaceAll() throws IOException { + return backspace(Integer.MAX_VALUE); + } + + /** + * Issue num backspaces. + * + * @return the number of characters backed up + */ + private int backspace(final int num) throws IOException { + if (buf.cursor == 0) { + return 0; + } + + int count = 0; + + int termwidth = getTerminal().getWidth(); + int lines = getCursorPosition() / termwidth; + count = moveCursor(-1 * num) * -1; + buf.buffer.delete(buf.cursor, buf.cursor + count); + if (getCursorPosition() / termwidth != lines) { + if (terminal.isAnsiSupported()) { + // debug("doing backspace redraw: " + getCursorPosition() + " on " + termwidth + ": " + lines); + printAnsiSequence("K"); + // if cursor+num wraps, then we need to clear the line(s) below too + // last char printed is one pos less than cursor so we subtract + // one +/* + // TODO: fixme (does not work - test with reverse search with wrapping line and CTRL-E) + int endCol = (getCursorPosition() + num - 1) % termwidth; + int curCol = getCursorPosition() % termwidth; + if (endCol < curCol) lines++; + for (int i = 1; i < lines; i++) { + printAnsiSequence("B"); + printAnsiSequence("2K"); + } + for (int i = 1; i < lines; i++) { + printAnsiSequence("A"); + } + return count; +*/ + } + } + drawBuffer(count); + + return count; + } + + /** + * Issue a backspace. + * + * @return true if successful + */ + public boolean backspace() throws IOException { + return backspace(1) == 1; + } + + protected boolean moveToEnd() throws IOException { + if (buf.cursor == buf.length()) { + return true; + } + return moveCursor(buf.length() - buf.cursor) > 0; + } + + /** + * Delete the character at the current position and redraw the remainder of the buffer. + */ + private boolean deleteCurrentCharacter() throws IOException { + if (buf.length() == 0 || buf.cursor == buf.length()) { + return false; + } + + buf.buffer.deleteCharAt(buf.cursor); + drawBuffer(1); + return true; + } + + /** + * This method is calling while doing a delete-to ("d"), change-to ("c"), + * or yank-to ("y") and it filters out only those movement operations + * that are allowable during those operations. Any operation that isn't + * allow drops you back into movement mode. + * + * @param op The incoming operation to remap + * @return The remaped operation + */ + private Operation viDeleteChangeYankToRemap (Operation op) { + switch (op) { + case VI_EOF_MAYBE: + case ABORT: + case BACKWARD_CHAR: + case FORWARD_CHAR: + case END_OF_LINE: + case VI_MATCH: + case VI_BEGNNING_OF_LINE_OR_ARG_DIGIT: + case VI_ARG_DIGIT: + case VI_PREV_WORD: + case VI_END_WORD: + case VI_CHAR_SEARCH: + case VI_NEXT_WORD: + case VI_FIRST_PRINT: + case VI_GOTO_MARK: + case VI_COLUMN: + case VI_DELETE_TO: + case VI_YANK_TO: + case VI_CHANGE_TO: + return op; + + default: + return Operation.VI_MOVEMENT_MODE; + } + } + + /** + * Deletes the previous character from the cursor position + * @param count number of times to do it. + * @return true if it was done. + * @throws IOException + */ + private boolean viRubout(int count) throws IOException { + boolean ok = true; + for (int i = 0; ok && i < count; i++) { + ok = backspace(); + } + return ok; + } + + /** + * Deletes the character you are sitting on and sucks the rest of + * the line in from the right. + * @param count Number of times to perform the operation. + * @return true if its works, false if it didn't + * @throws IOException + */ + private boolean viDelete(int count) throws IOException { + boolean ok = true; + for (int i = 0; ok && i < count; i++) { + ok = deleteCurrentCharacter(); + } + return ok; + } + + /** + * Switches the case of the current character from upper to lower + * or lower to upper as necessary and advances the cursor one + * position to the right. + * @param count The number of times to repeat + * @return true if it completed successfully, false if not all + * case changes could be completed. + * @throws IOException + */ + private boolean viChangeCase(int count) throws IOException { + boolean ok = true; + for (int i = 0; ok && i < count; i++) { + + ok = buf.cursor < buf.buffer.length (); + if (ok) { + char ch = buf.buffer.charAt(buf.cursor); + if (Character.isUpperCase(ch)) { + ch = Character.toLowerCase(ch); + } + else if (Character.isLowerCase(ch)) { + ch = Character.toUpperCase(ch); + } + buf.buffer.setCharAt(buf.cursor, ch); + drawBuffer(1); + moveCursor(1); + } + } + return ok; + } + + /** + * Implements the vi change character command (in move-mode "r" + * followed by the character to change to). + * @param count Number of times to perform the action + * @param c The character to change to + * @return Whether or not there were problems encountered + * @throws IOException + */ + private boolean viChangeChar(int count, int c) throws IOException { + // EOF, ESC, or CTRL-C aborts. + if (c < 0 || c == '\033' || c == '\003') { + return true; + } + + boolean ok = true; + for (int i = 0; ok && i < count; i++) { + ok = buf.cursor < buf.buffer.length (); + if (ok) { + buf.buffer.setCharAt(buf.cursor, (char) c); + drawBuffer(1); + if (i < (count-1)) { + moveCursor(1); + } + } + } + return ok; + } + + /** + * This is a close facsimile of the actual vi previous word logic. In + * actual vi words are determined by boundaries of identity characterse. + * This logic is a bit more simple and simply looks at white space or + * digits or characters. It should be revised at some point. + * + * @param count number of iterations + * @return true if the move was successful, false otherwise + * @throws IOException + */ + private boolean viPreviousWord(int count) throws IOException { + boolean ok = true; + if (buf.cursor == 0) { + return false; + } + + int pos = buf.cursor - 1; + for (int i = 0; pos > 0 && i < count; i++) { + // If we are on white space, then move back. + while (pos > 0 && isWhitespace(buf.buffer.charAt(pos))) { + --pos; + } + + while (pos > 0 && !isDelimiter(buf.buffer.charAt(pos-1))) { + --pos; + } + + if (pos > 0 && i < (count-1)) { + --pos; + } + } + setCursorPosition(pos); + return ok; + } + + /** + * Performs the vi "delete-to" action, deleting characters between a given + * span of the input line. + * @param startPos The start position + * @param endPos The end position. + * @param isChange If true, then the delete is part of a change operationg + * (e.g. "c$" is change-to-end-of line, so we first must delete to end + * of line to start the change + * @return true if it succeeded, false otherwise + * @throws IOException + */ + private boolean viDeleteTo(int startPos, int endPos, boolean isChange) throws IOException { + if (startPos == endPos) { + return true; + } + + if (endPos < startPos) { + int tmp = endPos; + endPos = startPos; + startPos = tmp; + } + + setCursorPosition(startPos); + buf.cursor = startPos; + buf.buffer.delete(startPos, endPos); + drawBuffer(endPos - startPos); + + // If we are doing a delete operation (e.g. "d$") then don't leave the + // cursor dangling off the end. In reality the "isChange" flag is silly + // what is really happening is that if we are in "move-mode" then the + // cursor can't be moved off the end of the line, but in "edit-mode" it + // is ok, but I have no easy way of knowing which mode we are in. + if (! isChange && startPos > 0 && startPos == buf.length()) { + moveCursor(-1); + } + return true; + } + + /** + * Implement the "vi" yank-to operation. This operation allows you + * to yank the contents of the current line based upon a move operation, + * for exaple "yw" yanks the current word, "3yw" yanks 3 words, etc. + * + * @param startPos The starting position from which to yank + * @param endPos The ending position to which to yank + * @return true if the yank succeeded + * @throws IOException + */ + private boolean viYankTo(int startPos, int endPos) throws IOException { + int cursorPos = startPos; + + if (endPos < startPos) { + int tmp = endPos; + endPos = startPos; + startPos = tmp; + } + + if (startPos == endPos) { + yankBuffer = ""; + return true; + } + + yankBuffer = buf.buffer.substring(startPos, endPos); + + /* + * It was a movement command that moved the cursor to find the + * end position, so put the cursor back where it started. + */ + setCursorPosition(cursorPos); + return true; + } + + /** + * Pasts the yank buffer to the right of the current cursor position + * and moves the cursor to the end of the pasted region. + * + * @param count Number of times to perform the operation. + * @return true if it worked, false otherwise + * @throws IOException + */ + private boolean viPut(int count) throws IOException { + if (yankBuffer.length () == 0) { + return true; + } + if (buf.cursor < buf.buffer.length ()) { + moveCursor(1); + } + for (int i = 0; i < count; i++) { + putString(yankBuffer); + } + moveCursor(-1); + return true; + } + + /** + * Searches forward of the current position for a character and moves + * the cursor onto it. + * @param count Number of times to repeat the process. + * @param ch The character to search for + * @return true if the char was found, false otherwise + * @throws IOException + */ + private boolean viCharSearch(int count, int invokeChar, int ch) throws IOException { + if (ch < 0 || invokeChar < 0) { + return false; + } + + char searchChar = (char)ch; + boolean isForward; + boolean stopBefore; + + /* + * The character stuff turns out to be hairy. Here is how it works: + * f - search forward for ch + * F - search backward for ch + * t - search forward for ch, but stop just before the match + * T - search backward for ch, but stop just after the match + * ; - After [fFtT;], repeat the last search, after ',' reverse it + * , - After [fFtT;], reverse the last search, after ',' repeat it + */ + if (invokeChar == ';' || invokeChar == ',') { + // No recent search done? Then bail + if (charSearchChar == 0) { + return false; + } + + // Reverse direction if switching between ',' and ';' + if (charSearchLastInvokeChar == ';' || charSearchLastInvokeChar == ',') { + if (charSearchLastInvokeChar != invokeChar) { + charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar); + } + } + else { + if (invokeChar == ',') { + charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar); + } + } + + searchChar = charSearchChar; + } + else { + charSearchChar = searchChar; + charSearchFirstInvokeChar = (char) invokeChar; + } + + charSearchLastInvokeChar = (char)invokeChar; + + isForward = Character.isLowerCase(charSearchFirstInvokeChar); + stopBefore = (Character.toLowerCase(charSearchFirstInvokeChar) == 't'); + + boolean ok = false; + + if (isForward) { + while (count-- > 0) { + int pos = buf.cursor + 1; + while (pos < buf.buffer.length()) { + if (buf.buffer.charAt(pos) == searchChar) { + setCursorPosition(pos); + ok = true; + break; + } + ++pos; + } + } + + if (ok) { + if (stopBefore) + moveCursor(-1); + + /* + * When in yank-to, move-to, del-to state we actually want to + * go to the character after the one we landed on to make sure + * that the character we ended up on is included in the + * operation + */ + if (isInViMoveOperationState()) { + moveCursor(1); + } + } + } + else { + while (count-- > 0) { + int pos = buf.cursor - 1; + while (pos >= 0) { + if (buf.buffer.charAt(pos) == searchChar) { + setCursorPosition(pos); + ok = true; + break; + } + --pos; + } + } + + if (ok && stopBefore) + moveCursor(1); + } + + return ok; + } + + private char switchCase(char ch) { + if (Character.isUpperCase(ch)) { + return Character.toLowerCase(ch); + } + return Character.toUpperCase(ch); + } + + /** + * @return true if line reader is in the middle of doing a change-to + * delete-to or yank-to. + */ + private final boolean isInViMoveOperationState() { + return state == State.VI_CHANGE_TO + || state == State.VI_DELETE_TO + || state == State.VI_YANK_TO; + } + + /** + * This is a close facsimile of the actual vi next word logic. + * As with viPreviousWord() this probably needs to be improved + * at some point. + * + * @param count number of iterations + * @return true if the move was successful, false otherwise + * @throws IOException + */ + private boolean viNextWord(int count) throws IOException { + int pos = buf.cursor; + int end = buf.buffer.length(); + + for (int i = 0; pos < end && i < count; i++) { + // Skip over letter/digits + while (pos < end && !isDelimiter(buf.buffer.charAt(pos))) { + ++pos; + } + + /* + * Don't you love special cases? During delete-to and yank-to + * operations the word movement is normal. However, during a + * change-to, the trailing spaces behind the last word are + * left in tact. + */ + if (i < (count-1) || !(state == State.VI_CHANGE_TO)) { + while (pos < end && isDelimiter(buf.buffer.charAt(pos))) { + ++pos; + } + } + } + + setCursorPosition(pos); + return true; + } + + /** + * Implements a close facsimile of the vi end-of-word movement. + * If the character is on white space, it takes you to the end + * of the next word. If it is on the last character of a word + * it takes you to the next of the next word. Any other character + * of a word, takes you to the end of the current word. + * + * @param count Number of times to repeat the action + * @return true if it worked. + * @throws IOException + */ + private boolean viEndWord(int count) throws IOException { + int pos = buf.cursor; + int end = buf.buffer.length(); + + for (int i = 0; pos < end && i < count; i++) { + if (pos < (end-1) + && !isDelimiter(buf.buffer.charAt(pos)) + && isDelimiter(buf.buffer.charAt (pos+1))) { + ++pos; + } + + // If we are on white space, then move back. + while (pos < end && isDelimiter(buf.buffer.charAt(pos))) { + ++pos; + } + + while (pos < (end-1) && !isDelimiter(buf.buffer.charAt(pos+1))) { + ++pos; + } + } + setCursorPosition(pos); + return true; + } + + private boolean previousWord() throws IOException { + while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) { + // nothing + } + + while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) { + // nothing + } + + return true; + } + + private boolean nextWord() throws IOException { + while (isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) { + // nothing + } + + while (!isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) { + // nothing + } + + return true; + } + + /** + * Deletes to the beginning of the word that the cursor is sitting on. + * If the cursor is on white-space, it deletes that and to the beginning + * of the word before it. If the user is not on a word or whitespace + * it deletes up to the end of the previous word. + * + * @param count Number of times to perform the operation + * @return true if it worked, false if you tried to delete too many words + * @throws IOException + */ + private boolean unixWordRubout(int count) throws IOException { + boolean success = true; + StringBuilder killed = new StringBuilder(); + + for (; count > 0; --count) { + if (buf.cursor == 0) { + success = false; + break; + } + + while (isWhitespace(buf.current())) { + char c = buf.current(); + if (c == 0) { + break; + } + + killed.append(c); + backspace(); + } + + while (!isWhitespace(buf.current())) { + char c = buf.current(); + if (c == 0) { + break; + } + + killed.append(c); + backspace(); + } + } + + String copy = killed.reverse().toString(); + killRing.addBackwards(copy); + + return success; + } + + private String insertComment(boolean isViMode) throws IOException { + String comment = this.getCommentBegin (); + setCursorPosition(0); + putString(comment); + if (isViMode) { + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + } + return accept(); + } + + /** + * Similar to putString() but allows the string to be repeated a specific + * number of times, allowing easy support of vi digit arguments to a given + * command. The string is placed as the current cursor position. + * + * @param count The count of times to insert the string. + * @param str The string to insert + * @return true if the operation is a success, false otherwise + * @throws IOException + */ + private boolean insert(int count, final CharSequence str) throws IOException { + for (int i = 0; i < count; i++) { + buf.write(str); + if (mask == null) { + // no masking + print(str); + } else if (mask == NULL_MASK) { + // don't print anything + } else { + print(mask, str.length()); + } + } + drawBuffer(); + return true; + } + + /** + * Implements vi search ("/" or "?"). + * @throws IOException + */ + @SuppressWarnings("fallthrough") + private int viSearch(char searchChar) throws IOException { + boolean isForward = (searchChar == '/'); + + /* + * This is a little gross, I'm sure there is a more appropriate way + * of saving and restoring state. + */ + CursorBuffer origBuffer = buf.copy(); + + // Clear the contents of the current line and + setCursorPosition (0); + killLine(); + + // Our new "prompt" is the character that got us into search mode. + putString(Character.toString(searchChar)); + flush(); + + boolean isAborted = false; + boolean isComplete = false; + + /* + * Readline doesn't seem to do any special character map handling + * here, so I think we are safe. + */ + int ch = -1; + while (!isAborted && !isComplete && (ch = readCharacter()) != -1) { + switch (ch) { + case '\033': // ESC + /* + * The ESC behavior doesn't appear to be readline behavior, + * but it is a little tweak of my own. I like it. + */ + isAborted = true; + break; + case '\010': // Backspace + case '\177': // Delete + backspace(); + /* + * Backspacing through the "prompt" aborts the search. + */ + if (buf.cursor == 0) { + isAborted = true; + } + break; + case '\012': // NL + case '\015': // CR + isComplete = true; + break; + default: + putString(Character.toString((char) ch)); + } + + flush(); + } + + // If we aborted, then put ourself at the end of the original buffer. + if (ch == -1 || isAborted) { + setCursorPosition(0); + killLine(); + putString(origBuffer.buffer); + setCursorPosition(origBuffer.cursor); + return -1; + } + + /* + * The first character of the buffer was the search character itself + * so we discard it. + */ + String searchTerm = buf.buffer.substring(1); + int idx = -1; + + /* + * The semantics of the history thing is gross when you want to + * explicitly iterate over entries (without an iterator) as size() + * returns the actual number of entries in the list but get() + * doesn't work the way you think. + */ + int end = history.index(); + int start = (end <= history.size()) ? 0 : end - history.size(); + + if (isForward) { + for (int i = start; i < end; i++) { + if (history.get(i).toString().contains(searchTerm)) { + idx = i; + break; + } + } + } + else { + for (int i = end-1; i >= start; i--) { + if (history.get(i).toString().contains(searchTerm)) { + idx = i; + break; + } + } + } + + /* + * No match? Then restore what we were working on, but make sure + * the cursor is at the beginning of the line. + */ + if (idx == -1) { + setCursorPosition(0); + killLine(); + putString(origBuffer.buffer); + setCursorPosition(0); + return -1; + } + + /* + * Show the match. + */ + setCursorPosition(0); + killLine(); + putString(history.get(idx)); + setCursorPosition(0); + flush(); + + /* + * While searching really only the "n" and "N" keys are interpreted + * as movement, any other key is treated as if you are editing the + * line with it, so we return it back up to the caller for interpretation. + */ + isComplete = false; + while (!isComplete && (ch = readCharacter()) != -1) { + boolean forward = isForward; + switch (ch) { + case 'p': case 'P': + forward = !isForward; + // Fallthru + case 'n': case 'N': + boolean isMatch = false; + if (forward) { + for (int i = idx+1; !isMatch && i < end; i++) { + if (history.get(i).toString().contains(searchTerm)) { + idx = i; + isMatch = true; + } + } + } + else { + for (int i = idx - 1; !isMatch && i >= start; i--) { + if (history.get(i).toString().contains(searchTerm)) { + idx = i; + isMatch = true; + } + } + } + if (isMatch) { + setCursorPosition(0); + killLine(); + putString(history.get(idx)); + setCursorPosition(0); + } + break; + default: + isComplete = true; + } + flush(); + } + + /* + * Complete? + */ + return ch; + } + + public void setParenBlinkTimeout(int timeout) { + parenBlinkTimeout = timeout; + } + + private void insertClose(String s) throws IOException { + putString(s); + int closePosition = buf.cursor; + + moveCursor(-1); + viMatch(); + + + if (in.isNonBlockingEnabled()) { + in.peek(parenBlinkTimeout); + } + + setCursorPosition(closePosition); + } + + /** + * Implements vi style bracket matching ("%" command). The matching + * bracket for the current bracket type that you are sitting on is matched. + * The logic works like so: + * @return true if it worked, false if the cursor was not on a bracket + * character or if there was no matching bracket. + * @throws IOException + */ + private boolean viMatch() throws IOException { + int pos = buf.cursor; + + if (pos == buf.length()) { + return false; + } + + int type = getBracketType(buf.buffer.charAt (pos)); + int move = (type < 0) ? -1 : 1; + int count = 1; + + if (type == 0) + return false; + + while (count > 0) { + pos += move; + + // Fell off the start or end. + if (pos < 0 || pos >= buf.buffer.length ()) { + return false; + } + + int curType = getBracketType(buf.buffer.charAt (pos)); + if (curType == type) { + ++count; + } + else if (curType == -type) { + --count; + } + } + + /* + * Slight adjustment for delete-to, yank-to, change-to to ensure + * that the matching paren is consumed + */ + if (move > 0 && isInViMoveOperationState()) + ++pos; + + setCursorPosition(pos); + return true; + } + + /** + * Given a character determines what type of bracket it is (paren, + * square, curly, or none). + * @param ch The character to check + * @return 1 is square, 2 curly, 3 parent, or zero for none. The value + * will be negated if it is the closing form of the bracket. + */ + private int getBracketType (char ch) { + switch (ch) { + case '[': return 1; + case ']': return -1; + case '{': return 2; + case '}': return -2; + case '(': return 3; + case ')': return -3; + default: + return 0; + } + } + + private boolean deletePreviousWord() throws IOException { + StringBuilder killed = new StringBuilder(); + char c; + + while (isDelimiter((c = buf.current()))) { + if (c == 0) { + break; + } + + killed.append(c); + backspace(); + } + + while (!isDelimiter((c = buf.current()))) { + if (c == 0) { + break; + } + + killed.append(c); + backspace(); + } + + String copy = killed.reverse().toString(); + killRing.addBackwards(copy); + return true; + } + + private boolean deleteNextWord() throws IOException { + StringBuilder killed = new StringBuilder(); + char c; + + while (isDelimiter((c = buf.nextChar()))) { + if (c == 0) { + break; + } + killed.append(c); + delete(); + } + + while (!isDelimiter((c = buf.nextChar()))) { + if (c == 0) { + break; + } + killed.append(c); + delete(); + } + + String copy = killed.toString(); + killRing.add(copy); + + return true; + } + + private boolean capitalizeWord() throws IOException { + boolean first = true; + int i = 1; + char c; + while (buf.cursor + i - 1< buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) { + buf.buffer.setCharAt(buf.cursor + i - 1, first ? Character.toUpperCase(c) : Character.toLowerCase(c)); + first = false; + i++; + } + drawBuffer(); + moveCursor(i - 1); + return true; + } + + private boolean upCaseWord() throws IOException { + int i = 1; + char c; + while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) { + buf.buffer.setCharAt(buf.cursor + i - 1, Character.toUpperCase(c)); + i++; + } + drawBuffer(); + moveCursor(i - 1); + return true; + } + + private boolean downCaseWord() throws IOException { + int i = 1; + char c; + while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) { + buf.buffer.setCharAt(buf.cursor + i - 1, Character.toLowerCase(c)); + i++; + } + drawBuffer(); + moveCursor(i - 1); + return true; + } + + /** + * Performs character transpose. The character prior to the cursor and the + * character under the cursor are swapped and the cursor is advanced one + * character unless you are already at the end of the line. + * + * @param count The number of times to perform the transpose + * @return true if the operation succeeded, false otherwise (e.g. transpose + * cannot happen at the beginning of the line). + * @throws IOException + */ + private boolean transposeChars(int count) throws IOException { + for (; count > 0; --count) { + if (buf.cursor == 0 || buf.cursor == buf.buffer.length()) { + return false; + } + + int first = buf.cursor-1; + int second = buf.cursor; + + char tmp = buf.buffer.charAt (first); + buf.buffer.setCharAt(first, buf.buffer.charAt(second)); + buf.buffer.setCharAt(second, tmp); + + // This could be done more efficiently by only re-drawing at the end. + moveInternal(-1); + drawBuffer(); + moveInternal(2); + } + + return true; + } + + public boolean isKeyMap(String name) { + // Current keymap. + KeyMap map = consoleKeys.getKeys(); + KeyMap mapByName = consoleKeys.getKeyMaps().get(name); + + if (mapByName == null) + return false; + + /* + * This may not be safe to do, but there doesn't appear to be a + * clean way to find this information out. + */ + return map == mapByName; + } + + + /** + * The equivalent of hitting <RET>. The line is considered + * complete and is returned. + * + * @return The completed line of text. + * @throws IOException + */ + public String accept() throws IOException { + moveToEnd(); + println(); // output newline + flush(); + return finishBuffer(); + } + + private void abort() throws IOException { + beep(); + buf.clear(); + println(); + redrawLine(); + } + + /** + * Move the cursor where characters. + * + * @param num If less than 0, move abs(where) to the left, otherwise move where to the right. + * @return The number of spaces we moved + */ + public int moveCursor(final int num) throws IOException { + int where = num; + + if ((buf.cursor == 0) && (where <= 0)) { + return 0; + } + + if ((buf.cursor == buf.buffer.length()) && (where >= 0)) { + return 0; + } + + if ((buf.cursor + where) < 0) { + where = -buf.cursor; + } + else if ((buf.cursor + where) > buf.buffer.length()) { + where = buf.buffer.length() - buf.cursor; + } + + moveInternal(where); + + return where; + } + + /** + * Move the cursor where characters, without checking the current buffer. + * + * @param where the number of characters to move to the right or left. + */ + private void moveInternal(final int where) throws IOException { + // debug ("move cursor " + where + " (" + // + buf.cursor + " => " + (buf.cursor + where) + ")"); + buf.cursor += where; + + if (terminal.isAnsiSupported()) { + if (where < 0) { + back(Math.abs(where)); + } else { + int width = getTerminal().getWidth(); + int cursor = getCursorPosition(); + int oldLine = (cursor - where) / width; + int newLine = cursor / width; + if (newLine > oldLine) { + printAnsiSequence((newLine - oldLine) + "B"); + } + printAnsiSequence(1 +(cursor % width) + "G"); + } +// flush(); + return; + } + + char c; + + if (where < 0) { + int len = 0; + for (int i = buf.cursor; i < buf.cursor - where; i++) { + if (buf.buffer.charAt(i) == '\t') { + len += TAB_WIDTH; + } + else { + len++; + } + } + + char chars[] = new char[len]; + Arrays.fill(chars, BACKSPACE); + out.write(chars); + + return; + } + else if (buf.cursor == 0) { + return; + } + else if (mask != null) { + c = mask; + } + else { + print(buf.buffer.substring(buf.cursor - where, buf.cursor).toCharArray()); + return; + } + + // null character mask: don't output anything + if (mask == NULL_MASK) { + return; + } + + print(c, Math.abs(where)); + } + + // FIXME: replace() is not used + + public final boolean replace(final int num, final String replacement) { + buf.buffer.replace(buf.cursor - num, buf.cursor, replacement); + try { + moveCursor(-num); + drawBuffer(Math.max(0, num - replacement.length())); + moveCursor(replacement.length()); + } + catch (IOException e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Read a character from the console. + * + * @return the character, or -1 if an EOF is received. + */ + public final int readCharacter() throws IOException { + int c = reader.read(); + if (c >= 0) { + Log.trace("Keystroke: ", c); + // clear any echo characters + if (terminal.isSupported()) { + clearEcho(c); + } + } + return c; + } + + /** + * Clear the echoed characters for the specified character code. + */ + private int clearEcho(final int c) throws IOException { + // if the terminal is not echoing, then ignore + if (!terminal.isEchoEnabled()) { + return 0; + } + + // otherwise, clear + int num = countEchoCharacters(c); + back(num); + drawBuffer(num); + + return num; + } + + private int countEchoCharacters(final int c) { + // tabs as special: we need to determine the number of spaces + // to cancel based on what out current cursor position is + if (c == 9) { + int tabStop = 8; // will this ever be different? + int position = getCursorPosition(); + + return tabStop - (position % tabStop); + } + + return getPrintableCharacters(c).length(); + } + + /** + * Return the number of characters that will be printed when the specified + * character is echoed to the screen + * + * Adapted from cat by Torbjorn Granlund, as repeated in stty by David MacKenzie. + */ + private StringBuilder getPrintableCharacters(final int ch) { + StringBuilder sbuff = new StringBuilder(); + + if (ch >= 32) { + if (ch < 127) { + sbuff.append(ch); + } + else if (ch == 127) { + sbuff.append('^'); + sbuff.append('?'); + } + else { + sbuff.append('M'); + sbuff.append('-'); + + if (ch >= (128 + 32)) { + if (ch < (128 + 127)) { + sbuff.append((char) (ch - 128)); + } + else { + sbuff.append('^'); + sbuff.append('?'); + } + } + else { + sbuff.append('^'); + sbuff.append((char) (ch - 128 + 64)); + } + } + } + else { + sbuff.append('^'); + sbuff.append((char) (ch + 64)); + } + + return sbuff; + } + + public final int readCharacter(final char... allowed) throws IOException { + // if we restrict to a limited set and the current character is not in the set, then try again. + char c; + + Arrays.sort(allowed); // always need to sort before binarySearch + + while (Arrays.binarySearch(allowed, c = (char) readCharacter()) < 0) { + // nothing + } + + return c; + } + + // + // Key Bindings + // + + public static final String JLINE_COMPLETION_THRESHOLD = "jline.completion.threshold"; + + // + // Line Reading + // + + /** + * Read the next line and return the contents of the buffer. + */ + public String readLine() throws IOException { + return readLine((String) null); + } + + /** + * Read the next line with the specified character mask. If null, then + * characters will be echoed. If 0, then no characters will be echoed. + */ + public String readLine(final Character mask) throws IOException { + return readLine(null, mask); + } + + public String readLine(final String prompt) throws IOException { + return readLine(prompt, null); + } + + /** + * Sets the current keymap by name. Supported keymaps are "emacs", + * "vi-insert", "vi-move". + * @param name The name of the keymap to switch to + * @return true if the keymap was set, or false if the keymap is + * not recognized. + */ + public boolean setKeyMap(String name) { + return consoleKeys.setKeyMap(name); + } + + /** + * Returns the name of the current key mapping. + * @return the name of the key mapping. This will be the canonical name + * of the current mode of the key map and may not reflect the name that + * was used with {@link #setKeyMap(String)}. + */ + public String getKeyMap() { + return consoleKeys.getKeys().getName(); + } + + /** + * Read a line from the in {@link InputStream}, and return the line + * (without any trailing newlines). + * + * @param prompt The prompt to issue to the console, may be null. + * @return A line that is read from the terminal, or null if there was null input (e.g., CTRL-D + * was pressed). + */ + public String readLine(String prompt, final Character mask) throws IOException { + // prompt may be null + // mask may be null + + /* + * This is the accumulator for VI-mode repeat count. That is, while in + * move mode, if you type 30x it will delete 30 characters. This is + * where the "30" is accumulated until the command is struck. + */ + int repeatCount = 0; + + // FIXME: This blows, each call to readLine will reset the console's state which doesn't seem very nice. + this.mask = mask; + if (prompt != null) { + setPrompt(prompt); + } + else { + prompt = getPrompt(); + } + + try { + if (!terminal.isSupported()) { + beforeReadLine(prompt, mask); + } + + if (prompt != null && prompt.length() > 0) { + out.write(prompt); + out.flush(); + } + + // if the terminal is unsupported, just use plain-java reading + if (!terminal.isSupported()) { + return readLineSimple(); + } + + if (handleUserInterrupt && (terminal instanceof UnixTerminal)) { + ((UnixTerminal) terminal).disableInterruptCharacter(); + } + + String originalPrompt = this.prompt; + + state = State.NORMAL; + + boolean success = true; + + StringBuilder sb = new StringBuilder(); + Stack pushBackChar = new Stack(); + while (true) { + int c = pushBackChar.isEmpty() ? readCharacter() : pushBackChar.pop (); + if (c == -1) { + return null; + } + sb.appendCodePoint(c); + + if (recording) { + macro += new String(new int[]{c}, 0, 1); + } + + Object o = getKeys().getBound( sb ); + /* + * The kill ring keeps record of whether or not the + * previous command was a yank or a kill. We reset + * that state here if needed. + */ + if (!recording && !(o instanceof KeyMap)) { + if (o != Operation.YANK_POP && o != Operation.YANK) { + killRing.resetLastYank(); + } + if (o != Operation.KILL_LINE && o != Operation.KILL_WHOLE_LINE + && o != Operation.BACKWARD_KILL_WORD && o != Operation.KILL_WORD + && o != Operation.UNIX_LINE_DISCARD && o != Operation.UNIX_WORD_RUBOUT) { + killRing.resetLastKill(); + } + } + + if (o == Operation.DO_LOWERCASE_VERSION) { + sb.setLength( sb.length() - 1); + sb.append( Character.toLowerCase( (char) c )); + o = getKeys().getBound( sb ); + } + + /* + * A KeyMap indicates that the key that was struck has a + * number of keys that can follow it as indicated in the + * map. This is used primarily for Emacs style ESC-META-x + * lookups. Since more keys must follow, go back to waiting + * for the next key. + */ + if ( o instanceof KeyMap ) { + /* + * The ESC key (#27) is special in that it is ambiguous until + * you know what is coming next. The ESC could be a literal + * escape, like the user entering vi-move mode, or it could + * be part of a terminal control sequence. The following + * logic attempts to disambiguate things in the same + * fashion as regular vi or readline. + * + * When ESC is encountered and there is no other pending + * character in the pushback queue, then attempt to peek + * into the input stream (if the feature is enabled) for + * 150ms. If nothing else is coming, then assume it is + * not a terminal control sequence, but a raw escape. + */ + if (c == 27 + && pushBackChar.isEmpty() + && in.isNonBlockingEnabled() + && in.peek(escapeTimeout) == -2) { + o = ((KeyMap) o).getAnotherKey(); + if (o == null || o instanceof KeyMap) { + continue; + } + sb.setLength(0); + } + else { + continue; + } + } + + /* + * If we didn't find a binding for the key and there is + * more than one character accumulated then start checking + * the largest span of characters from the beginning to + * see if there is a binding for them. + * + * For example if our buffer has ESC,CTRL-M,C the getBound() + * called previously indicated that there is no binding for + * this sequence, so this then checks ESC,CTRL-M, and failing + * that, just ESC. Each keystroke that is pealed off the end + * during these tests is stuffed onto the pushback buffer so + * they won't be lost. + * + * If there is no binding found, then we go back to waiting for + * input. + */ + while ( o == null && sb.length() > 0 ) { + c = sb.charAt( sb.length() - 1 ); + sb.setLength( sb.length() - 1 ); + Object o2 = getKeys().getBound( sb ); + if ( o2 instanceof KeyMap ) { + o = ((KeyMap) o2).getAnotherKey(); + if ( o == null ) { + continue; + } else { + pushBackChar.push( (char) c ); + } + } + } + + if ( o == null ) { + continue; + } + Log.trace("Binding: ", o); + + + // Handle macros + if (o instanceof String) { + String macro = (String) o; + for (int i = 0; i < macro.length(); i++) { + pushBackChar.push(macro.charAt(macro.length() - 1 - i)); + } + sb.setLength( 0 ); + continue; + } + + // Handle custom callbacks + //original code: +// if (o instanceof ActionListener) { +// ((ActionListener) o).actionPerformed(null); +// sb.setLength( 0 ); +// continue; +// } + //using reflection to avoid dependency on java.desktop: + try { + Class actionListener = + Class.forName("java.awt.event.ActionListener", false, ClassLoader.getSystemClassLoader()); + Class actionEvent = + Class.forName("java.awt.event.ActionEvent", false, ClassLoader.getSystemClassLoader()); + if (actionListener.isAssignableFrom(o.getClass())) { + Method actionPerformed = + actionListener.getMethod("actionPerformed", actionEvent); + try { + actionPerformed.invoke(o, (Object) null); + } catch (InvocationTargetException ex ) { + Log.error("Exception while running registered action", ex); + } + sb.setLength( 0 ); + continue; + } + } catch (ReflectiveOperationException ex) { + //ignore + } + + // Search mode. + // + // Note that we have to do this first, because if there is a command + // not linked to a search command, we leave the search mode and fall + // through to the normal state. + if (state == State.SEARCH || state == State.FORWARD_SEARCH) { + int cursorDest = -1; + switch ( ((Operation) o )) { + case ABORT: + state = State.NORMAL; + buf.clear(); + buf.buffer.append(searchTerm); + break; + + case REVERSE_SEARCH_HISTORY: + state = State.SEARCH; + if (searchTerm.length() == 0) { + searchTerm.append(previousSearchTerm); + } + + if (searchIndex > 0) { + searchIndex = searchBackwards(searchTerm.toString(), searchIndex); + } + break; + + case FORWARD_SEARCH_HISTORY: + state = State.FORWARD_SEARCH; + if (searchTerm.length() == 0) { + searchTerm.append(previousSearchTerm); + } + + if (searchIndex > -1 && searchIndex < history.size() - 1) { + searchIndex = searchForwards(searchTerm.toString(), searchIndex); + } + break; + + case BACKWARD_DELETE_CHAR: + if (searchTerm.length() > 0) { + searchTerm.deleteCharAt(searchTerm.length() - 1); + if (state == State.SEARCH) { + searchIndex = searchBackwards(searchTerm.toString()); + } else { + searchIndex = searchForwards(searchTerm.toString()); + } + } + break; + + case SELF_INSERT: + searchTerm.appendCodePoint(c); + if (state == State.SEARCH) { + searchIndex = searchBackwards(searchTerm.toString()); + } else { + searchIndex = searchForwards(searchTerm.toString()); + } + break; + + default: + // Set buffer and cursor position to the found string. + if (searchIndex != -1) { + history.moveTo(searchIndex); + // set cursor position to the found string + cursorDest = history.current().toString().indexOf(searchTerm.toString()); + } + state = State.NORMAL; + break; + } + + // if we're still in search mode, print the search status + if (state == State.SEARCH || state == State.FORWARD_SEARCH) { + if (searchTerm.length() == 0) { + if (state == State.SEARCH) { + printSearchStatus("", ""); + } else { + printForwardSearchStatus("", ""); + } + searchIndex = -1; + } else { + if (searchIndex == -1) { + beep(); + printSearchStatus(searchTerm.toString(), ""); + } else if (state == State.SEARCH) { + printSearchStatus(searchTerm.toString(), history.get(searchIndex).toString()); + } else { + printForwardSearchStatus(searchTerm.toString(), history.get(searchIndex).toString()); + } + } + } + // otherwise, restore the line + else { + restoreLine(originalPrompt, cursorDest); + } + } + if (state != State.SEARCH && state != State.FORWARD_SEARCH) { + /* + * If this is still false at the end of the switch, then + * we reset our repeatCount to 0. + */ + boolean isArgDigit = false; + + /* + * Every command that can be repeated a specified number + * of times, needs to know how many times to repeat, so + * we figure that out here. + */ + int count = (repeatCount == 0) ? 1 : repeatCount; + + /* + * Default success to true. You only need to explicitly + * set it if something goes wrong. + */ + success = true; + + if (o instanceof Operation) { + Operation op = (Operation)o; + /* + * Current location of the cursor (prior to the operation). + * These are used by vi *-to operation (e.g. delete-to) + * so we know where we came from. + */ + int cursorStart = buf.cursor; + State origState = state; + + /* + * If we are on a "vi" movement based operation, then we + * need to restrict the sets of inputs pretty heavily. + */ + if (state == State.VI_CHANGE_TO + || state == State.VI_YANK_TO + || state == State.VI_DELETE_TO) { + + op = viDeleteChangeYankToRemap(op); + } + + switch ( op ) { + case COMPLETE: // tab + // There is an annoyance with tab completion in that + // sometimes the user is actually pasting input in that + // has physical tabs in it. This attempts to look at how + // quickly a character follows the tab, if the character + // follows *immediately*, we assume it is a tab literal. + boolean isTabLiteral = false; + if (copyPasteDetection + && c == 9 + && (!pushBackChar.isEmpty() + || (in.isNonBlockingEnabled() && in.peek(escapeTimeout) != -2))) { + isTabLiteral = true; + } + + if (! isTabLiteral) { + success = complete(); + } + else { + putString(sb); + } + break; + + case POSSIBLE_COMPLETIONS: + printCompletionCandidates(); + break; + + case BEGINNING_OF_LINE: + success = setCursorPosition(0); + break; + + case YANK: + success = yank(); + break; + + case YANK_POP: + success = yankPop(); + break; + + case KILL_LINE: // CTRL-K + success = killLine(); + break; + + case KILL_WHOLE_LINE: + success = setCursorPosition(0) && killLine(); + break; + + case CLEAR_SCREEN: // CTRL-L + success = clearScreen(); + redrawLine(); + break; + + case OVERWRITE_MODE: + buf.setOverTyping(!buf.isOverTyping()); + break; + + case SELF_INSERT: + putString(sb); + break; + + case ACCEPT_LINE: + return accept(); + + case ABORT: + if (searchTerm == null) { + abort(); + } + break; + + case INTERRUPT: + if (handleUserInterrupt) { + println(); + flush(); + String partialLine = buf.buffer.toString(); + buf.clear(); + history.moveToEnd(); + throw new UserInterruptException(partialLine); + } + break; + + /* + * VI_MOVE_ACCEPT_LINE is the result of an ENTER + * while in move mode. This is the same as a normal + * ACCEPT_LINE, except that we need to enter + * insert mode as well. + */ + case VI_MOVE_ACCEPT_LINE: + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + return accept(); + + case BACKWARD_WORD: + success = previousWord(); + break; + + case FORWARD_WORD: + success = nextWord(); + break; + + case PREVIOUS_HISTORY: + success = moveHistory(false); + break; + + /* + * According to bash/readline move through history + * in "vi" mode will move the cursor to the + * start of the line. If there is no previous + * history, then the cursor doesn't move. + */ + case VI_PREVIOUS_HISTORY: + success = moveHistory(false, count) + && setCursorPosition(0); + break; + + case NEXT_HISTORY: + success = moveHistory(true); + break; + + /* + * According to bash/readline move through history + * in "vi" mode will move the cursor to the + * start of the line. If there is no next history, + * then the cursor doesn't move. + */ + case VI_NEXT_HISTORY: + success = moveHistory(true, count) + && setCursorPosition(0); + break; + + case BACKWARD_DELETE_CHAR: // backspace + success = backspace(); + break; + + case EXIT_OR_DELETE_CHAR: + if (buf.buffer.length() == 0) { + return null; + } + success = deleteCurrentCharacter(); + break; + + case DELETE_CHAR: // delete + success = deleteCurrentCharacter(); + break; + + case BACKWARD_CHAR: + success = moveCursor(-(count)) != 0; + break; + + case FORWARD_CHAR: + success = moveCursor(count) != 0; + break; + + case UNIX_LINE_DISCARD: + success = resetLine(); + break; + + case UNIX_WORD_RUBOUT: + success = unixWordRubout(count); + break; + + case BACKWARD_KILL_WORD: + success = deletePreviousWord(); + break; + + case KILL_WORD: + success = deleteNextWord(); + break; + + case BEGINNING_OF_HISTORY: + success = history.moveToFirst(); + if (success) { + setBuffer(history.current()); + } + break; + + case END_OF_HISTORY: + success = history.moveToLast(); + if (success) { + setBuffer(history.current()); + } + break; + + case HISTORY_SEARCH_BACKWARD: + searchTerm = new StringBuffer(buf.upToCursor()); + searchIndex = searchBackwards(searchTerm.toString(), history.index(), true); + + if (searchIndex == -1) { + beep(); + } else { + // Maintain cursor position while searching. + success = history.moveTo(searchIndex); + if (success) { + setBufferKeepPos(history.current()); + } + } + break; + + case HISTORY_SEARCH_FORWARD: + searchTerm = new StringBuffer(buf.upToCursor()); + int index = history.index() + 1; + + if (index == history.size()) { + history.moveToEnd(); + setBufferKeepPos(searchTerm.toString()); + } else if (index < history.size()) { + searchIndex = searchForwards(searchTerm.toString(), index, true); + if (searchIndex == -1) { + beep(); + } else { + // Maintain cursor position while searching. + success = history.moveTo(searchIndex); + if (success) { + setBufferKeepPos(history.current()); + } + } + } + break; + + case REVERSE_SEARCH_HISTORY: + if (searchTerm != null) { + previousSearchTerm = searchTerm.toString(); + } + searchTerm = new StringBuffer(buf.buffer); + state = State.SEARCH; + if (searchTerm.length() > 0) { + searchIndex = searchBackwards(searchTerm.toString()); + if (searchIndex == -1) { + beep(); + } + printSearchStatus(searchTerm.toString(), + searchIndex > -1 ? history.get(searchIndex).toString() : ""); + } else { + searchIndex = -1; + printSearchStatus("", ""); + } + break; + + case FORWARD_SEARCH_HISTORY: + if (searchTerm != null) { + previousSearchTerm = searchTerm.toString(); + } + searchTerm = new StringBuffer(buf.buffer); + state = State.FORWARD_SEARCH; + if (searchTerm.length() > 0) { + searchIndex = searchForwards(searchTerm.toString()); + if (searchIndex == -1) { + beep(); + } + printForwardSearchStatus(searchTerm.toString(), + searchIndex > -1 ? history.get(searchIndex).toString() : ""); + } else { + searchIndex = -1; + printForwardSearchStatus("", ""); + } + break; + + case CAPITALIZE_WORD: + success = capitalizeWord(); + break; + + case UPCASE_WORD: + success = upCaseWord(); + break; + + case DOWNCASE_WORD: + success = downCaseWord(); + break; + + case END_OF_LINE: + success = moveToEnd(); + break; + + case TAB_INSERT: + putString( "\t" ); + break; + + case RE_READ_INIT_FILE: + consoleKeys.loadKeys(appName, inputrcUrl); + break; + + case START_KBD_MACRO: + recording = true; + break; + + case END_KBD_MACRO: + recording = false; + macro = macro.substring(0, macro.length() - sb.length()); + break; + + case CALL_LAST_KBD_MACRO: + for (int i = 0; i < macro.length(); i++) { + pushBackChar.push(macro.charAt(macro.length() - 1 - i)); + } + sb.setLength( 0 ); + break; + + case VI_EDITING_MODE: + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case VI_MOVEMENT_MODE: + /* + * If we are re-entering move mode from an + * aborted yank-to, delete-to, change-to then + * don't move the cursor back. The cursor is + * only move on an expclit entry to movement + * mode. + */ + if (state == State.NORMAL) { + moveCursor(-1); + } + consoleKeys.setKeyMap(KeyMap.VI_MOVE); + break; + + case VI_INSERTION_MODE: + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case VI_APPEND_MODE: + moveCursor(1); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case VI_APPEND_EOL: + success = moveToEnd(); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + /* + * Handler for CTRL-D. Attempts to follow readline + * behavior. If the line is empty, then it is an EOF + * otherwise it is as if the user hit enter. + */ + case VI_EOF_MAYBE: + if (buf.buffer.length() == 0) { + return null; + } + return accept(); + + case TRANSPOSE_CHARS: + success = transposeChars(count); + break; + + case INSERT_COMMENT: + return insertComment (false); + + case INSERT_CLOSE_CURLY: + insertClose("}"); + break; + + case INSERT_CLOSE_PAREN: + insertClose(")"); + break; + + case INSERT_CLOSE_SQUARE: + insertClose("]"); + break; + + case VI_INSERT_COMMENT: + return insertComment (true); + + case VI_MATCH: + success = viMatch (); + break; + + case VI_SEARCH: + int lastChar = viSearch(sb.charAt (0)); + if (lastChar != -1) { + pushBackChar.push((char)lastChar); + } + break; + + case VI_ARG_DIGIT: + repeatCount = (repeatCount * 10) + sb.charAt(0) - '0'; + isArgDigit = true; + break; + + case VI_BEGNNING_OF_LINE_OR_ARG_DIGIT: + if (repeatCount > 0) { + repeatCount = (repeatCount * 10) + sb.charAt(0) - '0'; + isArgDigit = true; + } + else { + success = setCursorPosition(0); + } + break; + + case VI_FIRST_PRINT: + success = setCursorPosition(0) && viNextWord(1); + break; + + case VI_PREV_WORD: + success = viPreviousWord(count); + break; + + case VI_NEXT_WORD: + success = viNextWord(count); + break; + + case VI_END_WORD: + success = viEndWord(count); + break; + + case VI_INSERT_BEG: + success = setCursorPosition(0); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case VI_RUBOUT: + success = viRubout(count); + break; + + case VI_DELETE: + success = viDelete(count); + break; + + case VI_DELETE_TO: + /* + * This is a weird special case. In vi + * "dd" deletes the current line. So if we + * get a delete-to, followed by a delete-to, + * we delete the line. + */ + if (state == State.VI_DELETE_TO) { + success = setCursorPosition(0) && killLine(); + state = origState = State.NORMAL; + } + else { + state = State.VI_DELETE_TO; + } + break; + + case VI_YANK_TO: + // Similar to delete-to, a "yy" yanks the whole line. + if (state == State.VI_YANK_TO) { + yankBuffer = buf.buffer.toString(); + state = origState = State.NORMAL; + } + else { + state = State.VI_YANK_TO; + } + break; + + case VI_CHANGE_TO: + if (state == State.VI_CHANGE_TO) { + success = setCursorPosition(0) && killLine(); + state = origState = State.NORMAL; + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + } + else { + state = State.VI_CHANGE_TO; + } + break; + + case VI_KILL_WHOLE_LINE: + success = setCursorPosition(0) && killLine(); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case VI_PUT: + success = viPut(count); + break; + + case VI_CHAR_SEARCH: { + // ';' and ',' don't need another character. They indicate repeat next or repeat prev. + int searchChar = (c != ';' && c != ',') + ? (pushBackChar.isEmpty() + ? readCharacter() + : pushBackChar.pop ()) + : 0; + + success = viCharSearch(count, c, searchChar); + } + break; + + case VI_CHANGE_CASE: + success = viChangeCase(count); + break; + + case VI_CHANGE_CHAR: + success = viChangeChar(count, + pushBackChar.isEmpty() + ? readCharacter() + : pushBackChar.pop()); + break; + + case VI_DELETE_TO_EOL: + success = viDeleteTo(buf.cursor, buf.buffer.length(), false); + break; + + case VI_CHANGE_TO_EOL: + success = viDeleteTo(buf.cursor, buf.buffer.length(), true); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + break; + + case EMACS_EDITING_MODE: + consoleKeys.setKeyMap(KeyMap.EMACS); + break; + + default: + break; + } + + /* + * If we were in a yank-to, delete-to, move-to + * when this operation started, then fall back to + */ + if (origState != State.NORMAL) { + if (origState == State.VI_DELETE_TO) { + success = viDeleteTo(cursorStart, buf.cursor, false); + } + else if (origState == State.VI_CHANGE_TO) { + success = viDeleteTo(cursorStart, buf.cursor, true); + consoleKeys.setKeyMap(KeyMap.VI_INSERT); + } + else if (origState == State.VI_YANK_TO) { + success = viYankTo(cursorStart, buf.cursor); + } + state = State.NORMAL; + } + + /* + * Another subtly. The check for the NORMAL state is + * to ensure that we do not clear out the repeat + * count when in delete-to, yank-to, or move-to modes. + */ + if (state == State.NORMAL && !isArgDigit) { + /* + * If the operation performed wasn't a vi argument + * digit, then clear out the current repeatCount; + */ + repeatCount = 0; + } + + if (state != State.SEARCH && state != State.FORWARD_SEARCH) { + previousSearchTerm = ""; + searchTerm = null; + searchIndex = -1; + } + } + } + if (!success) { + beep(); + } + sb.setLength( 0 ); + flush(); + } + } + finally { + if (!terminal.isSupported()) { + afterReadLine(); + } + if (handleUserInterrupt && (terminal instanceof UnixTerminal)) { + ((UnixTerminal) terminal).enableInterruptCharacter(); + } + } + } + + /** + * Read a line for unsupported terminals. + */ + private String readLineSimple() throws IOException { + StringBuilder buff = new StringBuilder(); + + if (skipLF) { + skipLF = false; + + int i = readCharacter(); + + if (i == -1 || i == '\r') { + return buff.toString(); + } else if (i == '\n') { + // ignore + } else { + buff.append((char) i); + } + } + + while (true) { + int i = readCharacter(); + + if (i == -1 && buff.length() == 0) { + return null; + } + + if (i == -1 || i == '\n') { + return buff.toString(); + } else if (i == '\r') { + skipLF = true; + return buff.toString(); + } else { + buff.append((char) i); + } + } + } + + // + // Completion + // + + private final List completers = new LinkedList(); + + private CompletionHandler completionHandler = new CandidateListCompletionHandler(); + + /** + * Add the specified {@link jline.console.completer.Completer} to the list of handlers for tab-completion. + * + * @param completer the {@link jline.console.completer.Completer} to add + * @return true if it was successfully added + */ + public boolean addCompleter(final Completer completer) { + return completers.add(completer); + } + + /** + * Remove the specified {@link jline.console.completer.Completer} from the list of handlers for tab-completion. + * + * @param completer The {@link Completer} to remove + * @return True if it was successfully removed + */ + public boolean removeCompleter(final Completer completer) { + return completers.remove(completer); + } + + /** + * Returns an unmodifiable list of all the completers. + */ + public Collection getCompleters() { + return Collections.unmodifiableList(completers); + } + + public void setCompletionHandler(final CompletionHandler handler) { + this.completionHandler = checkNotNull(handler); + } + + public CompletionHandler getCompletionHandler() { + return this.completionHandler; + } + + /** + * Use the completers to modify the buffer with the appropriate completions. + * + * @return true if successful + */ + protected boolean complete() throws IOException { + // debug ("tab for (" + buf + ")"); + if (completers.size() == 0) { + return false; + } + + List candidates = new LinkedList(); + String bufstr = buf.buffer.toString(); + int cursor = buf.cursor; + + int position = -1; + + for (Completer comp : completers) { + if ((position = comp.complete(bufstr, cursor, candidates)) != -1) { + break; + } + } + + return candidates.size() != 0 && getCompletionHandler().complete(this, candidates, position); + } + + protected void printCompletionCandidates() throws IOException { + // debug ("tab for (" + buf + ")"); + if (completers.size() == 0) { + return; + } + + List candidates = new LinkedList(); + String bufstr = buf.buffer.toString(); + int cursor = buf.cursor; + + for (Completer comp : completers) { + if (comp.complete(bufstr, cursor, candidates) != -1) { + break; + } + } + CandidateListCompletionHandler.printCandidates(this, candidates); + drawLine(); + } + + /** + * The number of tab-completion candidates above which a warning will be + * prompted before showing all the candidates. + */ + private int autoprintThreshold = Configuration.getInteger(JLINE_COMPLETION_THRESHOLD, 100); // same default as bash + + /** + * @param threshold the number of candidates to print without issuing a warning. + */ + public void setAutoprintThreshold(final int threshold) { + this.autoprintThreshold = threshold; + } + + /** + * @return the number of candidates to print without issuing a warning. + */ + public int getAutoprintThreshold() { + return autoprintThreshold; + } + + private boolean paginationEnabled; + + /** + * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal. + */ + public void setPaginationEnabled(final boolean enabled) { + this.paginationEnabled = enabled; + } + + /** + * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal. + */ + public boolean isPaginationEnabled() { + return paginationEnabled; + } + + // + // History + // + + private History history = new MemoryHistory(); + + public void setHistory(final History history) { + this.history = history; + } + + public History getHistory() { + return history; + } + + private boolean historyEnabled = true; + + /** + * Whether or not to add new commands to the history buffer. + */ + public void setHistoryEnabled(final boolean enabled) { + this.historyEnabled = enabled; + } + + /** + * Whether or not to add new commands to the history buffer. + */ + public boolean isHistoryEnabled() { + return historyEnabled; + } + + /** + * Used in "vi" mode for argumented history move, to move a specific + * number of history entries forward or back. + * + * @param next If true, move forward + * @param count The number of entries to move + * @return true if the move was successful + * @throws IOException + */ + private boolean moveHistory(final boolean next, int count) throws IOException { + boolean ok = true; + for (int i = 0; i < count && (ok = moveHistory(next)); i++) { + /* empty */ + } + return ok; + } + + /** + * Move up or down the history tree. + */ + private boolean moveHistory(final boolean next) throws IOException { + if (next && !history.next()) { + return false; + } + else if (!next && !history.previous()) { + return false; + } + + setBuffer(history.current()); + + return true; + } + + // + // Printing + // + + public static final String CR = Configuration.getLineSeparator(); + + /** + * Output the specified character to the output stream without manipulating the current buffer. + */ + private void print(final int c) throws IOException { + if (c == '\t') { + char chars[] = new char[TAB_WIDTH]; + Arrays.fill(chars, ' '); + out.write(chars); + return; + } + + out.write(c); + } + + /** + * Output the specified characters to the output stream without manipulating the current buffer. + */ + private void print(final char... buff) throws IOException { + int len = 0; + for (char c : buff) { + if (c == '\t') { + len += TAB_WIDTH; + } + else { + len++; + } + } + + char chars[]; + if (len == buff.length) { + chars = buff; + } + else { + chars = new char[len]; + int pos = 0; + for (char c : buff) { + if (c == '\t') { + Arrays.fill(chars, pos, pos + TAB_WIDTH, ' '); + pos += TAB_WIDTH; + } + else { + chars[pos] = c; + pos++; + } + } + } + + out.write(chars); + } + + private void print(final char c, final int num) throws IOException { + if (num == 1) { + print(c); + } + else { + char[] chars = new char[num]; + Arrays.fill(chars, c); + print(chars); + } + } + + /** + * Output the specified string to the output stream (but not the buffer). + */ + public final void print(final CharSequence s) throws IOException { + print(checkNotNull(s).toString().toCharArray()); + } + + public final void println(final CharSequence s) throws IOException { + print(checkNotNull(s).toString().toCharArray()); + println(); + } + + /** + * Output a platform-dependant newline. + */ + public final void println() throws IOException { + print(CR); +// flush(); + } + + // + // Actions + // + + /** + * Issue a delete. + * + * @return true if successful + */ + public final boolean delete() throws IOException { + if (buf.cursor == buf.buffer.length()) { + return false; + } + + buf.buffer.delete(buf.cursor, buf.cursor + 1); + drawBuffer(1); + + return true; + } + + /** + * Kill the buffer ahead of the current cursor position. + * + * @return true if successful + */ + public boolean killLine() throws IOException { + int cp = buf.cursor; + int len = buf.buffer.length(); + + if (cp >= len) { + return false; + } + + int num = len - cp; + clearAhead(num, 0); + + char[] killed = new char[num]; + buf.buffer.getChars(cp, (cp + num), killed, 0); + buf.buffer.delete(cp, (cp + num)); + + String copy = new String(killed); + killRing.add(copy); + + return true; + } + + public boolean yank() throws IOException { + String yanked = killRing.yank(); + + if (yanked == null) { + return false; + } + putString(yanked); + return true; + } + + public boolean yankPop() throws IOException { + if (!killRing.lastYank()) { + return false; + } + String current = killRing.yank(); + if (current == null) { + // This shouldn't happen. + return false; + } + backspace(current.length()); + String yanked = killRing.yankPop(); + if (yanked == null) { + // This shouldn't happen. + return false; + } + + putString(yanked); + return true; + } + + /** + * Clear the screen by issuing the ANSI "clear screen" code. + */ + public boolean clearScreen() throws IOException { + if (!terminal.isAnsiSupported()) { + return false; + } + + // send the ANSI code to clear the screen + printAnsiSequence("2J"); + + // then send the ANSI code to go to position 1,1 + printAnsiSequence("1;1H"); + + return true; + } + + /** + * Issue an audible keyboard bell. + */ + public void beep() throws IOException { + if (bellEnabled) { + print(KEYBOARD_BELL); + // need to flush so the console actually beeps + flush(); + } + } + + //disabled to avoid dependency on java.desktop: +// /** +// * Paste the contents of the clipboard into the console buffer +// * +// * @return true if clipboard contents pasted +// */ +// public boolean paste() throws IOException { +// Clipboard clipboard; +// try { // May throw ugly exception on system without X +// clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); +// } +// catch (Exception e) { +// return false; +// } +// +// if (clipboard == null) { +// return false; +// } +// +// Transferable transferable = clipboard.getContents(null); +// +// if (transferable == null) { +// return false; +// } +// +// try { +// @SuppressWarnings("deprecation") +// Object content = transferable.getTransferData(DataFlavor.plainTextFlavor); +// +// // This fix was suggested in bug #1060649 at +// // http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056 +// // to get around the deprecated DataFlavor.plainTextFlavor, but it +// // raises a UnsupportedFlavorException on Mac OS X +// +// if (content == null) { +// try { +// content = new DataFlavor().getReaderForText(transferable); +// } +// catch (Exception e) { +// // ignore +// } +// } +// +// if (content == null) { +// return false; +// } +// +// String value; +// +// if (content instanceof Reader) { +// // TODO: we might want instead connect to the input stream +// // so we can interpret individual lines +// value = ""; +// String line; +// +// BufferedReader read = new BufferedReader((Reader) content); +// while ((line = read.readLine()) != null) { +// if (value.length() > 0) { +// value += "\n"; +// } +// +// value += line; +// } +// } +// else { +// value = content.toString(); +// } +// +// if (value == null) { +// return true; +// } +// +// putString(value); +// +// return true; +// } +// catch (UnsupportedFlavorException e) { +// Log.error("Paste failed: ", e); +// +// return false; +// } +// } + + //disabled to avoid dependency on java.desktop: +// // +// // Triggered Actions +// // +// +// private final Map triggeredActions = new HashMap(); +// +// /** +// * Adding a triggered Action allows to give another curse of action if a character passed the pre-processing. +// *

+// * Say you want to close the application if the user enter q. +// * addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick. +// */ +// public void addTriggeredAction(final char c, final ActionListener listener) { +// triggeredActions.put(c, listener); +// } + + // + // Formatted Output + // + + /** + * Output the specified {@link Collection} in proper columns. + */ + public void printColumns(final Collection items) throws IOException { + if (items == null || items.isEmpty()) { + return; + } + + int width = getTerminal().getWidth(); + int height = getTerminal().getHeight(); + + int maxWidth = 0; + for (CharSequence item : items) { + maxWidth = Math.max(maxWidth, item.length()); + } + maxWidth = maxWidth + 3; + Log.debug("Max width: ", maxWidth); + + int showLines; + if (isPaginationEnabled()) { + showLines = height - 1; // page limit + } + else { + showLines = Integer.MAX_VALUE; + } + + StringBuilder buff = new StringBuilder(); + for (CharSequence item : items) { + if ((buff.length() + maxWidth) > width) { + println(buff); + buff.setLength(0); + + if (--showLines == 0) { + // Overflow + print(resources.getString("DISPLAY_MORE")); + flush(); + int c = readCharacter(); + if (c == '\r' || c == '\n') { + // one step forward + showLines = 1; + } + else if (c != 'q') { + // page forward + showLines = height - 1; + } + + back(resources.getString("DISPLAY_MORE").length()); + if (c == 'q') { + // cancel + break; + } + } + } + + // NOTE: toString() is important here due to AnsiString being retarded + buff.append(item.toString()); + for (int i = 0; i < (maxWidth - item.length()); i++) { + buff.append(' '); + } + } + + if (buff.length() > 0) { + println(buff); + } + } + + // + // Non-supported Terminal Support + // + + private Thread maskThread; + + private void beforeReadLine(final String prompt, final Character mask) { + if (mask != null && maskThread == null) { + final String fullPrompt = "\r" + prompt + + " " + + " " + + " " + + "\r" + prompt; + + maskThread = new Thread() + { + public void run() { + while (!interrupted()) { + try { + Writer out = getOutput(); + out.write(fullPrompt); + out.flush(); + sleep(3); + } + catch (IOException e) { + return; + } + catch (InterruptedException e) { + return; + } + } + } + }; + + maskThread.setPriority(Thread.MAX_PRIORITY); + maskThread.setDaemon(true); + maskThread.start(); + } + } + + private void afterReadLine() { + if (maskThread != null && maskThread.isAlive()) { + maskThread.interrupt(); + } + + maskThread = null; + } + + /** + * Erases the current line with the existing prompt, then redraws the line + * with the provided prompt and buffer + * @param prompt + * the new prompt + * @param buffer + * the buffer to be drawn + * @param cursorDest + * where you want the cursor set when the line has been drawn. + * -1 for end of line. + * */ + public void resetPromptLine(String prompt, String buffer, int cursorDest) throws IOException { + // move cursor to end of line + moveToEnd(); + + // backspace all text, including prompt + buf.buffer.append(this.prompt); + int promptLength = 0; + if (this.prompt != null) { + promptLength = this.prompt.length(); + } + + buf.cursor += promptLength; + setPrompt(""); + backspaceAll(); + + setPrompt(prompt); + redrawLine(); + setBuffer(buffer); + + // move cursor to destination (-1 will move to end of line) + if (cursorDest < 0) cursorDest = buffer.length(); + setCursorPosition(cursorDest); + + flush(); + } + + public void printSearchStatus(String searchTerm, String match) throws IOException { + printSearchStatus(searchTerm, match, "(reverse-i-search)`"); + } + + public void printForwardSearchStatus(String searchTerm, String match) throws IOException { + printSearchStatus(searchTerm, match, "(i-search)`"); + } + + private void printSearchStatus(String searchTerm, String match, String searchLabel) throws IOException { + String prompt = searchLabel + searchTerm + "': "; + int cursorDest = match.indexOf(searchTerm); + resetPromptLine(prompt, match, cursorDest); + } + + public void restoreLine(String originalPrompt, int cursorDest) throws IOException { + // TODO move cursor to matched string + String prompt = lastLine(originalPrompt); + String buffer = buf.buffer.toString(); + resetPromptLine(prompt, buffer, cursorDest); + } + + // + // History search + // + /** + * Search backward in history from a given position. + * + * @param searchTerm substring to search for. + * @param startIndex the index from which on to search + * @return index where this substring has been found, or -1 else. + */ + public int searchBackwards(String searchTerm, int startIndex) { + return searchBackwards(searchTerm, startIndex, false); + } + + /** + * Search backwards in history from the current position. + * + * @param searchTerm substring to search for. + * @return index where the substring has been found, or -1 else. + */ + public int searchBackwards(String searchTerm) { + return searchBackwards(searchTerm, history.index()); + } + + + public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) { + ListIterator it = history.entries(startIndex); + while (it.hasPrevious()) { + History.Entry e = it.previous(); + if (startsWith) { + if (e.value().toString().startsWith(searchTerm)) { + return e.index(); + } + } else { + if (e.value().toString().contains(searchTerm)) { + return e.index(); + } + } + } + return -1; + } + + /** + * Search forward in history from a given position. + * + * @param searchTerm substring to search for. + * @param startIndex the index from which on to search + * @return index where this substring has been found, or -1 else. + */ + public int searchForwards(String searchTerm, int startIndex) { + return searchForwards(searchTerm, startIndex, false); + } + /** + * Search forwards in history from the current position. + * + * @param searchTerm substring to search for. + * @return index where the substring has been found, or -1 else. + */ + public int searchForwards(String searchTerm) { + return searchForwards(searchTerm, history.index()); + } + + public int searchForwards(String searchTerm, int startIndex, boolean startsWith) { + if (startIndex >= history.size()) { + startIndex = history.size() - 1; + } + + ListIterator it = history.entries(startIndex); + + if (searchIndex != -1 && it.hasNext()) { + it.next(); + } + + while (it.hasNext()) { + History.Entry e = it.next(); + if (startsWith) { + if (e.value().toString().startsWith(searchTerm)) { + return e.index(); + } + } else { + if (e.value().toString().contains(searchTerm)) { + return e.index(); + } + } + } + return -1; + } + + // + // Helpers + // + + /** + * Checks to see if the specified character is a delimiter. We consider a + * character a delimiter if it is anything but a letter or digit. + * + * @param c The character to test + * @return True if it is a delimiter + */ + private boolean isDelimiter(final char c) { + return !Character.isLetterOrDigit(c); + } + + /** + * Checks to see if a character is a whitespace character. Currently + * this delegates to {@link Character#isWhitespace(char)}, however + * eventually it should be hooked up so that the definition of whitespace + * can be configured, as readline does. + * + * @param c The character to check + * @return true if the character is a whitespace + */ + private boolean isWhitespace(final char c) { + return Character.isWhitespace (c); + } + + private void printAnsiSequence(String sequence) throws IOException { + print(27); + print('['); + print(sequence); + flush(); // helps with step debugging + } + +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * A holder for a {@link StringBuilder} that also contains the current cursor position. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.0 + */ +public class CursorBuffer +{ + private boolean overTyping = false; + + public int cursor = 0; + + public final StringBuilder buffer = new StringBuilder(); + + public CursorBuffer copy () { + CursorBuffer that = new CursorBuffer(); + that.overTyping = this.overTyping; + that.cursor = this.cursor; + that.buffer.append (this.toString()); + + return that; + } + + public boolean isOverTyping() { + return overTyping; + } + + public void setOverTyping(final boolean b) { + overTyping = b; + } + + public int length() { + return buffer.length(); + } + + public char nextChar() { + if (cursor == buffer.length()) { + return 0; + } else { + return buffer.charAt(cursor); + } + } + + public char current() { + if (cursor <= 0) { + return 0; + } + + return buffer.charAt(cursor - 1); + } + + /** + * Write the specific character into the buffer, setting the cursor position + * ahead one. The text may overwrite or insert based on the current setting + * of {@link #isOverTyping}. + * + * @param c the character to insert + */ + public void write(final char c) { + buffer.insert(cursor++, c); + if (isOverTyping() && cursor < buffer.length()) { + buffer.deleteCharAt(cursor); + } + } + + /** + * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point. + */ + public void write(final CharSequence str) { + checkNotNull(str); + + if (buffer.length() == 0) { + buffer.append(str); + } + else { + buffer.insert(cursor, str); + } + + cursor += str.length(); + + if (isOverTyping() && cursor < buffer.length()) { + buffer.delete(cursor, (cursor + str.length())); + } + } + + public boolean clear() { + if (buffer.length() == 0) { + return false; + } + + buffer.delete(0, buffer.length()); + cursor = 0; + return true; + } + + public String upToCursor() { + if (cursor <= 0) { + return ""; + } + + return buffer.substring(0, cursor); + } + + @Override + public String toString() { + return buffer.toString(); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +import java.util.HashMap; +import java.util.Map; + +/** + * The KeyMap class contains all bindings from keys to operations. + * + * @author Guillaume Nodet + * @since 2.6 + */ +public class KeyMap { + + public static final String VI_MOVE = "vi-move"; + public static final String VI_INSERT = "vi-insert"; + public static final String EMACS = "emacs"; + public static final String EMACS_STANDARD = "emacs-standard"; + public static final String EMACS_CTLX = "emacs-ctlx"; + public static final String EMACS_META = "emacs-meta"; + + private static final int KEYMAP_LENGTH = 256; + + private static final Object NULL_FUNCTION = new Object(); + + private Object[] mapping = new Object[KEYMAP_LENGTH]; + private Object anotherKey = null; + private String name; + private boolean isViKeyMap; + + public KeyMap(String name, boolean isViKeyMap) { + this(name, new Object[KEYMAP_LENGTH], isViKeyMap); + } + + protected KeyMap(String name, Object[] mapping, boolean isViKeyMap) { + this.mapping = mapping; + this.name = name; + this.isViKeyMap = isViKeyMap; + } + + public boolean isViKeyMap() { + return isViKeyMap; + } + + public String getName() { + return name; + } + + public Object getAnotherKey() { + return anotherKey; + } + + public void from(KeyMap other) { + this.mapping = other.mapping; + this.anotherKey = other.anotherKey; + } + + public Object getBound( CharSequence keySeq ) { + if (keySeq != null && keySeq.length() > 0) { + KeyMap map = this; + for (int i = 0; i < keySeq.length(); i++) { + char c = keySeq.charAt(i); + if (c > 255) { + return Operation.SELF_INSERT; + } + if (map.mapping[c] instanceof KeyMap) { + if (i == keySeq.length() - 1) { + return map.mapping[c]; + } else { + map = (KeyMap) map.mapping[c]; + } + } else { + return map.mapping[c]; + } + } + } + return null; + } + + public void bindIfNotBound( CharSequence keySeq, Object function ) { + + bind (this, keySeq, function, true); + } + + public void bind( CharSequence keySeq, Object function ) { + + bind (this, keySeq, function, false); + } + + private static void bind( KeyMap map, CharSequence keySeq, Object function ) { + + bind (map, keySeq, function, false); + } + + private static void bind( KeyMap map, CharSequence keySeq, Object function, + boolean onlyIfNotBound ) { + + if (keySeq != null && keySeq.length() > 0) { + for (int i = 0; i < keySeq.length(); i++) { + char c = keySeq.charAt(i); + if (c >= map.mapping.length) { + return; + } + if (i < keySeq.length() - 1) { + if (!(map.mapping[c] instanceof KeyMap)) { + KeyMap m = new KeyMap("anonymous", false); + if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) { + m.anotherKey = map.mapping[c]; + } + map.mapping[c] = m; + } + map = (KeyMap) map.mapping[c]; + } else { + if (function == null) { + function = NULL_FUNCTION; + } + if (map.mapping[c] instanceof KeyMap) { + map.anotherKey = function; + } else { + Object op = map.mapping[c]; + if (onlyIfNotBound == false + || op == null + || op == Operation.DO_LOWERCASE_VERSION + || op == Operation.VI_MOVEMENT_MODE ) { + + } + + map.mapping[c] = function; + } + } + } + } + } + + public void setBlinkMatchingParen(boolean on) { + if (on) { + bind( "}", Operation.INSERT_CLOSE_CURLY ); + bind( ")", Operation.INSERT_CLOSE_PAREN ); + bind( "]", Operation.INSERT_CLOSE_SQUARE ); + } + } + + private static void bindArrowKeys(KeyMap map) { + + // MS-DOS + bind( map, "\033[0A", Operation.PREVIOUS_HISTORY ); + bind( map, "\033[0B", Operation.BACKWARD_CHAR ); + bind( map, "\033[0C", Operation.FORWARD_CHAR ); + bind( map, "\033[0D", Operation.NEXT_HISTORY ); + + // Windows + bind( map, "\340\000", Operation.KILL_WHOLE_LINE ); + bind( map, "\340\107", Operation.BEGINNING_OF_LINE ); + bind( map, "\340\110", Operation.PREVIOUS_HISTORY ); + bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY ); + bind( map, "\340\113", Operation.BACKWARD_CHAR ); + bind( map, "\340\115", Operation.FORWARD_CHAR ); + bind( map, "\340\117", Operation.END_OF_LINE ); + bind( map, "\340\120", Operation.NEXT_HISTORY ); + bind( map, "\340\121", Operation.END_OF_HISTORY ); + bind( map, "\340\122", Operation.OVERWRITE_MODE ); + bind( map, "\340\123", Operation.DELETE_CHAR ); + + bind( map, "\000\107", Operation.BEGINNING_OF_LINE ); + bind( map, "\000\110", Operation.PREVIOUS_HISTORY ); + bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY ); + bind( map, "\000\110", Operation.PREVIOUS_HISTORY ); + bind( map, "\000\113", Operation.BACKWARD_CHAR ); + bind( map, "\000\115", Operation.FORWARD_CHAR ); + bind( map, "\000\117", Operation.END_OF_LINE ); + bind( map, "\000\120", Operation.NEXT_HISTORY ); + bind( map, "\000\121", Operation.END_OF_HISTORY ); + bind( map, "\000\122", Operation.OVERWRITE_MODE ); + bind( map, "\000\123", Operation.DELETE_CHAR ); + + bind( map, "\033[A", Operation.PREVIOUS_HISTORY ); + bind( map, "\033[B", Operation.NEXT_HISTORY ); + bind( map, "\033[C", Operation.FORWARD_CHAR ); + bind( map, "\033[D", Operation.BACKWARD_CHAR ); + bind( map, "\033[H", Operation.BEGINNING_OF_LINE ); + bind( map, "\033[F", Operation.END_OF_LINE ); + + bind( map, "\033OA", Operation.PREVIOUS_HISTORY ); + bind( map, "\033OB", Operation.NEXT_HISTORY ); + bind( map, "\033OC", Operation.FORWARD_CHAR ); + bind( map, "\033OD", Operation.BACKWARD_CHAR ); + bind( map, "\033OH", Operation.BEGINNING_OF_LINE ); + bind( map, "\033OF", Operation.END_OF_LINE ); + + bind( map, "\033[1~", Operation.BEGINNING_OF_LINE); + bind( map, "\033[4~", Operation.END_OF_LINE); + bind( map, "\033[3~", Operation.DELETE_CHAR); + + // MINGW32 + bind( map, "\0340H", Operation.PREVIOUS_HISTORY ); + bind( map, "\0340P", Operation.NEXT_HISTORY ); + bind( map, "\0340M", Operation.FORWARD_CHAR ); + bind( map, "\0340K", Operation.BACKWARD_CHAR ); + } + +// public boolean isConvertMetaCharsToAscii() { +// return convertMetaCharsToAscii; +// } + +// public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) { +// this.convertMetaCharsToAscii = convertMetaCharsToAscii; +// } + + public static boolean isMeta( char c ) { + return c > 0x7f && c <= 0xff; + } + + public static char unMeta( char c ) { + return (char) (c & 0x7F); + } + + public static char meta( char c ) { + return (char) (c | 0x80); + } + + public static Map keyMaps() { + Map keyMaps = new HashMap(); + + KeyMap emacs = emacs(); + bindArrowKeys(emacs); + keyMaps.put(EMACS, emacs); + keyMaps.put(EMACS_STANDARD, emacs); + keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018")); + keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b")); + + KeyMap viMov = viMovement(); + bindArrowKeys(viMov); + keyMaps.put(VI_MOVE, viMov); + keyMaps.put("vi-command", viMov); + + KeyMap viIns = viInsertion(); + bindArrowKeys(viIns); + keyMaps.put(VI_INSERT, viIns); + keyMaps.put("vi", viIns); + + return keyMaps; + } + + public static KeyMap emacs() { + Object[] map = new Object[KEYMAP_LENGTH]; + Object[] ctrl = new Object[] { + // Control keys. + Operation.SET_MARK, /* Control-@ */ + Operation.BEGINNING_OF_LINE, /* Control-A */ + Operation.BACKWARD_CHAR, /* Control-B */ + Operation.INTERRUPT, /* Control-C */ + Operation.EXIT_OR_DELETE_CHAR, /* Control-D */ + Operation.END_OF_LINE, /* Control-E */ + Operation.FORWARD_CHAR, /* Control-F */ + Operation.ABORT, /* Control-G */ + Operation.BACKWARD_DELETE_CHAR, /* Control-H */ + Operation.COMPLETE, /* Control-I */ + Operation.ACCEPT_LINE, /* Control-J */ + Operation.KILL_LINE, /* Control-K */ + Operation.CLEAR_SCREEN, /* Control-L */ + Operation.ACCEPT_LINE, /* Control-M */ + Operation.NEXT_HISTORY, /* Control-N */ + null, /* Control-O */ + Operation.PREVIOUS_HISTORY, /* Control-P */ + Operation.QUOTED_INSERT, /* Control-Q */ + Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ + Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ + Operation.TRANSPOSE_CHARS, /* Control-T */ + Operation.UNIX_LINE_DISCARD, /* Control-U */ + Operation.QUOTED_INSERT, /* Control-V */ + Operation.UNIX_WORD_RUBOUT, /* Control-W */ + emacsCtrlX(), /* Control-X */ + Operation.YANK, /* Control-Y */ + null, /* Control-Z */ + emacsMeta(), /* Control-[ */ + null, /* Control-\ */ + Operation.CHARACTER_SEARCH, /* Control-] */ + null, /* Control-^ */ + Operation.UNDO, /* Control-_ */ + }; + System.arraycopy( ctrl, 0, map, 0, ctrl.length ); + for (int i = 32; i < 256; i++) { + map[i] = Operation.SELF_INSERT; + } + map[DELETE] = Operation.BACKWARD_DELETE_CHAR; + return new KeyMap(EMACS, map, false); + } + + public static final char CTRL_D = (char) 4; + public static final char CTRL_G = (char) 7; + public static final char CTRL_H = (char) 8; + public static final char CTRL_I = (char) 9; + public static final char CTRL_J = (char) 10; + public static final char CTRL_M = (char) 13; + public static final char CTRL_R = (char) 18; + public static final char CTRL_S = (char) 19; + public static final char CTRL_U = (char) 21; + public static final char CTRL_X = (char) 24; + public static final char CTRL_Y = (char) 25; + public static final char ESCAPE = (char) 27; /* Ctrl-[ */ + public static final char CTRL_OB = (char) 27; /* Ctrl-[ */ + public static final char CTRL_CB = (char) 29; /* Ctrl-] */ + + public static final int DELETE = (char) 127; + + public static KeyMap emacsCtrlX() { + Object[] map = new Object[KEYMAP_LENGTH]; + map[CTRL_G] = Operation.ABORT; + map[CTRL_R] = Operation.RE_READ_INIT_FILE; + map[CTRL_U] = Operation.UNDO; + map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK; + map['('] = Operation.START_KBD_MACRO; + map[')'] = Operation.END_KBD_MACRO; + for (int i = 'A'; i <= 'Z'; i++) { + map[i] = Operation.DO_LOWERCASE_VERSION; + } + map['e'] = Operation.CALL_LAST_KBD_MACRO; + map[DELETE] = Operation.KILL_LINE; + return new KeyMap(EMACS_CTLX, map, false); + } + + public static KeyMap emacsMeta() { + Object[] map = new Object[KEYMAP_LENGTH]; + map[CTRL_G] = Operation.ABORT; + map[CTRL_H] = Operation.BACKWARD_KILL_WORD; + map[CTRL_I] = Operation.TAB_INSERT; + map[CTRL_J] = Operation.VI_EDITING_MODE; + map[CTRL_M] = Operation.VI_EDITING_MODE; + map[CTRL_R] = Operation.REVERT_LINE; + map[CTRL_Y] = Operation.YANK_NTH_ARG; + map[CTRL_OB] = Operation.COMPLETE; + map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD; + map[' '] = Operation.SET_MARK; + map['#'] = Operation.INSERT_COMMENT; + map['&'] = Operation.TILDE_EXPAND; + map['*'] = Operation.INSERT_COMPLETIONS; + map['-'] = Operation.DIGIT_ARGUMENT; + map['.'] = Operation.YANK_LAST_ARG; + map['<'] = Operation.BEGINNING_OF_HISTORY; + map['='] = Operation.POSSIBLE_COMPLETIONS; + map['>'] = Operation.END_OF_HISTORY; + map['?'] = Operation.POSSIBLE_COMPLETIONS; + for (int i = 'A'; i <= 'Z'; i++) { + map[i] = Operation.DO_LOWERCASE_VERSION; + } + map['\\'] = Operation.DELETE_HORIZONTAL_SPACE; + map['_'] = Operation.YANK_LAST_ARG; + map['b'] = Operation.BACKWARD_WORD; + map['c'] = Operation.CAPITALIZE_WORD; + map['d'] = Operation.KILL_WORD; + map['f'] = Operation.FORWARD_WORD; + map['l'] = Operation.DOWNCASE_WORD; + map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY; + map['r'] = Operation.REVERT_LINE; + map['t'] = Operation.TRANSPOSE_WORDS; + map['u'] = Operation.UPCASE_WORD; + map['y'] = Operation.YANK_POP; + map['~'] = Operation.TILDE_EXPAND; + map[DELETE] = Operation.BACKWARD_KILL_WORD; + return new KeyMap(EMACS_META, map, false); + } + + public static KeyMap viInsertion() { + Object[] map = new Object[KEYMAP_LENGTH]; + Object[] ctrl = new Object[] { + // Control keys. + null, /* Control-@ */ + Operation.SELF_INSERT, /* Control-A */ + Operation.SELF_INSERT, /* Control-B */ + Operation.SELF_INSERT, /* Control-C */ + Operation.VI_EOF_MAYBE, /* Control-D */ + Operation.SELF_INSERT, /* Control-E */ + Operation.SELF_INSERT, /* Control-F */ + Operation.SELF_INSERT, /* Control-G */ + Operation.BACKWARD_DELETE_CHAR, /* Control-H */ + Operation.COMPLETE, /* Control-I */ + Operation.ACCEPT_LINE, /* Control-J */ + Operation.SELF_INSERT, /* Control-K */ + Operation.SELF_INSERT, /* Control-L */ + Operation.ACCEPT_LINE, /* Control-M */ + Operation.MENU_COMPLETE, /* Control-N */ + Operation.SELF_INSERT, /* Control-O */ + Operation.MENU_COMPLETE_BACKWARD, /* Control-P */ + Operation.SELF_INSERT, /* Control-Q */ + Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ + Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ + Operation.TRANSPOSE_CHARS, /* Control-T */ + Operation.UNIX_LINE_DISCARD, /* Control-U */ + Operation.QUOTED_INSERT, /* Control-V */ + Operation.UNIX_WORD_RUBOUT, /* Control-W */ + Operation.SELF_INSERT, /* Control-X */ + Operation.YANK, /* Control-Y */ + Operation.SELF_INSERT, /* Control-Z */ + Operation.VI_MOVEMENT_MODE, /* Control-[ */ + Operation.SELF_INSERT, /* Control-\ */ + Operation.SELF_INSERT, /* Control-] */ + Operation.SELF_INSERT, /* Control-^ */ + Operation.UNDO, /* Control-_ */ + }; + System.arraycopy( ctrl, 0, map, 0, ctrl.length ); + for (int i = 32; i < 256; i++) { + map[i] = Operation.SELF_INSERT; + } + map[DELETE] = Operation.BACKWARD_DELETE_CHAR; + return new KeyMap(VI_INSERT, map, false); + } + + public static KeyMap viMovement() { + Object[] map = new Object[KEYMAP_LENGTH]; + Object[] low = new Object[] { + // Control keys. + null, /* Control-@ */ + null, /* Control-A */ + null, /* Control-B */ + Operation.INTERRUPT, /* Control-C */ + /* + * ^D is supposed to move down half a screen. In bash + * appears to be ignored. + */ + Operation.VI_EOF_MAYBE, /* Control-D */ + Operation.EMACS_EDITING_MODE, /* Control-E */ + null, /* Control-F */ + Operation.ABORT, /* Control-G */ + Operation.BACKWARD_CHAR, /* Control-H */ + null, /* Control-I */ + Operation.VI_MOVE_ACCEPT_LINE, /* Control-J */ + Operation.KILL_LINE, /* Control-K */ + Operation.CLEAR_SCREEN, /* Control-L */ + Operation.VI_MOVE_ACCEPT_LINE, /* Control-M */ + Operation.VI_NEXT_HISTORY, /* Control-N */ + null, /* Control-O */ + Operation.VI_PREVIOUS_HISTORY, /* Control-P */ + /* + * My testing with readline is the ^Q is ignored. + * Maybe this should be null? + */ + Operation.QUOTED_INSERT, /* Control-Q */ + + /* + * TODO - Very broken. While in forward/reverse + * history search the VI keyset should go out the + * window and we need to enter a very simple keymap. + */ + Operation.REVERSE_SEARCH_HISTORY, /* Control-R */ + /* TODO */ + Operation.FORWARD_SEARCH_HISTORY, /* Control-S */ + Operation.TRANSPOSE_CHARS, /* Control-T */ + Operation.UNIX_LINE_DISCARD, /* Control-U */ + /* TODO */ + Operation.QUOTED_INSERT, /* Control-V */ + Operation.UNIX_WORD_RUBOUT, /* Control-W */ + null, /* Control-X */ + /* TODO */ + Operation.YANK, /* Control-Y */ + null, /* Control-Z */ + emacsMeta(), /* Control-[ */ + null, /* Control-\ */ + /* TODO */ + Operation.CHARACTER_SEARCH, /* Control-] */ + null, /* Control-^ */ + /* TODO */ + Operation.UNDO, /* Control-_ */ + Operation.FORWARD_CHAR, /* SPACE */ + null, /* ! */ + null, /* " */ + Operation.VI_INSERT_COMMENT, /* # */ + Operation.END_OF_LINE, /* $ */ + Operation.VI_MATCH, /* % */ + Operation.VI_TILDE_EXPAND, /* & */ + null, /* ' */ + null, /* ( */ + null, /* ) */ + /* TODO */ + Operation.VI_COMPLETE, /* * */ + Operation.VI_NEXT_HISTORY, /* + */ + Operation.VI_CHAR_SEARCH, /* , */ + Operation.VI_PREVIOUS_HISTORY, /* - */ + /* TODO */ + Operation.VI_REDO, /* . */ + Operation.VI_SEARCH, /* / */ + Operation.VI_BEGNNING_OF_LINE_OR_ARG_DIGIT, /* 0 */ + Operation.VI_ARG_DIGIT, /* 1 */ + Operation.VI_ARG_DIGIT, /* 2 */ + Operation.VI_ARG_DIGIT, /* 3 */ + Operation.VI_ARG_DIGIT, /* 4 */ + Operation.VI_ARG_DIGIT, /* 5 */ + Operation.VI_ARG_DIGIT, /* 6 */ + Operation.VI_ARG_DIGIT, /* 7 */ + Operation.VI_ARG_DIGIT, /* 8 */ + Operation.VI_ARG_DIGIT, /* 9 */ + null, /* : */ + Operation.VI_CHAR_SEARCH, /* ; */ + null, /* < */ + Operation.VI_COMPLETE, /* = */ + null, /* > */ + Operation.VI_SEARCH, /* ? */ + null, /* @ */ + Operation.VI_APPEND_EOL, /* A */ + Operation.VI_PREV_WORD, /* B */ + Operation.VI_CHANGE_TO_EOL, /* C */ + Operation.VI_DELETE_TO_EOL, /* D */ + Operation.VI_END_WORD, /* E */ + Operation.VI_CHAR_SEARCH, /* F */ + /* I need to read up on what this does */ + Operation.VI_FETCH_HISTORY, /* G */ + null, /* H */ + Operation.VI_INSERT_BEG, /* I */ + null, /* J */ + null, /* K */ + null, /* L */ + null, /* M */ + Operation.VI_SEARCH_AGAIN, /* N */ + null, /* O */ + Operation.VI_PUT, /* P */ + null, /* Q */ + /* TODO */ + Operation.VI_REPLACE, /* R */ + Operation.VI_KILL_WHOLE_LINE, /* S */ + Operation.VI_CHAR_SEARCH, /* T */ + /* TODO */ + Operation.REVERT_LINE, /* U */ + null, /* V */ + Operation.VI_NEXT_WORD, /* W */ + Operation.VI_RUBOUT, /* X */ + Operation.VI_YANK_TO, /* Y */ + null, /* Z */ + null, /* [ */ + Operation.VI_COMPLETE, /* \ */ + null, /* ] */ + Operation.VI_FIRST_PRINT, /* ^ */ + Operation.VI_YANK_ARG, /* _ */ + Operation.VI_GOTO_MARK, /* ` */ + Operation.VI_APPEND_MODE, /* a */ + Operation.VI_PREV_WORD, /* b */ + Operation.VI_CHANGE_TO, /* c */ + Operation.VI_DELETE_TO, /* d */ + Operation.VI_END_WORD, /* e */ + Operation.VI_CHAR_SEARCH, /* f */ + null, /* g */ + Operation.BACKWARD_CHAR, /* h */ + Operation.VI_INSERTION_MODE, /* i */ + Operation.NEXT_HISTORY, /* j */ + Operation.PREVIOUS_HISTORY, /* k */ + Operation.FORWARD_CHAR, /* l */ + Operation.VI_SET_MARK, /* m */ + Operation.VI_SEARCH_AGAIN, /* n */ + null, /* o */ + Operation.VI_PUT, /* p */ + null, /* q */ + Operation.VI_CHANGE_CHAR, /* r */ + Operation.VI_SUBST, /* s */ + Operation.VI_CHAR_SEARCH, /* t */ + Operation.UNDO, /* u */ + null, /* v */ + Operation.VI_NEXT_WORD, /* w */ + Operation.VI_DELETE, /* x */ + Operation.VI_YANK_TO, /* y */ + null, /* z */ + null, /* { */ + Operation.VI_COLUMN, /* | */ + null, /* } */ + Operation.VI_CHANGE_CASE, /* ~ */ + Operation.VI_DELETE /* DEL */ + }; + System.arraycopy( low, 0, map, 0, low.length ); + for (int i = 128; i < 256; i++) { + map[i] = null; + } + return new KeyMap(VI_MOVE, map, false); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2002-2013, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +/** + * The kill ring class keeps killed text in a fixed size ring. In this + * class we also keep record of whether or not the last command was a + * kill or a yank. Depending on this, the class may behave + * different. For instance, two consecutive kill-word commands fill + * the same slot such that the next yank will return the two + * previously killed words instead that only the last one. Likewise + * yank pop requires that the previous command was either a yank or a + * yank-pop. + */ +public final class KillRing { + + /** + * Default size is 60, like in emacs. + */ + private static final int DEFAULT_SIZE = 60; + + private final String[] slots; + private int head = 0; + private boolean lastKill = false; + private boolean lastYank = false; + + /** + * Creates a new kill ring of the given size. + */ + public KillRing(int size) { + slots = new String[size]; + } + + /** + * Creates a new kill ring of the default size. {@see DEFAULT_SIZE}. + */ + public KillRing() { + this(DEFAULT_SIZE); + } + + /** + * Resets the last-yank state. + */ + public void resetLastYank() { + lastYank = false; + } + + /** + * Resets the last-kill state. + */ + public void resetLastKill() { + lastKill = false; + } + + /** + * Returns {@code true} if the last command was a yank. + */ + public boolean lastYank() { + return lastYank; + } + + /** + * Adds the string to the kill-ring. Also sets lastYank to false + * and lastKill to true. + */ + public void add(String str) { + lastYank = false; + + if (lastKill) { + if (slots[head] != null) { + slots[head] += str; + return; + } + } + + lastKill = true; + next(); + slots[head] = str; + } + + /** + * Adds the string to the kill-ring product of killing + * backwards. If the previous command was a kill text one then + * adds the text at the beginning of the previous kill to avoid + * that two consecutive backwards kills followed by a yank leaves + * things reversed. + */ + public void addBackwards(String str) { + lastYank = false; + + if (lastKill) { + if (slots[head] != null) { + slots[head] = str + slots[head]; + return; + } + } + + lastKill = true; + next(); + slots[head] = str; + } + + /** + * Yanks a previously killed text. Returns {@code null} if the + * ring is empty. + */ + public String yank() { + lastKill = false; + lastYank = true; + return slots[head]; + } + + /** + * Moves the pointer to the current slot back and returns the text + * in that position. If the previous command was not yank returns + * null. + */ + public String yankPop() { + lastKill = false; + if (lastYank) { + prev(); + return slots[head]; + } + return null; + } + + /** + * Moves the pointer to the current slot forward. If the end of + * the slots is reached then points back to the beginning. + */ + private void next() { + if (head == 0 && slots[0] == null) { + return; + } + head++; + if (head == slots.length) { + head = 0; + } + } + + /** + * Moves the pointer to the current slot backwards. If the + * beginning of the slots is reached then traverses the slot + * backwards until one with not null content is found. + */ + private void prev() { + head--; + if (head == -1) { + int x = (slots.length - 1); + for (; x >= 0; x--) { + if (slots[x] != null) { + break; + } + } + head = x; + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +/** + * List of all operations. + * + * @author Guillaume Nodet + * @since 2.6 + */ +public enum Operation { + + ABORT, + ACCEPT_LINE, + ARROW_KEY_PREFIX, + BACKWARD_BYTE, + BACKWARD_CHAR, + BACKWARD_DELETE_CHAR, + BACKWARD_KILL_LINE, + BACKWARD_KILL_WORD, + BACKWARD_WORD, + BEGINNING_OF_HISTORY, + BEGINNING_OF_LINE, + CALL_LAST_KBD_MACRO, + CAPITALIZE_WORD, + CHARACTER_SEARCH, + CHARACTER_SEARCH_BACKWARD, + CLEAR_SCREEN, + COMPLETE, + COPY_BACKWARD_WORD, + COPY_FORWARD_WORD, + COPY_REGION_AS_KILL, + DELETE_CHAR, + DELETE_CHAR_OR_LIST, + DELETE_HORIZONTAL_SPACE, + DIGIT_ARGUMENT, + DO_LOWERCASE_VERSION, + DOWNCASE_WORD, + DUMP_FUNCTIONS, + DUMP_MACROS, + DUMP_VARIABLES, + EMACS_EDITING_MODE, + END_KBD_MACRO, + END_OF_HISTORY, + END_OF_LINE, + EXCHANGE_POINT_AND_MARK, + EXIT_OR_DELETE_CHAR, + FORWARD_BACKWARD_DELETE_CHAR, + FORWARD_BYTE, + FORWARD_CHAR, + FORWARD_SEARCH_HISTORY, + FORWARD_WORD, + HISTORY_SEARCH_BACKWARD, + HISTORY_SEARCH_FORWARD, + INSERT_CLOSE_CURLY, + INSERT_CLOSE_PAREN, + INSERT_CLOSE_SQUARE, + INSERT_COMMENT, + INSERT_COMPLETIONS, + INTERRUPT, + KILL_WHOLE_LINE, + KILL_LINE, + KILL_REGION, + KILL_WORD, + MENU_COMPLETE, + MENU_COMPLETE_BACKWARD, + NEXT_HISTORY, + NON_INCREMENTAL_FORWARD_SEARCH_HISTORY, + NON_INCREMENTAL_REVERSE_SEARCH_HISTORY, + NON_INCREMENTAL_FORWARD_SEARCH_HISTORY_AGAIN, + NON_INCREMENTAL_REVERSE_SEARCH_HISTORY_AGAIN, + OLD_MENU_COMPLETE, + OVERWRITE_MODE, + PASTE_FROM_CLIPBOARD, + POSSIBLE_COMPLETIONS, + PREVIOUS_HISTORY, + QUOTED_INSERT, + RE_READ_INIT_FILE, + REDRAW_CURRENT_LINE, + REVERSE_SEARCH_HISTORY, + REVERT_LINE, + SELF_INSERT, + SET_MARK, + SKIP_CSI_SEQUENCE, + START_KBD_MACRO, + TAB_INSERT, + TILDE_EXPAND, + TRANSPOSE_CHARS, + TRANSPOSE_WORDS, + TTY_STATUS, + UNDO, + UNIVERSAL_ARGUMENT, + UNIX_FILENAME_RUBOUT, + UNIX_LINE_DISCARD, + UNIX_WORD_RUBOUT, + UPCASE_WORD, + YANK, + YANK_LAST_ARG, + YANK_NTH_ARG, + YANK_POP, + VI_APPEND_EOL, + VI_APPEND_MODE, + VI_ARG_DIGIT, + VI_BACK_TO_INDENT, + VI_BACKWARD_BIGWORD, + VI_BACKWARD_WORD, + VI_BWORD, + VI_CHANGE_CASE, + VI_CHANGE_CHAR, + VI_CHANGE_TO, + VI_CHANGE_TO_EOL, + VI_CHAR_SEARCH, + VI_COLUMN, + VI_COMPLETE, + VI_DELETE, + VI_DELETE_TO, + VI_DELETE_TO_EOL, + VI_EDITING_MODE, + VI_END_BIGWORD, + VI_END_WORD, + VI_EOF_MAYBE, + VI_EWORD, + VI_FWORD, + VI_FETCH_HISTORY, + VI_FIRST_PRINT, + VI_FORWARD_BIGWORD, + VI_FORWARD_WORD, + VI_GOTO_MARK, + VI_INSERT_BEG, + VI_INSERTION_MODE, + VI_KILL_WHOLE_LINE, + VI_MATCH, + VI_MOVEMENT_MODE, + VI_NEXT_WORD, + VI_OVERSTRIKE, + VI_OVERSTRIKE_DELETE, + VI_PREV_WORD, + VI_PUT, + VI_REDO, + VI_REPLACE, + VI_RUBOUT, + VI_SEARCH, + VI_SEARCH_AGAIN, + VI_SET_MARK, + VI_SUBST, + VI_TILDE_EXPAND, + VI_YANK_ARG, + VI_YANK_TO, + VI_MOVE_ACCEPT_LINE, + VI_NEXT_HISTORY, + VI_PREVIOUS_HISTORY, + VI_INSERT_COMMENT, + VI_BEGNNING_OF_LINE_OR_ARG_DIGIT, +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console; + +/** + * This exception is thrown by {@link ConsoleReader#readLine} when + * user interrupt handling is enabled and the user types the + * interrupt character (ctrl-C). The partially entered line is + * available via the {@link #getPartialLine()} method. + */ +public class UserInterruptException + extends RuntimeException +{ + private static final long serialVersionUID = 6172232572140736750L; + + private final String partialLine; + + public UserInterruptException(String partialLine) + { + this.partialLine = partialLine; + } + + /** + * @return the partially entered line when ctrl-C was pressed + */ + public String getPartialLine() + { + return partialLine; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Completer which contains multiple completers and aggregates them together. + * + * @author Jason Dillon + * @since 2.3 + */ +public class AggregateCompleter + implements Completer +{ + private final List completers = new ArrayList(); + + public AggregateCompleter() { + // empty + } + + /** + * Construct an AggregateCompleter with the given collection of completers. + * The completers will be used in the iteration order of the collection. + * + * @param completers the collection of completers + */ + public AggregateCompleter(final Collection completers) { + checkNotNull(completers); + this.completers.addAll(completers); + } + + /** + * Construct an AggregateCompleter with the given completers. + * The completers will be used in the order given. + * + * @param completers the completers + */ + public AggregateCompleter(final Completer... completers) { + this(Arrays.asList(completers)); + } + + /** + * Retrieve the collection of completers currently being aggregated. + * + * @return the aggregated completers + */ + public Collection getCompleters() { + return completers; + } + + /** + * Perform a completion operation across all aggregated completers. + * + * @see Completer#complete(String, int, java.util.List) + * @return the highest completion return value from all completers + */ + public int complete(final String buffer, final int cursor, final List candidates) { + // buffer could be null + checkNotNull(candidates); + + List completions = new ArrayList(completers.size()); + + // Run each completer, saving its completion results + int max = -1; + for (Completer completer : completers) { + Completion completion = new Completion(candidates); + completion.complete(completer, buffer, cursor); + + // Compute the max cursor position + max = Math.max(max, completion.cursor); + + completions.add(completion); + } + + // Append candidates from completions which have the same cursor position as max + for (Completion completion : completions) { + if (completion.cursor == max) { + candidates.addAll(completion.candidates); + } + } + + return max; + } + + /** + * @return a string representing the aggregated completers + */ + @Override + public String toString() { + return getClass().getSimpleName() + "{" + + "completers=" + completers + + '}'; + } + + private class Completion + { + public final List candidates; + + public int cursor; + + public Completion(final List candidates) { + checkNotNull(candidates); + this.candidates = new LinkedList(candidates); + } + + public void complete(final Completer completer, final String buffer, final int cursor) { + checkNotNull(completer); + this.cursor = completer.complete(buffer, cursor, candidates); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import jdk.internal.jline.internal.Log; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * A {@link Completer} implementation that invokes a child completer using the appropriate separator argument. + * This can be used instead of the individual completers having to know about argument parsing semantics. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public class ArgumentCompleter + implements Completer +{ + private final ArgumentDelimiter delimiter; + + private final List completers = new ArrayList(); + + private boolean strict = true; + + /** + * Create a new completer with the specified argument delimiter. + * + * @param delimiter The delimiter for parsing arguments + * @param completers The embedded completers + */ + public ArgumentCompleter(final ArgumentDelimiter delimiter, final Collection completers) { + this.delimiter = checkNotNull(delimiter); + checkNotNull(completers); + this.completers.addAll(completers); + } + + /** + * Create a new completer with the specified argument delimiter. + * + * @param delimiter The delimiter for parsing arguments + * @param completers The embedded completers + */ + public ArgumentCompleter(final ArgumentDelimiter delimiter, final Completer... completers) { + this(delimiter, Arrays.asList(completers)); + } + + /** + * Create a new completer with the default {@link WhitespaceArgumentDelimiter}. + * + * @param completers The embedded completers + */ + public ArgumentCompleter(final Completer... completers) { + this(new WhitespaceArgumentDelimiter(), completers); + } + + /** + * Create a new completer with the default {@link WhitespaceArgumentDelimiter}. + * + * @param completers The embedded completers + */ + public ArgumentCompleter(final List completers) { + this(new WhitespaceArgumentDelimiter(), completers); + } + + /** + * If true, a completion at argument index N will only succeed + * if all the completions from 0-(N-1) also succeed. + */ + public void setStrict(final boolean strict) { + this.strict = strict; + } + + /** + * Returns whether a completion at argument index N will success + * if all the completions from arguments 0-(N-1) also succeed. + * + * @return True if strict. + * @since 2.3 + */ + public boolean isStrict() { + return this.strict; + } + + /** + * @since 2.3 + */ + public ArgumentDelimiter getDelimiter() { + return delimiter; + } + + /** + * @since 2.3 + */ + public List getCompleters() { + return completers; + } + + public int complete(final String buffer, final int cursor, final List candidates) { + // buffer can be null + checkNotNull(candidates); + + ArgumentDelimiter delim = getDelimiter(); + ArgumentList list = delim.delimit(buffer, cursor); + int argpos = list.getArgumentPosition(); + int argIndex = list.getCursorArgumentIndex(); + + if (argIndex < 0) { + return -1; + } + + List completers = getCompleters(); + Completer completer; + + // if we are beyond the end of the completers, just use the last one + if (argIndex >= completers.size()) { + completer = completers.get(completers.size() - 1); + } + else { + completer = completers.get(argIndex); + } + + // ensure that all the previous completers are successful before allowing this completer to pass (only if strict). + for (int i = 0; isStrict() && (i < argIndex); i++) { + Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i); + String[] args = list.getArguments(); + String arg = (args == null || i >= args.length) ? "" : args[i]; + + List subCandidates = new LinkedList(); + + if (sub.complete(arg, arg.length(), subCandidates) == -1) { + return -1; + } + + if (subCandidates.size() == 0) { + return -1; + } + } + + int ret = completer.complete(list.getCursorArgument(), argpos, candidates); + + if (ret == -1) { + return -1; + } + + int pos = ret + list.getBufferPosition() - argpos; + + // Special case: when completing in the middle of a line, and the area under the cursor is a delimiter, + // then trim any delimiters from the candidates, since we do not need to have an extra delimiter. + // + // E.g., if we have a completion for "foo", and we enter "f bar" into the buffer, and move to after the "f" + // and hit TAB, we want "foo bar" instead of "foo bar". + + if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) { + for (int i = 0; i < candidates.size(); i++) { + CharSequence val = candidates.get(i); + + while (val.length() > 0 && delim.isDelimiter(val, val.length() - 1)) { + val = val.subSequence(0, val.length() - 1); + } + + candidates.set(i, val); + } + } + + Log.trace("Completing ", buffer, " (pos=", cursor, ") with: ", candidates, ": offset=", pos); + + return pos; + } + + /** + * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom breaking up of a {@link String} into individual + * arguments in order to dispatch the arguments to the nested {@link Completer}. + * + * @author Marc Prud'hommeaux + */ + public static interface ArgumentDelimiter + { + /** + * Break the specified buffer into individual tokens that can be completed on their own. + * + * @param buffer The buffer to split + * @param pos The current position of the cursor in the buffer + * @return The tokens + */ + ArgumentList delimit(CharSequence buffer, int pos); + + /** + * Returns true if the specified character is a whitespace parameter. + * + * @param buffer The complete command buffer + * @param pos The index of the character in the buffer + * @return True if the character should be a delimiter + */ + boolean isDelimiter(CharSequence buffer, int pos); + } + + /** + * Abstract implementation of a delimiter that uses the {@link #isDelimiter} method to determine if a particular + * character should be used as a delimiter. + * + * @author Marc Prud'hommeaux + */ + public abstract static class AbstractArgumentDelimiter + implements ArgumentDelimiter + { + private char[] quoteChars = {'\'', '"'}; + + private char[] escapeChars = {'\\'}; + + public void setQuoteChars(final char[] chars) { + this.quoteChars = chars; + } + + public char[] getQuoteChars() { + return this.quoteChars; + } + + public void setEscapeChars(final char[] chars) { + this.escapeChars = chars; + } + + public char[] getEscapeChars() { + return this.escapeChars; + } + + public ArgumentList delimit(final CharSequence buffer, final int cursor) { + List args = new LinkedList(); + StringBuilder arg = new StringBuilder(); + int argpos = -1; + int bindex = -1; + int quoteStart = -1; + + for (int i = 0; (buffer != null) && (i < buffer.length()); i++) { + // once we reach the cursor, set the + // position of the selected index + if (i == cursor) { + bindex = args.size(); + // the position in the current argument is just the + // length of the current argument + argpos = arg.length(); + } + + if (quoteStart < 0 && isQuoteChar(buffer, i)) { + // Start a quote block + quoteStart = i; + } else if (quoteStart >= 0) { + // In a quote block + if (buffer.charAt(quoteStart) == buffer.charAt(i) && !isEscaped(buffer, i)) { + // End the block; arg could be empty, but that's fine + args.add(arg.toString()); + arg.setLength(0); + quoteStart = -1; + } else if (!isEscapeChar(buffer, i)) { + // Take the next character + arg.append(buffer.charAt(i)); + } + } else { + // Not in a quote block + if (isDelimiter(buffer, i)) { + if (arg.length() > 0) { + args.add(arg.toString()); + arg.setLength(0); // reset the arg + } + } else if (!isEscapeChar(buffer, i)) { + arg.append(buffer.charAt(i)); + } + } + } + + if (cursor == buffer.length()) { + bindex = args.size(); + // the position in the current argument is just the + // length of the current argument + argpos = arg.length(); + } + if (arg.length() > 0) { + args.add(arg.toString()); + } + + return new ArgumentList(args.toArray(new String[args.size()]), bindex, argpos, cursor); + } + + /** + * Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not + * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and + * returns true from {@link #isDelimiterChar}. + * + * @param buffer The complete command buffer + * @param pos The index of the character in the buffer + * @return True if the character should be a delimiter + */ + public boolean isDelimiter(final CharSequence buffer, final int pos) { + return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos); + } + + public boolean isQuoted(final CharSequence buffer, final int pos) { + return false; + } + + public boolean isQuoteChar(final CharSequence buffer, final int pos) { + if (pos < 0) { + return false; + } + + for (int i = 0; (quoteChars != null) && (i < quoteChars.length); i++) { + if (buffer.charAt(pos) == quoteChars[i]) { + return !isEscaped(buffer, pos); + } + } + + return false; + } + + /** + * Check if this character is a valid escape char (i.e. one that has not been escaped) + * + * @param buffer + * @param pos + * @return + */ + public boolean isEscapeChar(final CharSequence buffer, final int pos) { + if (pos < 0) { + return false; + } + + for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) { + if (buffer.charAt(pos) == escapeChars[i]) { + return !isEscaped(buffer, pos); // escape escape + } + } + + return false; + } + + /** + * Check if a character is escaped (i.e. if the previous character is an escape) + * + * @param buffer + * the buffer to check in + * @param pos + * the position of the character to check + * @return true if the character at the specified position in the given buffer is an escape character and the character immediately preceding it is not an + * escape character. + */ + public boolean isEscaped(final CharSequence buffer, final int pos) { + if (pos <= 0) { + return false; + } + + return isEscapeChar(buffer, pos - 1); + } + + /** + * Returns true if the character at the specified position if a delimiter. This method will only be called if + * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the + * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead. + */ + public abstract boolean isDelimiterChar(CharSequence buffer, int pos); + } + + /** + * {@link ArgumentCompleter.ArgumentDelimiter} implementation that counts all whitespace (as reported by + * {@link Character#isWhitespace}) as being a delimiter. + * + * @author Marc Prud'hommeaux + */ + public static class WhitespaceArgumentDelimiter + extends AbstractArgumentDelimiter + { + /** + * The character is a delimiter if it is whitespace, and the + * preceding character is not an escape character. + */ + @Override + public boolean isDelimiterChar(final CharSequence buffer, final int pos) { + return Character.isWhitespace(buffer.charAt(pos)); + } + } + + /** + * The result of a delimited buffer. + * + * @author Marc Prud'hommeaux + */ + public static class ArgumentList + { + private String[] arguments; + + private int cursorArgumentIndex; + + private int argumentPosition; + + private int bufferPosition; + + /** + * @param arguments The array of tokens + * @param cursorArgumentIndex The token index of the cursor + * @param argumentPosition The position of the cursor in the current token + * @param bufferPosition The position of the cursor in the whole buffer + */ + public ArgumentList(final String[] arguments, final int cursorArgumentIndex, final int argumentPosition, final int bufferPosition) { + this.arguments = checkNotNull(arguments); + this.cursorArgumentIndex = cursorArgumentIndex; + this.argumentPosition = argumentPosition; + this.bufferPosition = bufferPosition; + } + + public void setCursorArgumentIndex(final int i) { + this.cursorArgumentIndex = i; + } + + public int getCursorArgumentIndex() { + return this.cursorArgumentIndex; + } + + public String getCursorArgument() { + if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) { + return null; + } + + return arguments[cursorArgumentIndex]; + } + + public void setArgumentPosition(final int pos) { + this.argumentPosition = pos; + } + + public int getArgumentPosition() { + return this.argumentPosition; + } + + public void setArguments(final String[] arguments) { + this.arguments = arguments; + } + + public String[] getArguments() { + return this.arguments; + } + + public void setBufferPosition(final int pos) { + this.bufferPosition = pos; + } + + public int getBufferPosition() { + return this.bufferPosition; + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import jdk.internal.jline.console.ConsoleReader; +import jdk.internal.jline.console.CursorBuffer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.Set; + +/** + * A {@link CompletionHandler} that deals with multiple distinct completions + * by outputting the complete list of possibilities to the console. This + * mimics the behavior of the + * readline library. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public class CandidateListCompletionHandler + implements CompletionHandler +{ + // TODO: handle quotes and escaped quotes && enable automatic escaping of whitespace + + public boolean complete(final ConsoleReader reader, final List candidates, final int pos) throws + IOException + { + CursorBuffer buf = reader.getCursorBuffer(); + + // if there is only one completion, then fill in the buffer + if (candidates.size() == 1) { + CharSequence value = candidates.get(0); + + // fail if the only candidate is the same as the current buffer + if (value.equals(buf.toString())) { + return false; + } + + setBuffer(reader, value, pos); + + return true; + } + else if (candidates.size() > 1) { + String value = getUnambiguousCompletions(candidates); + setBuffer(reader, value, pos); + } + + printCandidates(reader, candidates); + + // redraw the current console buffer + reader.drawLine(); + + return true; + } + + public static void setBuffer(final ConsoleReader reader, final CharSequence value, final int offset) throws + IOException + { + while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) { + // empty + } + + reader.putString(value); + reader.setCursorPosition(offset + value.length()); + } + + /** + * Print out the candidates. If the size of the candidates is greater than the + * {@link ConsoleReader#getAutoprintThreshold}, they prompt with a warning. + * + * @param candidates the list of candidates to print + */ + public static void printCandidates(final ConsoleReader reader, Collection candidates) throws + IOException + { + Set distinct = new HashSet(candidates); + + if (distinct.size() > reader.getAutoprintThreshold()) { + //noinspection StringConcatenation + reader.print(Messages.DISPLAY_CANDIDATES.format(candidates.size())); + reader.flush(); + + int c; + + String noOpt = Messages.DISPLAY_CANDIDATES_NO.format(); + String yesOpt = Messages.DISPLAY_CANDIDATES_YES.format(); + char[] allowed = {yesOpt.charAt(0), noOpt.charAt(0)}; + + while ((c = reader.readCharacter(allowed)) != -1) { + String tmp = new String(new char[]{(char) c}); + + if (noOpt.startsWith(tmp)) { + reader.println(); + return; + } + else if (yesOpt.startsWith(tmp)) { + break; + } + else { + reader.beep(); + } + } + } + + // copy the values and make them distinct, without otherwise affecting the ordering. Only do it if the sizes differ. + if (distinct.size() != candidates.size()) { + Collection copy = new ArrayList(); + + for (CharSequence next : candidates) { + if (!copy.contains(next)) { + copy.add(next); + } + } + + candidates = copy; + } + + reader.println(); + reader.printColumns(candidates); + } + + /** + * Returns a root that matches all the {@link String} elements of the specified {@link List}, + * or null if there are no commonalities. For example, if the list contains + * foobar, foobaz, foobuz, the method will return foob. + */ + private String getUnambiguousCompletions(final List candidates) { + if (candidates == null || candidates.isEmpty()) { + return null; + } + + // convert to an array for speed + String[] strings = candidates.toArray(new String[candidates.size()]); + + String first = strings[0]; + StringBuilder candidate = new StringBuilder(); + + for (int i = 0; i < first.length(); i++) { + if (startsWith(first.substring(0, i + 1), strings)) { + candidate.append(first.charAt(i)); + } + else { + break; + } + } + + return candidate.toString(); + } + + /** + * @return true is all the elements of candidates start with starts + */ + private boolean startsWith(final String starts, final String[] candidates) { + for (String candidate : candidates) { + if (!candidate.startsWith(starts)) { + return false; + } + } + + return true; + } + + private static enum Messages + { + DISPLAY_CANDIDATES, + DISPLAY_CANDIDATES_YES, + DISPLAY_CANDIDATES_NO,; + + private static final + ResourceBundle + bundle = + ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault()); + + public String format(final Object... args) { + if (bundle == null) + return ""; + else + return String.format(bundle.getString(name()), args); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,13 @@ +# +# Copyright (c) 2002-2012, the original author or authors. +# +# This software is distributable under the BSD license. See the terms of the +# BSD license in the documentation provided with this software. +# +# http://www.opensource.org/licenses/bsd-license.php +# + +DISPLAY_CANDIDATES=Display all %d possibilities? (y or n) +DISPLAY_CANDIDATES_YES=y +DISPLAY_CANDIDATES_NO=n +DISPLAY_MORE=--More-- diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import java.util.List; + +/** + * A completer is the mechanism by which tab-completion candidates will be resolved. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public interface Completer +{ + // + // FIXME: Check if we can use CharSequece for buffer? + // + + /** + * Populates candidates with a list of possible completions for the buffer. + * + * The candidates list will not be sorted before being displayed to the user: thus, the + * complete method should sort the {@link List} before returning. + * + * @param buffer The buffer + * @param cursor The current position of the cursor in the buffer + * @param candidates The {@link List} of candidates to populate + * @return The index of the buffer for which the completion will be relative + */ + int complete(String buffer, int cursor, List candidates); +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import jdk.internal.jline.console.ConsoleReader; + +import java.io.IOException; +import java.util.List; + +/** + * Handler for dealing with candidates for tab-completion. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public interface CompletionHandler +{ + boolean complete(ConsoleReader reader, List candidates, int position) throws IOException; +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * {@link Completer} for {@link Enum} names. + * + * @author Jason Dillon + * @since 2.3 + */ +public class EnumCompleter + extends StringsCompleter +{ + public EnumCompleter(Class> source) { + checkNotNull(source); + + for (Enum n : source.getEnumConstants()) { + this.getStrings().add(n.name().toLowerCase()); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import jdk.internal.jline.internal.Configuration; + +import java.io.File; +import java.util.List; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * A file name completer takes the buffer and issues a list of + * potential completions. + *

+ * This completer tries to behave as similar as possible to + * bash's file name completion (using GNU readline) + * with the following exceptions: + *

+ *

    + *
  • Candidates that are directories will end with "/"
  • + *
  • Wildcard regular expressions are not evaluated or replaced
  • + *
  • The "~" character can be used to represent the user's home, + * but it cannot complete to other users' homes, since java does + * not provide any way of determining that easily
  • + *
+ * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public class FileNameCompleter + implements Completer +{ + // TODO: Handle files with spaces in them + + private static final boolean OS_IS_WINDOWS; + + static { + String os = Configuration.getOsName(); + OS_IS_WINDOWS = os.contains("windows"); + } + + public int complete(String buffer, final int cursor, final List candidates) { + // buffer can be null + checkNotNull(candidates); + + if (buffer == null) { + buffer = ""; + } + + if (OS_IS_WINDOWS) { + buffer = buffer.replace('/', '\\'); + } + + String translated = buffer; + + File homeDir = getUserHome(); + + // Special character: ~ maps to the user's home directory + if (translated.startsWith("~" + separator())) { + translated = homeDir.getPath() + translated.substring(1); + } + else if (translated.startsWith("~")) { + translated = homeDir.getParentFile().getAbsolutePath(); + } + else if (!(new File(translated).isAbsolute())) { + String cwd = getUserDir().getAbsolutePath(); + translated = cwd + separator() + translated; + } + + File file = new File(translated); + final File dir; + + if (translated.endsWith(separator())) { + dir = file; + } + else { + dir = file.getParentFile(); + } + + File[] entries = dir == null ? new File[0] : dir.listFiles(); + + return matchFiles(buffer, translated, entries, candidates); + } + + protected String separator() { + return File.separator; + } + + protected File getUserHome() { + return Configuration.getUserHome(); + } + + protected File getUserDir() { + return new File("."); + } + + protected int matchFiles(final String buffer, final String translated, final File[] files, final List candidates) { + if (files == null) { + return -1; + } + + int matches = 0; + + // first pass: just count the matches + for (File file : files) { + if (file.getAbsolutePath().startsWith(translated)) { + matches++; + } + } + for (File file : files) { + if (file.getAbsolutePath().startsWith(translated)) { + CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " "); + candidates.add(render(file, name).toString()); + } + } + + final int index = buffer.lastIndexOf(separator()); + + return index + separator().length(); + } + + protected CharSequence render(final File file, final CharSequence name) { + return name; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import java.util.List; + +/** + * Null completer. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public final class NullCompleter + implements Completer +{ + public static final NullCompleter INSTANCE = new NullCompleter(); + + public int complete(final String buffer, final int cursor, final List candidates) { + return -1; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.completer; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Completer for a set of strings. + * + * @author Jason Dillon + * @since 2.3 + */ +public class StringsCompleter + implements Completer +{ + private final SortedSet strings = new TreeSet(); + + public StringsCompleter() { + // empty + } + + public StringsCompleter(final Collection strings) { + checkNotNull(strings); + getStrings().addAll(strings); + } + + public StringsCompleter(final String... strings) { + this(Arrays.asList(strings)); + } + + public Collection getStrings() { + return strings; + } + + public int complete(final String buffer, final int cursor, final List candidates) { + // buffer could be null + checkNotNull(candidates); + + if (buffer == null) { + candidates.addAll(strings); + } + else { + for (String match : strings.tailSet(buffer)) { + if (!match.startsWith(buffer)) { + break; + } + + candidates.add(match); + } + } + + if (candidates.size() == 1) { + candidates.set(0, candidates.get(0) + " "); + } + + return candidates.isEmpty() ? -1 : 0; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +/** + * Console completer support. + * + * @since 2.3 + */ +package jdk.internal.jline.console.completer; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.history; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.Flushable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.Reader; + +import jdk.internal.jline.internal.Log; +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * {@link History} using a file for persistent backing. + *

+ * Implementers should install shutdown hook to call {@link FileHistory#flush} + * to save history to disk. + * + * @author Jason Dillon + * @since 2.0 + */ +public class FileHistory + extends MemoryHistory + implements PersistentHistory, Flushable +{ + private final File file; + + public FileHistory(final File file) throws IOException { + this.file = checkNotNull(file); + load(file); + } + + public File getFile() { + return file; + } + + public void load(final File file) throws IOException { + checkNotNull(file); + if (file.exists()) { + Log.trace("Loading history from: ", file); + load(new FileReader(file)); + } + } + + public void load(final InputStream input) throws IOException { + checkNotNull(input); + load(new InputStreamReader(input)); + } + + public void load(final Reader reader) throws IOException { + checkNotNull(reader); + BufferedReader input = new BufferedReader(reader); + + String item; + while ((item = input.readLine()) != null) { + internalAdd(item); + } + } + + public void flush() throws IOException { + Log.trace("Flushing history"); + + if (!file.exists()) { + File dir = file.getParentFile(); + if (!dir.exists() && !dir.mkdirs()) { + Log.warn("Failed to create directory: ", dir); + } + if (!file.createNewFile()) { + Log.warn("Failed to create file: ", file); + } + } + + PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file))); + try { + for (Entry entry : this) { + out.println(entry.value()); + } + } + finally { + out.close(); + } + } + + public void purge() throws IOException { + Log.trace("Purging history"); + + clear(); + + if (!file.delete()) { + Log.warn("Failed to delete history file: ", file); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.history; + +import java.util.Iterator; +import java.util.ListIterator; + +/** + * Console history. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public interface History + extends Iterable +{ + int size(); + + boolean isEmpty(); + + int index(); + + void clear(); + + CharSequence get(int index); + + void add(CharSequence line); + + /** + * Set the history item at the given index to the given CharSequence. + * + * @param index the index of the history offset + * @param item the new item + * @since 2.7 + */ + void set(int index, CharSequence item); + + /** + * Remove the history element at the given index. + * + * @param i the index of the element to remove + * @return the removed element + * @since 2.7 + */ + CharSequence remove(int i); + + /** + * Remove the first element from history. + * + * @return the removed element + * @since 2.7 + */ + CharSequence removeFirst(); + + /** + * Remove the last element from history + * + * @return the removed element + * @since 2.7 + */ + CharSequence removeLast(); + + void replace(CharSequence item); + + // + // Entries + // + + interface Entry + { + int index(); + + CharSequence value(); + } + + ListIterator entries(int index); + + ListIterator entries(); + + Iterator iterator(); + + // + // Navigation + // + + CharSequence current(); + + boolean previous(); + + boolean next(); + + boolean moveToFirst(); + + boolean moveToLast(); + + boolean moveTo(int index); + + void moveToEnd(); +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.history; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Non-persistent {@link History}. + * + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 + */ +public class MemoryHistory + implements History +{ + public static final int DEFAULT_MAX_SIZE = 500; + + private final LinkedList items = new LinkedList(); + + private int maxSize = DEFAULT_MAX_SIZE; + + private boolean ignoreDuplicates = true; + + private boolean autoTrim = false; + + // NOTE: These are all ideas from looking at the Bash man page: + + // TODO: Add ignore space? (lines starting with a space are ignored) + + // TODO: Add ignore patterns? + + // TODO: Add history timestamp? + + // TODO: Add erase dups? + + private int offset = 0; + + private int index = 0; + + public void setMaxSize(final int maxSize) { + this.maxSize = maxSize; + maybeResize(); + } + + public int getMaxSize() { + return maxSize; + } + + public boolean isIgnoreDuplicates() { + return ignoreDuplicates; + } + + public void setIgnoreDuplicates(final boolean flag) { + this.ignoreDuplicates = flag; + } + + public boolean isAutoTrim() { + return autoTrim; + } + + public void setAutoTrim(final boolean flag) { + this.autoTrim = flag; + } + + public int size() { + return items.size(); + } + + public boolean isEmpty() { + return items.isEmpty(); + } + + public int index() { + return offset + index; + } + + public void clear() { + items.clear(); + offset = 0; + index = 0; + } + + public CharSequence get(final int index) { + return items.get(index - offset); + } + + public void set(int index, CharSequence item) { + items.set(index - offset, item); + } + + public void add(CharSequence item) { + checkNotNull(item); + + if (isAutoTrim()) { + item = String.valueOf(item).trim(); + } + + if (isIgnoreDuplicates()) { + if (!items.isEmpty() && item.equals(items.getLast())) { + return; + } + } + + internalAdd(item); + } + + public CharSequence remove(int i) { + return items.remove(i); + } + + public CharSequence removeFirst() { + return items.removeFirst(); + } + + public CharSequence removeLast() { + return items.removeLast(); + } + + protected void internalAdd(CharSequence item) { + items.add(item); + + maybeResize(); + } + + public void replace(final CharSequence item) { + items.removeLast(); + add(item); + } + + private void maybeResize() { + while (size() > getMaxSize()) { + items.removeFirst(); + offset++; + } + + index = size(); + } + + public ListIterator entries(final int index) { + return new EntriesIterator(index - offset); + } + + public ListIterator entries() { + return entries(offset); + } + + public Iterator iterator() { + return entries(); + } + + private static class EntryImpl + implements Entry + { + private final int index; + + private final CharSequence value; + + public EntryImpl(int index, CharSequence value) { + this.index = index; + this.value = value; + } + + public int index() { + return index; + } + + public CharSequence value() { + return value; + } + + @Override + public String toString() { + return String.format("%d: %s", index, value); + } + } + + private class EntriesIterator + implements ListIterator + { + private final ListIterator source; + + private EntriesIterator(final int index) { + source = items.listIterator(index); + } + + public Entry next() { + if (!source.hasNext()) { + throw new NoSuchElementException(); + } + return new EntryImpl(offset + source.nextIndex(), source.next()); + } + + public Entry previous() { + if (!source.hasPrevious()) { + throw new NoSuchElementException(); + } + return new EntryImpl(offset + source.previousIndex(), source.previous()); + } + + public int nextIndex() { + return offset + source.nextIndex(); + } + + public int previousIndex() { + return offset + source.previousIndex(); + } + + public boolean hasNext() { + return source.hasNext(); + } + + public boolean hasPrevious() { + return source.hasPrevious(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public void set(final Entry entry) { + throw new UnsupportedOperationException(); + } + + public void add(final Entry entry) { + throw new UnsupportedOperationException(); + } + } + + // + // Navigation + // + + /** + * This moves the history to the last entry. This entry is one position + * before the moveToEnd() position. + * + * @return Returns false if there were no history entries or the history + * index was already at the last entry. + */ + public boolean moveToLast() { + int lastEntry = size() - 1; + if (lastEntry >= 0 && lastEntry != index) { + index = size() - 1; + return true; + } + + return false; + } + + /** + * Move to the specified index in the history + * @param index + * @return + */ + public boolean moveTo(int index) { + index -= offset; + if (index >= 0 && index < size() ) { + this.index = index; + return true; + } + return false; + } + + /** + * Moves the history index to the first entry. + * + * @return Return false if there are no entries in the history or if the + * history is already at the beginning. + */ + public boolean moveToFirst() { + if (size() > 0 && index != 0) { + index = 0; + return true; + } + + return false; + } + + /** + * Move to the end of the history buffer. This will be a blank entry, after + * all of the other entries. + */ + public void moveToEnd() { + index = size(); + } + + /** + * Return the content of the current buffer. + */ + public CharSequence current() { + if (index >= size()) { + return ""; + } + + return items.get(index); + } + + /** + * Move the pointer to the previous element in the buffer. + * + * @return true if we successfully went to the previous element + */ + public boolean previous() { + if (index <= 0) { + return false; + } + + index--; + + return true; + } + + /** + * Move the pointer to the next element in the buffer. + * + * @return true if we successfully went to the next element + */ + public boolean next() { + if (index >= size()) { + return false; + } + + index++; + + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (Entry e : this) { + sb.append(e.toString() + "\n"); + } + return sb.toString(); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.history; + +import java.io.IOException; + +/** + * Persistent {@link History}. + * + * @author Jason Dillon + * @since 2.3 + */ +public interface PersistentHistory + extends History +{ + /** + * Flush all items to persistent storage. + * + * @throws IOException Flush failed + */ + void flush() throws IOException; + + /** + * Purge persistent storage and {@link #clear}. + * + * @throws IOException Purge failed + */ + void purge() throws IOException; +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +/** + * Console history support. + * + * @since 2.0 + */ +package jdk.internal.jline.console.history; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.internal; + +import jdk.internal.jline.console.ConsoleReader; + +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.util.Enumeration; + +// FIXME: Clean up API and move to jline.console.runner package + +/** + * An {@link InputStream} implementation that wraps a {@link ConsoleReader}. + * It is useful for setting up the {@link System#in} for a generic console. + * + * @author Marc Prud'hommeaux + * @since 2.7 + */ +class ConsoleReaderInputStream + extends SequenceInputStream +{ + private static InputStream systemIn = System.in; + + public static void setIn() throws IOException { + setIn(new ConsoleReader()); + } + + public static void setIn(final ConsoleReader reader) { + System.setIn(new ConsoleReaderInputStream(reader)); + } + + /** + * Restore the original {@link System#in} input stream. + */ + public static void restoreIn() { + System.setIn(systemIn); + } + + public ConsoleReaderInputStream(final ConsoleReader reader) { + super(new ConsoleEnumeration(reader)); + } + + private static class ConsoleEnumeration + implements Enumeration + { + private final ConsoleReader reader; + private ConsoleLineInputStream next = null; + private ConsoleLineInputStream prev = null; + + public ConsoleEnumeration(final ConsoleReader reader) { + this.reader = reader; + } + + public InputStream nextElement() { + if (next != null) { + InputStream n = next; + prev = next; + next = null; + + return n; + } + + return new ConsoleLineInputStream(reader); + } + + public boolean hasMoreElements() { + // the last line was null + if ((prev != null) && (prev.wasNull == true)) { + return false; + } + + if (next == null) { + next = (ConsoleLineInputStream) nextElement(); + } + + return next != null; + } + } + + private static class ConsoleLineInputStream + extends InputStream + { + private final ConsoleReader reader; + private String line = null; + private int index = 0; + private boolean eol = false; + protected boolean wasNull = false; + + public ConsoleLineInputStream(final ConsoleReader reader) { + this.reader = reader; + } + + public int read() throws IOException { + if (eol) { + return -1; + } + + if (line == null) { + line = reader.readLine(); + } + + if (line == null) { + wasNull = true; + return -1; + } + + if (index >= line.length()) { + eol = true; + return '\n'; // lines are ended with a newline + } + + return line.charAt(index++); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.console.internal; + +import jdk.internal.jline.console.ConsoleReader; +import jdk.internal.jline.console.completer.ArgumentCompleter; +import jdk.internal.jline.console.completer.Completer; +import jdk.internal.jline.console.history.FileHistory; +import jdk.internal.jline.internal.Configuration; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +// FIXME: Clean up API and move to jline.console.runner package + +/** + * A pass-through application that sets the system input stream to a + * {@link ConsoleReader} and invokes the specified main method. + * + * @author Marc Prud'hommeaux + * @since 2.7 + */ +public class ConsoleRunner +{ + public static final String property = "jline.history"; + + // FIXME: This is really ugly... re-write this + + public static void main(final String[] args) throws Exception { + List argList = new ArrayList(Arrays.asList(args)); + if (argList.size() == 0) { + usage(); + return; + } + + String historyFileName = System.getProperty(ConsoleRunner.property, null); + + String mainClass = argList.remove(0); + ConsoleReader reader = new ConsoleReader(); + + if (historyFileName != null) { + reader.setHistory(new FileHistory(new File(Configuration.getUserHome(), + String.format(".jline-%s.%s.history", mainClass, historyFileName)))); + } + else { + reader.setHistory(new FileHistory(new File(Configuration.getUserHome(), + String.format(".jline-%s.history", mainClass)))); + } + + String completors = System.getProperty(ConsoleRunner.class.getName() + ".completers", ""); + List completorList = new ArrayList(); + + for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) { + Object obj = Class.forName(tok.nextToken()).newInstance(); + completorList.add((Completer) obj); + } + + if (completorList.size() > 0) { + reader.addCompleter(new ArgumentCompleter(completorList)); + } + + ConsoleReaderInputStream.setIn(reader); + + try { + Class type = Class.forName(mainClass); + Method method = type.getMethod("main", String[].class); + method.invoke(null); + } + finally { + // just in case this main method is called from another program + ConsoleReaderInputStream.restoreIn(); + } + } + + private static void usage() { + System.out.println("Usage: \n java " + "[-Djline.history='name'] " + + ConsoleRunner.class.getName() + + " [args]" + + "\n\nThe -Djline.history option will avoid history" + + "\nmangling when running ConsoleRunner on the same application." + + "\n\nargs will be passed directly to the target class name."); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +/** + * Console support. + * + * @since 2.0 + */ +package jdk.internal.jline.console; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Properties; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Provides access to configuration values. + * + * @author Jason Dillon + * @author Guillaume Nodet + * @since 2.4 + */ +public class Configuration +{ + /** + * System property which can point to a file or URL containing configuration properties to load. + * + * @since 2.7 + */ + public static final String JLINE_CONFIGURATION = "jline.configuration"; + + /** + * Default configuration file name loaded from user's home directory. + */ + public static final String JLINE_RC = ".jline.rc"; + + private static volatile Properties properties; + + private static Properties initProperties() { + URL url = determineUrl(); + Properties props = new Properties(); + try { + loadProperties(url, props); + } + catch (IOException e) { + // debug here instead of warn, as this can happen normally if default jline.rc file is missing + Log.debug("Unable to read configuration from: ", url, e); + } + return props; + } + + private static void loadProperties(final URL url, final Properties props) throws IOException { + Log.debug("Loading properties from: ", url); + InputStream input = url.openStream(); + try { + props.load(new BufferedInputStream(input)); + } + finally { + try { + input.close(); + } + catch (IOException e) { + // ignore + } + } + + if (Log.DEBUG) { + Log.debug("Loaded properties:"); + for (Map.Entry entry : props.entrySet()) { + Log.debug(" ", entry.getKey(), "=", entry.getValue()); + } + } + } + + private static URL determineUrl() { + // See if user has customized the configuration location via sysprop + String tmp = System.getProperty(JLINE_CONFIGURATION); + if (tmp != null) { + return Urls.create(tmp); + } + else { + // Otherwise try the default + File file = new File(getUserHome(), JLINE_RC); + return Urls.create(file); + } + } + + /** + * @since 2.7 + */ + public static void reset() { + Log.debug("Resetting"); + properties = null; + + // force new properties to load + getProperties(); + } + + /** + * @since 2.7 + */ + public static Properties getProperties() { + // Not sure its worth to guard this with any synchronization, volatile field probably sufficient + if (properties == null) { + properties = initProperties(); + } + return properties; + } + + public static String getString(final String name, final String defaultValue) { + checkNotNull(name); + + String value; + + // Check sysprops first, it always wins + value = System.getProperty(name); + + if (value == null) { + // Next try userprops + value = getProperties().getProperty(name); + + if (value == null) { + // else use the default + value = defaultValue; + } + } + + return value; + } + + public static String getString(final String name) { + return getString(name, null); + } + + public static boolean getBoolean(final String name, final boolean defaultValue) { + String value = getString(name); + if (value == null) { + return defaultValue; + } + return value.length() == 0 + || value.equalsIgnoreCase("1") + || value.equalsIgnoreCase("on") + || value.equalsIgnoreCase("true"); + } + + /** + * @since 2.6 + */ + public static int getInteger(final String name, final int defaultValue) { + String str = getString(name); + if (str == null) { + return defaultValue; + } + return Integer.parseInt(str); + } + + /** + * @since 2.6 + */ + public static long getLong(final String name, final long defaultValue) { + String str = getString(name); + if (str == null) { + return defaultValue; + } + return Long.parseLong(str); + } + + // + // System property helpers + // + + /** + * @since 2.7 + */ + public static String getLineSeparator() { + return System.getProperty("line.separator"); + } + + public static File getUserHome() { + return new File(System.getProperty("user.home")); + } + + public static String getOsName() { + return System.getProperty("os.name").toLowerCase(); + } + + /** + * @since 2.7 + */ + public static boolean isWindows() { + return getOsName().startsWith("windows"); + } + + // FIXME: Sort out use of property access of file.encoding in InputStreamReader, consolidate should configuration access here + + public static String getFileEncoding() { + return System.getProperty("file.encoding"); + } + + /** + * Get the default encoding. Will first look at the LC_CTYPE environment variable, then the input.encoding + * system property, then the default charset according to the JVM. + * + * @return The default encoding to use when none is specified. + */ + public static String getEncoding() { + // LC_CTYPE is usually in the form en_US.UTF-8 + String envEncoding = extractEncodingFromCtype(System.getenv("LC_CTYPE")); + if (envEncoding != null) { + return envEncoding; + } + return System.getProperty("input.encoding", Charset.defaultCharset().name()); + } + + /** + * Parses the LC_CTYPE value to extract the encoding according to the POSIX standard, which says that the LC_CTYPE + * environment variable may be of the format [language[_territory][.codeset][@modifier]] + * + * @param ctype The ctype to parse, may be null + * @return The encoding, if one was present, otherwise null + */ + static String extractEncodingFromCtype(String ctype) { + if (ctype != null && ctype.indexOf('.') > 0) { + String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1); + if (encodingAndModifier.indexOf('@') > 0) { + return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@')); + } else { + return encodingAndModifier; + } + } + return null; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.MalformedInputException; +import java.nio.charset.UnmappableCharacterException; + + +/** + * + * NOTE for JLine: the default InputStreamReader that comes from the JRE + * usually read more bytes than needed from the input stream, which + * is not usable in a character per character model used in the console. + * We thus use the harmony code which only reads the minimal number of bytes, + * with a modification to ensure we can read larger characters (UTF-16 has + * up to 4 bytes, and UTF-32, rare as it is, may have up to 8). + */ +/** + * A class for turning a byte stream into a character stream. Data read from the + * source input stream is converted into characters by either a default or a + * provided character converter. The default encoding is taken from the + * "file.encoding" system property. {@code InputStreamReader} contains a buffer + * of bytes read from the source stream and converts these into characters as + * needed. The buffer size is 8K. + * + * @see OutputStreamWriter + */ +public class InputStreamReader extends Reader { + private InputStream in; + + private static final int BUFFER_SIZE = 8192; + + private boolean endOfInput = false; + + String encoding; + + CharsetDecoder decoder; + + ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE); + + /** + * Constructs a new {@code InputStreamReader} on the {@link InputStream} + * {@code in}. This constructor sets the character converter to the encoding + * specified in the "file.encoding" property and falls back to ISO 8859_1 + * (ISO-Latin-1) if the property doesn't exist. + * + * @param in + * the input stream from which to read characters. + */ + public InputStreamReader(InputStream in) { + super(in); + this.in = in; + // FIXME: This should probably use Configuration.getFileEncoding() + encoding = System.getProperty("file.encoding", "ISO8859_1"); //$NON-NLS-1$//$NON-NLS-2$ + decoder = Charset.forName(encoding).newDecoder().onMalformedInput( + CodingErrorAction.REPLACE).onUnmappableCharacter( + CodingErrorAction.REPLACE); + bytes.limit(0); + } + + /** + * Constructs a new InputStreamReader on the InputStream {@code in}. The + * character converter that is used to decode bytes into characters is + * identified by name by {@code enc}. If the encoding cannot be found, an + * UnsupportedEncodingException error is thrown. + * + * @param in + * the InputStream from which to read characters. + * @param enc + * identifies the character converter to use. + * @throws NullPointerException + * if {@code enc} is {@code null}. + * @throws UnsupportedEncodingException + * if the encoding specified by {@code enc} cannot be found. + */ + public InputStreamReader(InputStream in, final String enc) + throws UnsupportedEncodingException { + super(in); + if (enc == null) { + throw new NullPointerException(); + } + this.in = in; + try { + decoder = Charset.forName(enc).newDecoder().onMalformedInput( + CodingErrorAction.REPLACE).onUnmappableCharacter( + CodingErrorAction.REPLACE); + } catch (IllegalArgumentException e) { + throw (UnsupportedEncodingException) + new UnsupportedEncodingException(enc).initCause(e); + } + bytes.limit(0); + } + + /** + * Constructs a new InputStreamReader on the InputStream {@code in} and + * CharsetDecoder {@code dec}. + * + * @param in + * the source InputStream from which to read characters. + * @param dec + * the CharsetDecoder used by the character conversion. + */ + public InputStreamReader(InputStream in, CharsetDecoder dec) { + super(in); + dec.averageCharsPerByte(); + this.in = in; + decoder = dec; + bytes.limit(0); + } + + /** + * Constructs a new InputStreamReader on the InputStream {@code in} and + * Charset {@code charset}. + * + * @param in + * the source InputStream from which to read characters. + * @param charset + * the Charset that defines the character converter + */ + public InputStreamReader(InputStream in, Charset charset) { + super(in); + this.in = in; + decoder = charset.newDecoder().onMalformedInput( + CodingErrorAction.REPLACE).onUnmappableCharacter( + CodingErrorAction.REPLACE); + bytes.limit(0); + } + + /** + * Closes this reader. This implementation closes the source InputStream and + * releases all local storage. + * + * @throws IOException + * if an error occurs attempting to close this reader. + */ + @Override + public void close() throws IOException { + synchronized (lock) { + decoder = null; + if (in != null) { + in.close(); + in = null; + } + } + } + + /** + * Returns the name of the encoding used to convert bytes into characters. + * The value {@code null} is returned if this reader has been closed. + * + * @return the name of the character converter or {@code null} if this + * reader is closed. + */ + public String getEncoding() { + if (!isOpen()) { + return null; + } + return encoding; + } + + /** + * Reads a single character from this reader and returns it as an integer + * with the two higher-order bytes set to 0. Returns -1 if the end of the + * reader has been reached. The byte value is either obtained from + * converting bytes in this reader's buffer or by first filling the buffer + * from the source InputStream and then reading from the buffer. + * + * @return the character read or -1 if the end of the reader has been + * reached. + * @throws IOException + * if this reader is closed or some other I/O error occurs. + */ + @Override + public int read() throws IOException { + synchronized (lock) { + if (!isOpen()) { + throw new IOException("InputStreamReader is closed."); + } + + char buf[] = new char[4]; + return read(buf, 0, 4) != -1 ? Character.codePointAt(buf, 0) : -1; + } + } + + /** + * Reads at most {@code length} characters from this reader and stores them + * at position {@code offset} in the character array {@code buf}. Returns + * the number of characters actually read or -1 if the end of the reader has + * been reached. The bytes are either obtained from converting bytes in this + * reader's buffer or by first filling the buffer from the source + * InputStream and then reading from the buffer. + * + * @param buf + * the array to store the characters read. + * @param offset + * the initial position in {@code buf} to store the characters + * read from this reader. + * @param length + * the maximum number of characters to read. + * @return the number of characters read or -1 if the end of the reader has + * been reached. + * @throws IndexOutOfBoundsException + * if {@code offset < 0} or {@code length < 0}, or if + * {@code offset + length} is greater than the length of + * {@code buf}. + * @throws IOException + * if this reader is closed or some other I/O error occurs. + */ + @Override + public int read(char[] buf, int offset, int length) throws IOException { + synchronized (lock) { + if (!isOpen()) { + throw new IOException("InputStreamReader is closed."); + } + if (offset < 0 || offset > buf.length - length || length < 0) { + throw new IndexOutOfBoundsException(); + } + if (length == 0) { + return 0; + } + + CharBuffer out = CharBuffer.wrap(buf, offset, length); + CoderResult result = CoderResult.UNDERFLOW; + + // bytes.remaining() indicates number of bytes in buffer + // when 1-st time entered, it'll be equal to zero + boolean needInput = !bytes.hasRemaining(); + + while (out.hasRemaining()) { + // fill the buffer if needed + if (needInput) { + try { + if ((in.available() == 0) + && (out.position() > offset)) { + // we could return the result without blocking read + break; + } + } catch (IOException e) { + // available didn't work so just try the read + } + + int to_read = bytes.capacity() - bytes.limit(); + int off = bytes.arrayOffset() + bytes.limit(); + int was_red = in.read(bytes.array(), off, to_read); + + if (was_red == -1) { + endOfInput = true; + break; + } else if (was_red == 0) { + break; + } + bytes.limit(bytes.limit() + was_red); + needInput = false; + } + + // decode bytes + result = decoder.decode(bytes, out, false); + + if (result.isUnderflow()) { + // compact the buffer if no space left + if (bytes.limit() == bytes.capacity()) { + bytes.compact(); + bytes.limit(bytes.position()); + bytes.position(0); + } + needInput = true; + } else { + break; + } + } + + if (result == CoderResult.UNDERFLOW && endOfInput) { + result = decoder.decode(bytes, out, true); + decoder.flush(out); + decoder.reset(); + } + if (result.isMalformed()) { + throw new MalformedInputException(result.length()); + } else if (result.isUnmappable()) { + throw new UnmappableCharacterException(result.length()); + } + + return out.position() - offset == 0 ? -1 : out.position() - offset; + } + } + + /* + * Answer a boolean indicating whether or not this InputStreamReader is + * open. + */ + private boolean isOpen() { + return in != null; + } + + /** + * Indicates whether this reader is ready to be read without blocking. If + * the result is {@code true}, the next {@code read()} will not block. If + * the result is {@code false} then this reader may or may not block when + * {@code read()} is called. This implementation returns {@code true} if + * there are bytes available in the buffer or the source stream has bytes + * available. + * + * @return {@code true} if the receiver will not block when {@code read()} + * is called, {@code false} if unknown or blocking will occur. + * @throws IOException + * if this reader is closed or some other I/O error occurs. + */ + @Override + public boolean ready() throws IOException { + synchronized (lock) { + if (in == null) { + throw new IOException("InputStreamReader is closed."); + } + try { + return bytes.hasRemaining() || in.available() > 0; + } catch (IOException e) { + return false; + } + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.io.PrintStream; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Internal logger. + * + * @author Jason Dillon + * @since 2.0 + */ +public final class Log +{ + ///CLOVER:OFF + + public static enum Level + { + TRACE, + DEBUG, + INFO, + WARN, + ERROR + } + + @SuppressWarnings({"StringConcatenation"}) + public static final boolean TRACE = Boolean.getBoolean(Log.class.getName() + ".trace"); + + @SuppressWarnings({"StringConcatenation"}) + public static final boolean DEBUG = TRACE || Boolean.getBoolean(Log.class.getName() + ".debug"); + + private static PrintStream output = System.err; + + public static PrintStream getOutput() { + return output; + } + + public static void setOutput(final PrintStream out) { + output = checkNotNull(out); + } + + /** + * Helper to support rendering messages. + */ + @TestAccessible + static void render(final PrintStream out, final Object message) { + if (message.getClass().isArray()) { + Object[] array = (Object[]) message; + + out.print("["); + for (int i = 0; i < array.length; i++) { + out.print(array[i]); + if (i + 1 < array.length) { + out.print(","); + } + } + out.print("]"); + } + else { + out.print(message); + } + } + + @TestAccessible + static void log(final Level level, final Object... messages) { + //noinspection SynchronizeOnNonFinalField + synchronized (output) { + output.format("[%s] ", level); + + for (int i=0; iVERY IMPORTANT NOTES + *

    + *
  • This class is not thread safe. It expects at most one reader. + *
  • The {@link #shutdown()} method must be called in order to shut down + * the thread that handles blocking I/O. + *
+ * @since 2.7 + * @author Scott C. Gray + */ +public class NonBlockingInputStream + extends InputStream + implements Runnable +{ + private InputStream in; // The actual input stream + private int ch = -2; // Recently read character + + private boolean threadIsReading = false; + private boolean isShutdown = false; + private IOException exception = null; + private boolean nonBlockingEnabled; + + /** + * Creates a NonBlockingInputStream out of a normal blocking + * stream. Note that this call also spawn a separate thread to perform the + * blocking I/O on behalf of the thread that is using this class. The + * {@link #shutdown()} method must be called in order to shut this thread down. + * @param in The input stream to wrap + * @param isNonBlockingEnabled If true, then the non-blocking methods + * {@link #read(long)} and {@link #peek(long)} will be available and, + * more importantly, the thread will be started to provide support for the + * feature. If false, then this class acts as a clean-passthru for the + * underlying I/O stream and provides very little overhead. + */ + public NonBlockingInputStream (InputStream in, boolean isNonBlockingEnabled) { + this.in = in; + this.nonBlockingEnabled = isNonBlockingEnabled; + + if (isNonBlockingEnabled) { + Thread t = new Thread(this); + t.setName("NonBlockingInputStreamThread"); + t.setDaemon(true); + t.start(); + } + } + + /** + * Shuts down the thread that is handling blocking I/O. Note that if the + * thread is currently blocked waiting for I/O it will not actually + * shut down until the I/O is received. Shutting down the I/O thread + * does not prevent this class from being used, but causes the + * non-blocking methods to fail if called and causes {@link #isNonBlockingEnabled()} + * to return false. + */ + public synchronized void shutdown() { + if (!isShutdown && nonBlockingEnabled) { + isShutdown = true; + notify(); + } + } + + /** + * Non-blocking is considered enabled if the feature is enabled and the + * I/O thread has not been shut down. + * @return true if non-blocking mode is enabled. + */ + public boolean isNonBlockingEnabled() { + return nonBlockingEnabled && !isShutdown; + } + + @Override + public void close() throws IOException { + /* + * The underlying input stream is closed first. This means that if the + * I/O thread was blocked waiting on input, it will be woken for us. + */ + in.close(); + shutdown(); + } + + @Override + public int read() throws IOException { + if (nonBlockingEnabled) + return read(0L, false); + return in.read (); + } + + /** + * Peeks to see if there is a byte waiting in the input stream without + * actually consuming the byte. + * + * @param timeout The amount of time to wait, 0 == forever + * @return -1 on eof, -2 if the timeout expired with no available input + * or the character that was read (without consuming it). + * @throws IOException + */ + public int peek(long timeout) throws IOException { + if (!nonBlockingEnabled || isShutdown) { + throw new UnsupportedOperationException ("peek() " + + "cannot be called as non-blocking operation is disabled"); + } + return read(timeout, true); + } + + /** + * Attempts to read a character from the input stream for a specific + * period of time. + * @param timeout The amount of time to wait for the character + * @return The character read, -1 if EOF is reached, or -2 if the + * read timed out. + * @throws IOException + */ + public int read(long timeout) throws IOException { + if (!nonBlockingEnabled || isShutdown) { + throw new UnsupportedOperationException ("read() with timeout " + + "cannot be called as non-blocking operation is disabled"); + } + return read(timeout, false); + } + + /** + * Attempts to read a character from the input stream for a specific + * period of time. + * @param timeout The amount of time to wait for the character + * @return The character read, -1 if EOF is reached, or -2 if the + * read timed out. + * @throws IOException + */ + private synchronized int read(long timeout, boolean isPeek) throws IOException { + /* + * If the thread hit an IOException, we report it. + */ + if (exception != null) { + assert ch == -2; + IOException toBeThrown = exception; + if (!isPeek) + exception = null; + throw toBeThrown; + } + + /* + * If there was a pending character from the thread, then + * we send it. If the timeout is 0L or the thread was shut down + * then do a local read. + */ + if (ch >= -1) { + assert exception == null; + } + else if ((timeout == 0L || isShutdown) && !threadIsReading) { + ch = in.read(); + } + else { + /* + * If the thread isn't reading already, then ask it to do so. + */ + if (!threadIsReading) { + threadIsReading = true; + notify(); + } + + boolean isInfinite = (timeout <= 0L); + + /* + * So the thread is currently doing the reading for us. So + * now we play the waiting game. + */ + while (isInfinite || timeout > 0L) { + long start = System.currentTimeMillis (); + + try { + wait(timeout); + } + catch (InterruptedException e) { + /* IGNORED */ + } + + if (exception != null) { + assert ch == -2; + + IOException toBeThrown = exception; + if (!isPeek) + exception = null; + throw toBeThrown; + } + + if (ch >= -1) { + assert exception == null; + break; + } + + if (!isInfinite) { + timeout -= System.currentTimeMillis() - start; + } + } + } + + /* + * ch is the character that was just read. Either we set it because + * a local read was performed or the read thread set it (or failed to + * change it). We will return it's value, but if this was a peek + * operation, then we leave it in place. + */ + int ret = ch; + if (!isPeek) { + ch = -2; + } + return ret; + } + + /** + * This version of read() is very specific to jline's purposes, it + * will always always return a single byte at a time, rather than filling + * the entire buffer. + */ + @Override + public int read (byte[] b, int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int c; + if (nonBlockingEnabled) + c = this.read(0L); + else + c = in.read(); + + if (c == -1) { + return -1; + } + b[off] = (byte)c; + return 1; + } + + //@Override + public void run () { + Log.debug("NonBlockingInputStream start"); + boolean needToShutdown = false; + boolean needToRead = false; + + while (!needToShutdown) { + + /* + * Synchronize to grab variables accessed by both this thread + * and the accessing thread. + */ + synchronized (this) { + needToShutdown = this.isShutdown; + needToRead = this.threadIsReading; + + try { + /* + * Nothing to do? Then wait. + */ + if (!needToShutdown && !needToRead) { + wait(0); + } + } + catch (InterruptedException e) { + /* IGNORED */ + } + } + + /* + * We're not shutting down, but we need to read. This cannot + * happen while we are holding the lock (which we aren't now). + */ + if (!needToShutdown && needToRead) { + int charRead = -2; + IOException failure = null; + try { + charRead = in.read(); + } + catch (IOException e) { + failure = e; + } + + /* + * Re-grab the lock to update the state. + */ + synchronized (this) { + exception = failure; + ch = charRead; + threadIsReading = false; + notify(); + } + } + } + + Log.debug("NonBlockingInputStream shutdown"); + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.lang.annotation.*; + +/** + * Marker for reference which can be a null value. + * + * @since 2.7 + */ +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE}) +public @interface Nullable +{ + String value() default ""; +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +// Some bits lifted from Guava's ( http://code.google.com/p/guava-libraries/ ) Preconditions. + +/** + * Preconditions. + * + * @author Jason Dillon + * @since 2.7 + */ +public class Preconditions +{ + public static T checkNotNull(final T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.util.ArrayList; +import java.util.List; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Manages the JLine shutdown-hook thread and tasks to execute on shutdown. + * + * @author Jason Dillon + * @since 2.7 + */ +public class ShutdownHooks +{ + public static final String JLINE_SHUTDOWNHOOK = "jline.shutdownhook"; + + private static final boolean enabled = Configuration.getBoolean(JLINE_SHUTDOWNHOOK, true); + + private static final List tasks = new ArrayList(); + + private static Thread hook; + + public static synchronized T add(final T task) { + checkNotNull(task); + + // If not enabled ignore + if (!enabled) { + Log.debug("Shutdown-hook is disabled; not installing: ", task); + return task; + } + + // Install the hook thread if needed + if (hook == null) { + hook = addHook(new Thread("JLine Shutdown Hook") + { + @Override + public void run() { + runTasks(); + } + }); + } + + // Track the task + Log.debug("Adding shutdown-hook task: ", task); + tasks.add(task); + + return task; + } + + private static synchronized void runTasks() { + Log.debug("Running all shutdown-hook tasks"); + + // Iterate through copy of tasks list + for (Task task : tasks.toArray(new Task[tasks.size()])) { + Log.debug("Running task: ", task); + try { + task.run(); + } + catch (Throwable e) { + Log.warn("Task failed", e); + } + } + + tasks.clear(); + } + + private static Thread addHook(final Thread thread) { + Log.debug("Registering shutdown-hook: ", thread); + try { + Runtime.getRuntime().addShutdownHook(thread); + } + catch (AbstractMethodError e) { + // JDK 1.3+ only method. Bummer. + Log.debug("Failed to register shutdown-hook", e); + } + return thread; + } + + public static synchronized void remove(final Task task) { + checkNotNull(task); + + // ignore if not enabled or hook never installed + if (!enabled || hook == null) { + return; + } + + // Drop the task + tasks.remove(task); + + // If there are no more tasks, then remove the hook thread + if (tasks.isEmpty()) { + removeHook(hook); + hook = null; + } + } + + private static void removeHook(final Thread thread) { + Log.debug("Removing shutdown-hook: ", thread); + + try { + Runtime.getRuntime().removeShutdownHook(thread); + } + catch (AbstractMethodError e) { + // JDK 1.3+ only method. Bummer. + Log.debug("Failed to remove shutdown-hook", e); + } + catch (IllegalStateException e) { + // The VM is shutting down, not a big deal; ignore + } + } + + /** + * Essentially a {@link Runnable} which allows running to throw an exception. + */ + public static interface Task + { + void run() throws Exception; + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Provides access to terminal line settings via stty. + * + * @author Marc Prud'hommeaux + * @author Dale Kemp + * @author Jason Dillon + * @author Jean-Baptiste Onofr\u00E9 + * @since 2.0 + */ +public final class TerminalLineSettings +{ + public static final String JLINE_STTY = "jline.stty"; + + public static final String DEFAULT_STTY = "stty"; + + public static final String JLINE_SH = "jline.sh"; + + public static final String DEFAULT_SH = "sh"; + + private String sttyCommand; + + private String shCommand; + + private String config; + private String initialConfig; + + private long configLastFetched; + + public TerminalLineSettings() throws IOException, InterruptedException { + sttyCommand = Configuration.getString(JLINE_STTY, DEFAULT_STTY); + shCommand = Configuration.getString(JLINE_SH, DEFAULT_SH); + initialConfig = get("-g").trim(); + config = get("-a"); + configLastFetched = System.currentTimeMillis(); + + Log.debug("Config: ", config); + + // sanity check + if (config.length() == 0) { + throw new IOException(MessageFormat.format("Unrecognized stty code: {0}", config)); + } + } + + public String getConfig() { + return config; + } + + public void restore() throws IOException, InterruptedException { + set(initialConfig); + } + + public String get(final String args) throws IOException, InterruptedException { + return stty(args); + } + + public void set(final String args) throws IOException, InterruptedException { + stty(args); + } + + /** + *

+ * Get the value of a stty property, including the management of a cache. + *

+ * + * @param name the stty property. + * @return the stty property value. + */ + public int getProperty(String name) { + checkNotNull(name); + long currentTime = System.currentTimeMillis(); + try { + // tty properties are cached so we don't have to worry too much about getting term width/height + if (config == null || currentTime - configLastFetched > 1000) { + config = get("-a"); + } + } catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.debug("Failed to query stty ", name, "\n", e); + if (config == null) { + return -1; + } + } + + // always update the last fetched time and try to parse the output + if (currentTime - configLastFetched > 1000) { + configLastFetched = currentTime; + } + + return getProperty(name, config); + } + + /** + *

+ * Parses a stty output (provided by stty -a) and return the value of a given property. + *

+ * + * @param name property name. + * @param stty string resulting of stty -a execution. + * @return value of the given property. + */ + protected static int getProperty(String name, String stty) { + // try the first kind of regex + Pattern pattern = Pattern.compile(name + "\\s+=\\s+(.*?)[;\\n\\r]"); + Matcher matcher = pattern.matcher(stty); + if (!matcher.find()) { + // try a second kind of regex + pattern = Pattern.compile(name + "\\s+([^;]*)[;\\n\\r]"); + matcher = pattern.matcher(stty); + if (!matcher.find()) { + // try a second try of regex + pattern = Pattern.compile("(\\S*)\\s+" + name); + matcher = pattern.matcher(stty); + if (!matcher.find()) { + return -1; + } + } + } + return parseControlChar(matcher.group(1)); + } + + private static int parseControlChar(String str) { + // under + if ("".equals(str)) { + return -1; + } + // octal + if (str.charAt(0) == '0') { + return Integer.parseInt(str, 8); + } + // decimal + if (str.charAt(0) >= '1' && str.charAt(0) <= '9') { + return Integer.parseInt(str, 10); + } + // control char + if (str.charAt(0) == '^') { + if (str.charAt(1) == '?') { + return 127; + } else { + return str.charAt(1) - 64; + } + } else if (str.charAt(0) == 'M' && str.charAt(1) == '-') { + if (str.charAt(2) == '^') { + if (str.charAt(3) == '?') { + return 127 + 128; + } else { + return str.charAt(3) - 64 + 128; + } + } else { + return str.charAt(2) + 128; + } + } else { + return str.charAt(0); + } + } + + private String stty(final String args) throws IOException, InterruptedException { + checkNotNull(args); + return exec(String.format("%s %s < /dev/tty", sttyCommand, args)); + } + + private String exec(final String cmd) throws IOException, InterruptedException { + checkNotNull(cmd); + return exec(shCommand, "-c", cmd); + } + + private String exec(final String... cmd) throws IOException, InterruptedException { + checkNotNull(cmd); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + Log.trace("Running: ", cmd); + + Process p = Runtime.getRuntime().exec(cmd); + + InputStream in = null; + InputStream err = null; + OutputStream out = null; + try { + int c; + in = p.getInputStream(); + while ((c = in.read()) != -1) { + bout.write(c); + } + err = p.getErrorStream(); + while ((c = err.read()) != -1) { + bout.write(c); + } + out = p.getOutputStream(); + p.waitFor(); + } + finally { + close(in, out, err); + } + + String result = bout.toString(); + + Log.trace("Result: ", result); + + return result; + } + + private static void close(final Closeable... closeables) { + for (Closeable c : closeables) { + try { + c.close(); + } + catch (Exception e) { + // Ignore + } + } + } +} + diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Marker annotation for members which are exposed for testing access. + * + * @since 2.7 + */ +@Retention(RUNTIME) +@Target({TYPE, CONSTRUCTOR, METHOD, FIELD, PARAMETER}) +@Documented +public @interface TestAccessible +{ + // empty +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +package jdk.internal.jline.internal; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * URL helpers. + * + * @author Jason Dillon + * @author Guillaume Nodet + * @since 2.7 + */ +public class Urls +{ + public static URL create(final String input) { + if (input == null) { + return null; + } + try { + return new URL(input); + } + catch (MalformedURLException e) { + return create(new File(input)); + } + } + + public static URL create(final File file) { + try { + return file != null ? file.toURI().toURL() : null; + } + catch (MalformedURLException e) { + throw new IllegalStateException(e); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +/** + * Internal support. + * + * @since 2.0 + */ +package jdk.internal.jline.internal; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2002-2012, the original author or authors. + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * http://www.opensource.org/licenses/bsd-license.php + */ +/** + * JLine 2. + * + * @since 2.0 + */ +package jdk.internal.jline; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,127 @@ +/* + * 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. 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. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jdk_internal_jline_WindowsTerminal.h" + +#include +#include +#include + +static jclass recordClass; +static jmethodID recordConstructor; + +JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_initIDs + (JNIEnv *env, jclass) { + jclass cls = env->FindClass("jdk/internal/jline/WindowsTerminal$KEY_EVENT_RECORD"); + CHECK_NULL(cls); + recordClass = (jclass) env->NewGlobalRef(cls); + CHECK_NULL(recordClass); + recordConstructor = env->GetMethodID(cls, "", "(ZCIII)V"); + CHECK_NULL(recordConstructor); +} + +JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleMode + (JNIEnv *, jobject) { + HANDLE hStdIn; + if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return -1; + } + DWORD fdwMode; + if (! GetConsoleMode(hStdIn, &fdwMode)) { + return -1; + } + return fdwMode; +} + +JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_setConsoleMode + (JNIEnv *, jobject, jint mode) { + HANDLE hStdIn; + if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return ; + } + DWORD fdwMode = mode; + SetConsoleMode(hStdIn, fdwMode); +} + +JNIEXPORT jobject JNICALL Java_jdk_internal_jline_WindowsTerminal_readKeyEvent + (JNIEnv *env, jobject) { + HANDLE hStdIn; + if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return NULL; + } + INPUT_RECORD record; + DWORD n; + while (TRUE) { + if (ReadConsoleInput(hStdIn, &record, 1, &n) == 0) { + return NULL; + } + if (record.EventType == KEY_EVENT) { + jclass clazz = env->FindClass("jdk/internal/jline/WindowsTerminal$KEY_EVENT_RECORD"); + jmethodID constr = env->GetMethodID(clazz, "", "(ZCIII)V"); + return env->NewObject(recordClass, + recordConstructor, + record.Event.KeyEvent.bKeyDown, + record.Event.KeyEvent.uChar.UnicodeChar, + record.Event.KeyEvent.dwControlKeyState, + record.Event.KeyEvent.wVirtualKeyCode, + record.Event.KeyEvent.wRepeatCount); + } + continue; + } +} + +JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleOutputCodepage + (JNIEnv *, jobject) { + return GetConsoleCP(); +} + +JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth + (JNIEnv *, jobject) { + HANDLE hStdIn; + if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return -1; + } + CONSOLE_SCREEN_BUFFER_INFO info; + if (! GetConsoleScreenBufferInfo(hStdIn, &info)) { + return -1; + } + return info.dwSize.X; +} + +JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalHeight + (JNIEnv *, jobject) { + HANDLE hStdIn; + if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return -1; + } + CONSOLE_SCREEN_BUFFER_INFO info; + if (! GetConsoleScreenBufferInfo(hStdIn, &info)) { + return -1; + } + return info.dwSize.Y; +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Crypt.java --- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Crypt.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Crypt.java Wed Jul 05 20:41:30 2017 +0200 @@ -377,7 +377,7 @@ * */ - public static void main(String arg[]) { + public static void main(String[] arg) { if (arg.length!=2) { System.err.println("usage: Crypt password salt"); @@ -386,7 +386,7 @@ Crypt c = new Crypt(); try { - byte result[] = c.crypt + byte[] result = c.crypt (arg[0].getBytes("ISO-8859-1"), arg[1].getBytes("ISO-8859-1")); for (int i=0; i 0) { - String groupSIDs[] = ntSystem.getGroupIDs(); + String[] groupSIDs = ntSystem.getGroupIDs(); groups = new NTSidGroupPrincipal[groupSIDs.length]; for (int i = 0; i < groupSIDs.length; i++) { groups[i] = new NTSidGroupPrincipal(groupSIDs[i]); diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTSystem.java --- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTSystem.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTSystem.java Wed Jul 05 20:41:30 2017 +0200 @@ -40,7 +40,7 @@ private String domain; private String domainSID; private String userSID; - private String groupIDs[]; + private String[] groupIDs; private String primaryGroupID; private long impersonationToken; diff -r b050dcca193f -r 9b3a9d72f07b jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java --- a/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java Wed Jul 05 20:41:30 2017 +0200 @@ -38,10 +38,10 @@ * @author Rosanna Lee */ public final class FactoryImpl implements SaslClientFactory, SaslServerFactory { - private static final String myMechs[] = { + private static final String[] myMechs = { "GSSAPI"}; - private static final int mechPolicies[] = { + private static final int[] mechPolicies = { PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE }; diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/TEST.groups --- a/jdk/test/TEST.groups Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/TEST.groups Wed Jul 05 20:41:30 2017 +0200 @@ -243,6 +243,7 @@ javax/xml \ -javax/xml/crypto \ jdk/asm \ + jdk/internal/jline \ com/sun/jndi \ com/sun/corba \ lib/testlibrary \ diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/lang/ProcessHandle/InfoTest.java --- a/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -32,24 +32,24 @@ import java.nio.file.attribute.UserPrincipal; import java.time.Duration; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Random; -import java.util.Scanner; -import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; import jdk.testlibrary.Platform; +import jdk.testlibrary.Utils; + import org.testng.Assert; import org.testng.annotations.Test; import org.testng.TestNG; /* * @test + * @build jdk.testlibrary.* * @library /lib/testlibrary * @summary Functions of ProcessHandle.Info * @author Roger Riggs @@ -91,16 +91,16 @@ "test runner is included."); ProcessHandle self = ProcessHandle.current(); - Duration somecpu = Duration.ofMillis(200L); - Instant end = Instant.now().plus(somecpu); + Duration someCPU = Duration.ofMillis(200L); + Instant end = Instant.now().plus(someCPU); while (Instant.now().isBefore(end)) { // waste the cpu } ProcessHandle.Info info = self.info(); System.out.printf(" info: %s%n", info); Optional totalCpu = info.totalCpuDuration(); - if (totalCpu.isPresent() && (totalCpu.get().compareTo(somecpu) < 0)) { - Assert.fail("reported cputime less than expected: " + somecpu + ", " + + if (totalCpu.isPresent() && (totalCpu.get().compareTo(someCPU) < 0)) { + Assert.fail("reported cputime less than expected: " + someCPU + ", " + "actual: " + info.totalCpuDuration()); } } @@ -111,17 +111,16 @@ @Test public static void test2() { try { - long cpulooptime = 1 << 8; + long cpuLoopTime = 100; // 100 ms String[] extraArgs = {"pid", "parent", "stdin"}; - Instant beforeStart = Instant.now().truncatedTo(ChronoUnit.SECONDS); JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs); Instant afterStart = Instant.now(); try (BufferedReader lines = p1.outputReader()) { Duration lastCpu = Duration.ofMillis(0L); - for (int j = 0; j < 20; j++) { + for (int j = 0; j < 10; j++) { - p1.sendAction("cpuloop", cpulooptime); + p1.sendAction("cpuloop", cpuLoopTime); p1.sendAction("cputime", ""); // Read cputime from child @@ -187,17 +186,21 @@ if (info.totalCpuDuration().isPresent()) { Duration totalCPU = info.totalCpuDuration().get(); Duration epsilon = Duration.ofMillis(200L); - Assert.assertTrue(totalCPU.toNanos() > 0L, - "total cpu time expected > 0ms, actual: " + totalCPU); - Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + 10_000_000_000L, - "total cpu time expected < 10s more than previous iteration, actual: " + totalCPU); if (childCpuTime != null) { System.out.printf(" info.totalCPU: %s, childCpuTime: %s, diff: %s%n", - totalCPU.toNanos(), childCpuTime.toNanos(), childCpuTime.toNanos() - totalCPU.toNanos()); + totalCPU.toNanos(), childCpuTime.toNanos(), + childCpuTime.toNanos() - totalCPU.toNanos()); Assert.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon), childCpuTime + " should be within " + epsilon + " of " + totalCPU); } + Assert.assertTrue(totalCPU.toNanos() > 0L, + "total cpu time expected > 0ms, actual: " + totalCPU); + long t = Utils.adjustTimeout(10L); // Adjusted timeout seconds + Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L, + "total cpu time expected < " + t + + " seconds more than previous iteration, actual: " + + (totalCPU.toNanos() - lastCpu.toNanos())); lastCpu = totalCPU; } @@ -209,7 +212,7 @@ } } } - p1.waitFor(5, TimeUnit.SECONDS); + p1.waitFor(Utils.adjustTimeout(5), TimeUnit.SECONDS); } catch (IOException | InterruptedException ie) { ie.printStackTrace(System.out); Assert.fail("unexpected exception", ie); @@ -252,7 +255,7 @@ Assert.assertTrue(p.waitFor(15, TimeUnit.SECONDS)); } } catch (IOException | InterruptedException ex) { - ex.printStackTrace(System.out);; + ex.printStackTrace(System.out); } finally { // Destroy any children that still exist ProcessUtil.destroyProcessTree(ProcessHandle.current()); @@ -274,7 +277,7 @@ if (dur1.isPresent() && dur2.isPresent()) { Duration total1 = dur1.get(); - Duration total2 = dur2.get(); ; + Duration total2 = dur2.get(); System.out.printf(" total1 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n", Objects.toString(total1), myCputime1, myCputime1.minus(total1)); System.out.printf(" total2 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n", @@ -326,7 +329,7 @@ * @param d1 a Duration - presumed to be shorter * @param d2 a 2nd Duration - presumed to be greater (or within Epsilon) * @param epsilon Epsilon the amount of overlap allowed - * @return + * @return true if d2 is greater than d1 or within epsilon, false otherwise */ static boolean checkEpsilon(Duration d1, Duration d2, Duration epsilon) { if (d1.toNanos() <= d2.toNanos()) { @@ -339,7 +342,7 @@ /** * Spawn a native process with the provided arguments. * @param command the executable of native process - * @args + * @param args to start a new process * @return the Process that was started * @throws IOException thrown by ProcessBuilder.start */ diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/lang/ProcessHandle/JavaChild.java --- a/jdk/test/java/lang/ProcessHandle/JavaChild.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java Wed Jul 05 20:41:30 2017 +0200 @@ -281,12 +281,12 @@ sendResult(action, Integer.toString(millis)); break; case "cpuloop": - long times = Long.valueOf(args[nextArg++]); - Instant end = Instant.now().plusMillis(times); - while (Instant.now().isBefore(end)) { - // burn the cpu til the time is up + long cpuMillis = Long.valueOf(args[nextArg++]); + long cpuTarget = getCpuTime() + cpuMillis * 1_000_000L; + while (getCpuTime() < cpuTarget) { + // burn the cpu until the time is up } - sendResult(action, times); + sendResult(action, cpuMillis); break; case "cputime": sendResult(action, getCpuTime()); diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/lang/ProcessHandle/OnExitTest.java --- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -27,16 +27,19 @@ import java.time.Instant; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; + +import jdk.testlibrary.Utils; + import org.testng.annotations.Test; import org.testng.Assert; import org.testng.TestNG; /* * @test + * @build jdk.testlibrary.Utils * @summary Functions of Process.onExit and ProcessHandle.onExit * @author Roger Riggs */ @@ -88,6 +91,7 @@ */ @Test public static void test2() { + ProcessHandle procHandle = null; try { ConcurrentHashMap processes = new ConcurrentHashMap<>(); List children = getChildren(ProcessHandle.current()); @@ -96,7 +100,7 @@ "Expected to start with zero children; " + children); JavaChild proc = JavaChild.spawnJavaChild("stdin"); - ProcessHandle procHandle = proc.toHandle(); + procHandle = proc.toHandle(); printf(" spawned: %d%n", proc.getPid()); proc.forEachOutputLine((s) -> { @@ -114,7 +118,8 @@ // Poll until all 9 child processes exist or the timeout is reached int expected = 9; - Instant endTimeout = Instant.now().plusSeconds(10L); + long timeout = Utils.adjustTimeout(10L); + Instant endTimeout = Instant.now().plusSeconds(timeout); do { Thread.sleep(200L); printf(" subprocess count: %d, waiting for %d%n", processes.size(), expected); @@ -123,16 +128,17 @@ children = getAllChildren(procHandle); - ArrayBlockingQueue completions = new ArrayBlockingQueue<>(expected + 1); + ConcurrentHashMap> completions = + new ConcurrentHashMap<>(); Instant startTime = Instant.now(); // Create a future for each of the 9 children processes.forEach( (p, parent) -> { - p.onExit().whenComplete((ph, ex) -> { + CompletableFuture cf = p.onExit().whenComplete((ph, ex) -> { Duration elapsed = Duration.between(startTime, Instant.now()); - completions.add(ph); printf("whenComplete: pid: %s, exception: %s, thread: %s, elapsed: %s%n", ph, ex, Thread.currentThread(), elapsed); }); + completions.put(p, cf); }); // Check that each of the spawned processes is included in the children @@ -153,20 +159,23 @@ proc.destroy(); // kill off the parent proc.waitFor(); - // Wait for all the processes to be completed + // Wait for all the processes and corresponding onExit CF to be completed processes.forEach((p, parent) -> { try { p.onExit().get(); + completions.get(p).join(); } catch (InterruptedException | ExecutionException ex) { // ignore } }); - // Verify that all 9 exit handlers were called - processes.forEach((p, parent) -> - Assert.assertTrue(completions.contains(p), "Child onExit not called: " + p - + ", parent: " + parent - + ": " + p.info())); + // Verify that all 9 exit handlers were called with the correct ProcessHandle + processes.forEach((p, parent) -> { + ProcessHandle value = completions.get(p).getNow(null); + Assert.assertEquals(p, value, "onExit.get value expected: " + p + + ", actual: " + value + + ": " + p.info()); + }); // Show the status of the original children children.forEach(p -> printProcess(p, "after onExit:")); @@ -176,13 +185,12 @@ List children2 = getAllChildren(procHandle); printf(" children2: %s%n", children2.toString()); Assert.assertEquals(children2.size(), 0, "After onExit, expected no children"); - - Assert.assertEquals(remaining.size(), 0, "Unaccounted for children"); - } catch (IOException | InterruptedException ex) { Assert.fail(ex.getMessage()); } finally { - destroyProcessTree(ProcessHandle.current()); + if (procHandle != null) { + destroyProcessTree(procHandle); + } } } diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/lang/ProcessHandle/TreeTest.java --- a/jdk/test/java/lang/ProcessHandle/TreeTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -75,10 +75,12 @@ spawned.add(JavaChild.spawnJavaChild("pid", "stdin")); } - List subprocesses = getChildren(self); - subprocesses.forEach(ProcessUtil::printProcess); - count = subprocesses.size(); - Assert.assertEquals(count, MAXCHILDREN, "Wrong number of spawned children"); + // Verify spawned Process is in list of children + final List initialChildren = getChildren(self); + spawned.stream() + .map(Process::toHandle) + .filter(p -> !initialChildren.contains(p)) + .forEach(p -> Assert.fail("Spawned process missing from children: " + p)); // Send exit command to each spawned Process spawned.forEach(p -> { @@ -102,20 +104,25 @@ }); // Verify that ProcessHandle.isAlive sees each of them as not alive - for (ProcessHandle ph : subprocesses) { + for (Process p : spawned) { + ProcessHandle ph = p.toHandle(); Assert.assertFalse(ph.isAlive(), "ProcessHandle.isAlive for exited process: " + ph); } - // Verify no current children are visible - count = getChildren(self).size(); - Assert.assertEquals(count, 0, "Children destroyed, should be zero"); + // Verify spawned processes are not visible as children + final List afterChildren = getChildren(self); + spawned.stream() + .map(Process::toHandle) + .filter(p -> afterChildren.contains(p)) + .forEach(p -> Assert.fail("Spawned process missing from children: " + p)); } catch (IOException ioe) { Assert.fail("unable to spawn process", ioe); } finally { // Cleanup any left over processes - spawned.stream().map(Process::toHandle) + spawned.stream() + .map(Process::toHandle) .filter(ProcessHandle::isAlive) .forEach(ph -> printDeep(ph, "test1 cleanup: ")); destroyProcessTree(ProcessHandle.current()); @@ -127,7 +134,6 @@ */ @Test public static void test2() { - ProcessHandle p1Handle = null; try { ProcessHandle self = ProcessHandle.current(); List initialChildren = getChildren(self); @@ -138,7 +144,7 @@ } JavaChild p1 = JavaChild.spawnJavaChild("stdin"); - p1Handle = p1.toHandle(); + ProcessHandle p1Handle = p1.toHandle(); printf(" p1 pid: %d%n", p1.getPid()); int spawnNew = 3; @@ -187,9 +193,6 @@ throw new RuntimeException(t); } finally { // Cleanup any left over processes - if (p1Handle.isAlive()) { - printDeep(p1Handle, "test2 cleanup: "); - } destroyProcessTree(ProcessHandle.current()); } } @@ -205,7 +208,10 @@ JavaChild p1 = JavaChild.spawnJavaChild("stdin"); ProcessHandle p1Handle = p1.toHandle(); printf(" p1: %s%n", p1.getPid()); - long count = getChildren(self).size(); + + List subprocesses = getChildren(self); + subprocesses.forEach(ProcessUtil::printProcess); + long count = subprocesses.size(); Assert.assertEquals(count, 1, "Wrong number of spawned children"); int newChildren = 3; @@ -213,7 +219,7 @@ p1.sendAction("spawn", newChildren, "stdin"); // Wait for the new processes and save the list - List subprocesses = waitForAllChildren(p1Handle, newChildren); + subprocesses = waitForAllChildren(p1Handle, newChildren); printDeep(p1Handle, "allChildren"); Assert.assertEquals(subprocesses.size(), newChildren, "Wrong number of children"); @@ -249,6 +255,9 @@ Assert.fail("Spawn of subprocess failed", ioe); } catch (InterruptedException inte) { Assert.fail("InterruptedException", inte); + } finally { + // Cleanup any left over processes + destroyProcessTree(ProcessHandle.current()); } } @@ -299,16 +308,15 @@ } /** - * A test for scale; launch a large number (39) of subprocesses. + * A test for scale; launch a large number (14) of subprocesses. */ @Test public static void test5() { int factor = 2; - ProcessHandle p1Handle = null; Instant start = Instant.now(); try { JavaChild p1 = JavaChild.spawnJavaChild("stdin"); - p1Handle = p1.toHandle(); + ProcessHandle p1Handle = p1.toHandle(); printf("Spawning %d x %d x %d processes, pid: %d%n", factor, factor, factor, p1.getPid()); @@ -325,18 +333,14 @@ int newChildren = factor * (1 + factor * (1 + factor)); List children = ProcessUtil.waitForAllChildren(p1Handle, newChildren); - Assert.assertEquals(p1.children() - .filter(ProcessUtil::isNotWindowsConsole) - .count(), factor, "expected direct children"); - Assert.assertEquals(p1.allChildren() - .filter(ProcessUtil::isNotWindowsConsole) - .count(), - factor * factor * factor + factor * factor + factor, - "expected all children"); + Assert.assertEquals(getChildren(p1Handle).size(), + factor, "expected direct children"); + long count = getAllChildren(p1Handle).size(); + long totalChildren = factor * factor * factor + factor * factor + factor; + Assert.assertTrue(count >= totalChildren, + "expected at least " + totalChildren + ", actual: " + count); - List subprocesses = p1.allChildren() - .filter(ProcessUtil::isNotWindowsConsole) - .collect(Collectors.toList()); + List subprocesses = getAllChildren(p1Handle); printf(" allChildren: %s%n", subprocesses.stream().map(p -> p.getPid()) .collect(Collectors.toList())); @@ -347,10 +351,6 @@ Assert.fail("Unexpected Exception", ex); } finally { printf("Duration: %s%n", Duration.between(start, Instant.now())); - // Cleanup any left over processes - if (p1Handle.isAlive()) { - printDeep(p1Handle, "test5 cleanup: "); - } destroyProcessTree(ProcessHandle.current()); } } diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/net/Socks/SocksProxyVersion.java --- a/jdk/test/java/net/Socks/SocksProxyVersion.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/net/Socks/SocksProxyVersion.java Wed Jul 05 20:41:30 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6964547 5001942 + * @bug 6964547 5001942 8129444 * @run main/othervm SocksProxyVersion * @summary test socksProxyVersion system property */ @@ -32,13 +32,15 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; -import java.io.DataInputStream; import java.io.IOException; import java.net.InetAddress; +import java.net.Proxy; public class SocksProxyVersion implements Runnable { final ServerSocket ss; volatile boolean failed; + volatile boolean stopped = false; + volatile int expected; public static void main(String[] args) throws Exception { if (InetAddress.getLocalHost().isLoopbackAddress()) { @@ -48,21 +50,26 @@ new SocksProxyVersion(); } - @SuppressWarnings("try") public SocksProxyVersion() throws Exception { ss = new ServerSocket(0); + int port = ss.getLocalPort(); + Thread serverThread = new Thread(this); + serverThread.start(); try (ServerSocket socket = ss) { - runTest(); + runTest(port); + } finally { + stopped = true; + } + + serverThread.join(); + if (failed) { + throw new RuntimeException("socksProxyVersion not being set correctly"); } } - void runTest() throws Exception { - int port = ss.getLocalPort(); - Thread serverThread = new Thread(this); - serverThread.start(); - + final void runTest(int port) throws Exception { /* - * Retreving the IP Address of the machine + * Retrieving the IP Address of the machine * since "localhost" is bypassed as a non-proxy host */ String addr = InetAddress.getLocalHost().getHostAddress(); @@ -70,46 +77,54 @@ System.setProperty("socksProxyHost", addr); System.setProperty("socksProxyPort", Integer.toString(port)); + Proxy proxy = new Proxy(Proxy.Type.SOCKS, + new InetSocketAddress(addr, port)); + // SOCKS V4 System.setProperty("socksProxyVersion", Integer.toString(4)); - try (Socket s = new Socket()) { - s.connect(new InetSocketAddress(addr, port)); + this.expected = 4; + check(new Socket(), addr, port); + check(new Socket(proxy), addr, port); + + // SOCKS V5 + System.setProperty("socksProxyVersion", Integer.toString(5)); + this.expected = 5; + check(new Socket(), addr, port); + check(new Socket(proxy), addr, port); + } + + private void check(Socket socket, String addr, int port) + throws IOException + { + try (Socket s = socket) { + socket.connect(new InetSocketAddress(addr, port)); } catch (SocketException e) { // java.net.SocketException: Malformed reply from SOCKS server // This exception is OK, since the "server" does not implement // the socks protocol. It just verifies the version and closes. } - - // SOCKS V5 - System.setProperty("socksProxyVersion", Integer.toString(5)); - try (Socket s = new Socket()) { - s.connect(new InetSocketAddress(addr, port)); - } catch (SocketException e) { /* OK */ } - - serverThread.join(); - if (failed) { - throw new RuntimeException("socksProxyVersion not being set correctly"); - } } + @Override public void run() { + int count = 0; try { - try (Socket s = ss.accept()) { - int version = (s.getInputStream()).read(); - if (version != 4) { - System.out.println("Got " + version + ", expected 4"); - failed = true; + while (!stopped) { + try (Socket s = ss.accept()) { + int version = (s.getInputStream()).read(); + if (version != expected) { + System.out.printf("Iteration: %d, Got: %d, expected: %d%n", + count, version, expected); + failed = true; + } } - } - try (Socket s = ss.accept()) { - int version = (s.getInputStream()).read(); - if (version != 5) { - System.out.println("Got " + version + ", expected 5"); - failed = true; - } + count++; } } catch (IOException e) { - e.printStackTrace(); + if (!ss.isClosed()) { + e.printStackTrace(); + } + // ignore, server socket was closed } } } diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/util/Collection/MOAT.java --- a/jdk/test/java/util/Collection/MOAT.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/util/Collection/MOAT.java Wed Jul 05 20:41:30 2017 +0200 @@ -356,13 +356,7 @@ } check(c.toArray().length == c.size()); - check(c.toArray().getClass() == Object[].class - || - // !!!! - // 6260652: (coll) Arrays.asList(x).toArray().getClass() - // should be Object[].class - (c.getClass().getName().equals("java.util.Arrays$ArrayList")) - ); + check(c.toArray().getClass() == Object[].class); for (int size : new int[]{0,1,c.size(), c.size()+1}) { Integer[] a = c.toArray(new Integer[size]); check((size > c.size()) || a.length == c.size()); diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/java/util/logging/LoggingDeadlock2.java --- a/jdk/test/java/util/logging/LoggingDeadlock2.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/java/util/logging/LoggingDeadlock2.java Wed Jul 05 20:41:30 2017 +0200 @@ -57,35 +57,59 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.LogManager; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.concurrent.TimeUnit; public class LoggingDeadlock2 { + // ask child process to dumpstack after 60secs + public static final long DUMP_STACK_FREQUENCY_MS = 60000; + + // A marker that allows to validate the subprocess output. + public static final String MARKER = "$"; + public static void realMain(String arg[]) throws Throwable { try { System.out.println(javaChildArgs); ProcessBuilder pb = new ProcessBuilder(javaChildArgs); ProcessResults r = run(pb.start()); equal(r.exitValue(), 99); - equal(r.out(), ""); + + // output of subprocess should end with "$" + final String out = r.out(); + final String trailingOutput = out.indexOf(MARKER) > -1 + ? out.substring(out.indexOf(MARKER)+MARKER.length()) + : out; + equal(trailingOutput, ""); equal(r.err(), ""); + equal(out.startsWith("JavaChild started"), true); + equal(out.endsWith("$"), true); } catch (Throwable t) { unexpected(t); } } public static class JavaChild { public static void main(String args[]) throws Throwable { + System.out.println("JavaChild started"); + final CyclicBarrier startingGate = new CyclicBarrier(2); final Throwable[] thrown = new Throwable[1]; // Some random variation, to help tickle races. final Random rnd = new Random(); + final long seed = rnd.nextLong(); + rnd.setSeed(seed); + System.out.println("seed=" + seed); final boolean dojoin = rnd.nextBoolean(); final int JITTER = 1024; final int iters1 = rnd.nextInt(JITTER); final int iters2 = JITTER - iters1; final AtomicInteger counter = new AtomicInteger(0); + System.out.println("dojoin=" + dojoin); + System.out.println("iters1=" + iters1); + System.out.println("iters2=" + iters2); Thread exiter = new Thread() { public void run() { @@ -101,6 +125,12 @@ }}; exiter.start(); + System.out.println("exiter started"); + + // signal end of verbose output + System.out.print(MARKER); + System.out.flush(); + startingGate.await(); for (int i = 0; i < iters2; i++) counter.getAndIncrement(); @@ -124,6 +154,9 @@ private static final String javaExe = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; + private static final String jstackExe = + System.getProperty("java.home") + + File.separator + "bin" + File.separator + "jstack"; private static final String classpath = System.getProperty("java.class.path"); @@ -182,10 +215,15 @@ public void run() { try { Reader r = new InputStreamReader(is); - char[] buf = new char[4096]; int n; - while ((n = r.read(buf)) > 0) { - sb.append(buf,0,n); + while ((n = r.read()) > 0) { + sb.append((char)n); + + // prints everything immediately to System.out so that we can + // see the traces even in the event of a test timeout + System.out.write((char)n); + System.out.flush(); + } } catch (Throwable t) { throwable = t; @@ -196,6 +234,56 @@ } } + /** + * If the child process deadlocks, then the parent may fail in timeout. + * In that case, we won't have any interesting traces, unless we manage + * to get a thread dump from the child. + * It is unsure whether obtaining a thread dump from a deadlocked child + * will work - but maybe we could see something if the timeout is a false + * positive (the child has not deadlocked but hasn't managed to fully start + * yet, for instance). + * The idea here is to periodically try to obtain a thread dump from the + * child, every 60sec - which should be always less than the jtreg timeout. + */ + private static class TimeoutThread extends Thread { + final long ms; + final Process process; + TimeoutThread(long ms, Process p) { + super("TimeoutThread"); + setDaemon(true); + this.ms = ms; + this.process = p; + } + + @Override + public void run() { + long start = System.nanoTime(); + try { + while (true) { + sleep(ms); + System.err.println("Timeout reached: " + ms); + if (process.isAlive()) { + long pid = process.getPid(); + ProcessBuilder jstack = new ProcessBuilder(jstackExe, String.valueOf(pid)); + System.err.println("Dumping subprocess stack: " + pid); + Process p = jstack.inheritIO().start(); + p.waitFor(ms, TimeUnit.MILLISECONDS); + } else { + System.err.println("Process is not alive!"); + break; + } + } + } catch (InterruptedException ex) { + System.err.println("Interrupted: " + ex); + } catch (IOException io) { + System.err.println("Failed to get stack from subprocess"); + io.printStackTrace(); + } + } + + + } + private static ProcessResults run(Process p) { Throwable throwable = null; int exitValue = -1; @@ -208,10 +296,15 @@ new StreamAccumulator(p.getErrorStream()); try { + System.out.println("Waiting for child process to exit"); outAccumulator.start(); errAccumulator.start(); + // ask subprocess to dump stack every 60 secs. + new TimeoutThread(DUMP_STACK_FREQUENCY_MS, p).start(); + exitValue = p.waitFor(); + System.out.println("\nChild exited with status: " + exitValue); outAccumulator.join(); errAccumulator.join(); diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java --- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Wed Jul 05 20:41:30 2017 +0200 @@ -46,8 +46,8 @@ * An example to show the way to use SSLEngine in datagram connections. */ public class DTLSOverDatagram { - private static int MAX_HANDSHAKE_LOOPS = 60; - private static int MAX_APP_READ_LOOPS = 10; + private static int MAX_HANDSHAKE_LOOPS = 200; + private static int MAX_APP_READ_LOOPS = 60; /* * The following is to set up the keystores. diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/jdk/internal/jline/KeyConversionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/internal/jline/KeyConversionTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,59 @@ +/* + * 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 8080679 + * @summary Verify the conversion from key events to escape sequences works properly. + * @requires os.family == "windows" + */ + +import jdk.internal.jline.WindowsTerminal; +import jdk.internal.jline.WindowsTerminal.KEY_EVENT_RECORD; + +public class KeyConversionTest { + public static void main(String... args) throws Exception { + new KeyConversionTest().run(); + } + + void run() throws Exception { + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 37, 1), "\033[D"); //LEFT + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 37, 1), "\033[1;5D"); //Ctrl-LEFT + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 37, 1), "\033[1;3D"); //Alt-LEFT + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 46, 1), "\033[3~"); //delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 46, 1), "\033[3;5~"); //Ctrl-delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 46, 1), "\033[3;3~"); //Alt-delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 272, 46, 1), "\033[3;2~"); //Shift-delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 280, 46, 1), "\033[3;6~"); //Ctrl-Shift-delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 274, 46, 1), "\033[3;4~"); //Alt-Shift-delete + checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 282, 46, 1), "\033[3;8~"); //Ctrl-Alt-Shift-delete + } + + void checkKeyConversion(KEY_EVENT_RECORD event, String expected) { + String actual = WindowsTerminal.convertKeys(event); + + if (!expected.equals(actual)) { + throw new AssertionError("Expected: " + expected + "; actual: " + actual); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/jdk/internal/jline/console/StripAnsiTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/jdk/internal/jline/console/StripAnsiTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,56 @@ +/* + * 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 8080679 + * @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Method; +import jdk.internal.jline.console.ConsoleReader; + +public class StripAnsiTest { + public static void main(String... args) throws Exception { + new StripAnsiTest().run(); + } + + void run() throws Exception { + ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ConsoleReader reader = new ConsoleReader(in, out); + + String withAnsi = "0\033[s1\033[2J2\033[37;4m3"; + String expected = "0123"; + + Method stripAnsi = ConsoleReader.class.getDeclaredMethod("stripAnsi", String.class); + stripAnsi.setAccessible(true); + String actual = (String) stripAnsi.invoke(reader, withAnsi); + + if (!expected.equals(actual)) { + throw new IllegalStateException("Did not correctly strip escape sequences: " + actual); + } + } +} diff -r b050dcca193f -r 9b3a9d72f07b jdk/test/sun/security/krb5/auto/BadKdc1.java --- a/jdk/test/sun/security/krb5/auto/BadKdc1.java Wed Jul 05 20:40:53 2017 +0200 +++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java Wed Jul 05 20:41:30 2017 +0200 @@ -53,7 +53,7 @@ // k3 off k2 on "(122212(22){1,2}|1222323232-)", // 1 // k1 on - "(12(12){1,2}|122232-)" // empty + "(12(12){1,2}|122212|122232-)" // empty ); } } diff -r b050dcca193f -r 9b3a9d72f07b langtools/.hgtags --- a/langtools/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/langtools/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -314,3 +314,4 @@ 931ec7dd6cd9e4a92bde7b2cd26e9a9fb0ecdb56 jdk9-b69 d732d6dfa72743e3aa96375c6e33f1388dbaa5c6 jdk9-b70 dc35e315436d21eab68ef44909922fb3424917f3 jdk9-b71 +832e51533706b633d37a77282ae94d016b95e649 jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 20:40:53 2017 +0200 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 20:41:30 2017 +0200 @@ -4140,12 +4140,7 @@ public void visitAnnotatedType(JCAnnotatedType tree) { attribAnnotationTypes(tree.annotations, env); - JCExpression underlyingTypeTree = tree.getUnderlyingType(); - Type underlyingType = attribTree(underlyingTypeTree, env, - new ResultInfo(KindSelector.TYP_PCK, Type.noType)); - if (!chk.checkAnnotableType(underlyingType, tree.annotations, underlyingTypeTree.pos())) { - underlyingType = underlyingTypeTree.type = syms.errType; - } + Type underlyingType = attribType(tree.underlyingType, env); Type annotatedType = underlyingType.annotatedType(Annotations.TO_BE_SET); if (!env.info.isNewClass) @@ -4636,7 +4631,16 @@ } } else if (enclTr.hasTag(ANNOTATED_TYPE)) { JCAnnotatedType at = (JCTree.JCAnnotatedType) enclTr; - if (!chk.checkAnnotableType(enclTy, at.getAnnotations(), at.underlyingType.pos())) { + if (enclTy == null || enclTy.hasTag(NONE)) { + if (at.getAnnotations().size() == 1) { + log.error(at.underlyingType.pos(), "cant.type.annotate.scoping.1", at.getAnnotations().head.attribute); + } else { + ListBuffer comps = new ListBuffer<>(); + for (JCAnnotation an : at.getAnnotations()) { + comps.add(an.attribute); + } + log.error(at.underlyingType.pos(), "cant.type.annotate.scoping", comps.toList()); + } repeat = false; } enclTr = at.underlyingType; diff -r b050dcca193f -r 9b3a9d72f07b langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 20:40:53 2017 +0200 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 20:41:30 2017 +0200 @@ -63,8 +63,6 @@ import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.code.TypeTag.WILDCARD; -import static com.sun.tools.javac.resources.CompilerProperties.Errors.CantTypeAnnotateScoping; -import static com.sun.tools.javac.resources.CompilerProperties.Errors.CantTypeAnnotateScoping1; import static com.sun.tools.javac.tree.JCTree.Tag.*; /** Type checking helper class for the attribution phase. @@ -2694,29 +2692,6 @@ * Check annotations **************************************************************************/ - /** Verify that a component of a qualified type name being type annotated - * can indeed be legally be annotated. For example, package names and type - * names used to access static members cannot be annotated. - * - * @param typeComponent the component of the qualified name being annotated - * @param annotations the annotations - * @param pos diagnostic position - * @return true if all is swell, false otherwise. - */ - boolean checkAnnotableType(Type typeComponent, List annotations, DiagnosticPosition pos) { - if (typeComponent == null || typeComponent.hasTag(PACKAGE) || typeComponent.hasTag(NONE)) { - ListBuffer lb = new ListBuffer<>(); - for (JCAnnotation annotation : annotations) { - lb.append(annotation.annotationType.type.tsym); - } - List symbols = lb.toList(); - log.error(pos, - symbols.size() > 1 ? CantTypeAnnotateScoping(symbols) - : CantTypeAnnotateScoping1(symbols.get(0))); - return false; - } - return true; - } /** * Recursively validate annotations values */ diff -r b050dcca193f -r 9b3a9d72f07b langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java Wed Jul 05 20:40:53 2017 +0200 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java Wed Jul 05 20:41:30 2017 +0200 @@ -1,12 +1,12 @@ /* * @test /nodynamiccopyright/ - * @bug 8026564 8074346 + * @bug 8026564 * @summary The parts of a fully-qualified type can't be annotated. * @author Werner Dietl + * @ignore 8057679 clarify error messages trying to annotate scoping * @compile/fail/ref=CantAnnotatePackages.out -XDrawDiagnostics CantAnnotatePackages.java */ - import java.lang.annotation.*; import java.util.List; @@ -21,8 +21,6 @@ java. @TA lang.Object of3; List of4; - List<@CantAnnotatePackages_TB java.lang.Object> of5; // test that we do reasonable things for missing types. - // TODO: also note the order of error messages. } diff -r b050dcca193f -r 9b3a9d72f07b langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.out --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.out Wed Jul 05 20:40:53 2017 +0200 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.out Wed Jul 05 20:41:30 2017 +0200 @@ -1,7 +1,5 @@ -CantAnnotatePackages.java:20:14: compiler.err.cant.type.annotate.scoping.1: TA -CantAnnotatePackages.java:21:9: compiler.err.cant.type.annotate.scoping.1: TA -CantAnnotatePackages.java:22:14: compiler.err.cant.type.annotate.scoping.1: TA -CantAnnotatePackages.java:24:11: compiler.err.cant.resolve.location: kindname.class, CantAnnotatePackages_TB, , , (compiler.misc.location: kindname.class, CantAnnotatePackages, null) -CantAnnotatePackages.java:24:35: compiler.err.cant.type.annotate.scoping.1: CantAnnotatePackages_TB -CantAnnotatePackages.java:15:18: compiler.err.cant.type.annotate.scoping.1: @TA -6 errors +CantAnnotatePackages.java:14:13: compiler.err.cant.type.annotate.scoping.1: @TA +CantAnnotatePackages.java:19:18: compiler.err.cant.type.annotate.scoping.1: @TA +CantAnnotatePackages.java:20:19: compiler.err.cant.type.annotate.scoping.1: @TA +CantAnnotatePackages.java:21:24: compiler.err.cant.type.annotate.scoping.1: @TA +4 errors diff -r b050dcca193f -r 9b3a9d72f07b langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.java --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.java Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 8074346 - * @author sadayapalam - * @summary Test that type annotation on a qualified type doesn't cause spurious 'cannot find symbol' errors - * @compile/fail/ref=T8074346.out -XDrawDiagnostics T8074346.java -*/ - -abstract class T8074346 implements - @T8074346_TA @T8074346_TB java.util.Map<@T8074346_TA java.lang.String, java.lang.@T8074346_TA String>, - java.util.@T8074346_TA List { -} - -@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) -@interface T8074346_TA { } - -@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) -@interface T8074346_TB { } \ No newline at end of file diff -r b050dcca193f -r 9b3a9d72f07b langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.out --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.out Wed Jul 05 20:40:53 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -T8074346.java:10:35: compiler.err.cant.type.annotate.scoping: T8074346_TA,T8074346_TB -T8074346.java:10:62: compiler.err.cant.type.annotate.scoping.1: T8074346_TA -2 errors \ No newline at end of file diff -r b050dcca193f -r 9b3a9d72f07b langtools/test/tools/javac/generics/inference/8078024/T8078024.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/8078024/T8078024.java Wed Jul 05 20:41:30 2017 +0200 @@ -0,0 +1,45 @@ +/* + * 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. 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. + */ + +/** + * @test + * @bug 8078024 + * @summary before the patch for JDK-8078024 this code wasn't accepted by the compiler. After the + * mentioned patch the second method is selected as applicable and the code is accepted. + * @compile T8078024.java + */ + +import java.util.Arrays; +import java.util.List; + +class T8078024 { + public static List> cartesianProduct(List... lists) { + return cartesianProduct(Arrays.asList(lists)); + } + + public static List> cartesianProduct(List> lists) { + return null; + } +} diff -r b050dcca193f -r 9b3a9d72f07b make/CompileJavaModules.gmk --- a/make/CompileJavaModules.gmk Wed Jul 05 20:40:53 2017 +0200 +++ b/make/CompileJavaModules.gmk Wed Jul 05 20:41:30 2017 +0200 @@ -368,6 +368,10 @@ ################################################################################ +jdk.internal.le_COPY := .properties + +################################################################################ + jdk.jcmd_COPY := _options ################################################################################ diff -r b050dcca193f -r 9b3a9d72f07b make/Images.gmk --- a/make/Images.gmk Wed Jul 05 20:40:53 2017 +0200 +++ b/make/Images.gmk Wed Jul 05 20:41:30 2017 +0200 @@ -46,7 +46,7 @@ jdk.naming.dns jdk.naming.rmi jdk.scripting.nashorn jdk.zipfs # tools -TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.javadoc jdk.jcmd jdk.jconsole \ +TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.internal.le jdk.javadoc jdk.jcmd jdk.jconsole \ jdk.hotspot.agent jdk.hprof.agent jdk.jartool jdk.jdeps jdk.jdi jdk.jdwp.agent \ jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws diff -r b050dcca193f -r 9b3a9d72f07b modules.xml --- a/modules.xml Wed Jul 05 20:40:53 2017 +0200 +++ b/modules.xml Wed Jul 05 20:41:30 2017 +0200 @@ -1625,6 +1625,26 @@ + jdk.internal.le + java.base + + jdk.internal.jline + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console.completer + jdk.scripting.nashorn.shell + + + jdk.internal.jline.console.history + jdk.scripting.nashorn.shell + + + jdk.jartool java.base diff -r b050dcca193f -r 9b3a9d72f07b nashorn/.hgtags --- a/nashorn/.hgtags Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/.hgtags Wed Jul 05 20:41:30 2017 +0200 @@ -305,3 +305,4 @@ 194b74467afcab3ca0096f04570def424977215d jdk9-b69 3379235149c0e14e59e05c4ab8df450f5777b552 jdk9-b70 7066af6e7b06f3c6ebf449c88fc1064d2181237a jdk9-b71 +d017877b3b8cd39337f1bdc00d958f821433c4c3 jdk9-b72 diff -r b050dcca193f -r 9b3a9d72f07b nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Jul 05 20:41:30 2017 +0200 @@ -39,7 +39,7 @@ */ public final class MemberInfo implements Cloneable { // class loader of this class - private static ClassLoader myLoader = MemberInfo.class.getClassLoader(); + private static final ClassLoader MY_LOADER = MemberInfo.class.getClassLoader(); /** * The different kinds of available class annotations @@ -493,7 +493,7 @@ if (type.getSort() == Type.OBJECT) { try { - final Class clazz = Class.forName(type.getClassName(), false, myLoader); + final Class clazz = Class.forName(type.getClassName(), false, MY_LOADER); return ScriptObject.class.isAssignableFrom(clazz); } catch (final ClassNotFoundException cnfe) { return false; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java Wed Jul 05 20:41:30 2017 +0200 @@ -156,14 +156,14 @@ return null; } - private static MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get", + private static final MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get", MethodType.methodType(Object.class, int.class)); - private static MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get", + private static final MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get", MethodType.methodType(Object.class, Object.class)); - private static MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class); - private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); + private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class); + private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); private enum CollectionType { ARRAY, LIST, MAP @@ -287,7 +287,7 @@ if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinites trigger IOOBE return null; // not an exact integer } - return Integer.valueOf(intIndex); + return intIndex; } catch(Exception|Error e) { throw e; } catch(final Throwable t) { @@ -343,9 +343,9 @@ } } - private static MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class); - private static MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class); - private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey", + private static final MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class); + private static final MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class); + private static final MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey", MethodType.methodType(boolean.class, Object.class)); private static MethodHandle findRangeCheck(final Class collectionType) { @@ -353,7 +353,7 @@ } @SuppressWarnings("unused") - private static final boolean rangeCheck(final Object array, final Object index) { + private static boolean rangeCheck(final Object array, final Object index) { if(!(index instanceof Number)) { return false; } @@ -370,7 +370,7 @@ } @SuppressWarnings("unused") - private static final boolean rangeCheck(final List list, final Object index) { + private static boolean rangeCheck(final List list, final Object index) { if(!(index instanceof Number)) { return false; } @@ -386,10 +386,10 @@ throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size()); } - private static MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set", + private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set", MethodType.methodType(Object.class, int.class, Object.class)); - private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", + private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", MethodType.methodType(Object.class, Object.class, Object.class)); private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, @@ -471,16 +471,16 @@ gic.getValidatorClass(), gic.getValidationType()); } - private static MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength", + private static final MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength", MethodType.methodType(int.class, Object.class)); - private static MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size", + private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size", MethodType.methodType(int.class)); - private static MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size", + private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size", MethodType.methodType(int.class)); - private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class); + private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class); private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) { assertParameterCount(callSiteDescriptor, 1); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java Wed Jul 05 20:41:30 2017 +0200 @@ -164,7 +164,7 @@ } } if(b == null) { - return name.toString(); + return name; } assert lastEscape != -1; b.append(name, lastEscape + 1, l); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java Wed Jul 05 20:41:30 2017 +0200 @@ -166,7 +166,7 @@ } }; - private static final ClassLoader getClassLoader(final Class clazz) { + private static ClassLoader getClassLoader(final Class clazz) { return AccessController.doPrivileged(new PrivilegedAction() { @Override public ClassLoader run() { @@ -298,7 +298,7 @@ * @return true if there can be a conversion, false if there can not. */ public boolean canConvert(final Class from, final Class to) { - return canAutoConvert(from, to) || canConvert.get(from).get(to).booleanValue(); + return canAutoConvert(from, to) || canConvert.get(from).get(to); } /** diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/Formatter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/Formatter.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/Formatter.java Wed Jul 05 20:41:30 2017 +0200 @@ -170,7 +170,7 @@ * @return true if '<' is in the string, else false */ private static boolean isPreviousArgument(final String s) { - return (s != null && s.indexOf('<') >= 0) ? true : false; + return (s != null && s.indexOf('<') >= 0); } // %[argument_index$][flags][width][.precision][t]conversion diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java Wed Jul 05 20:41:30 2017 +0200 @@ -705,7 +705,7 @@ /** private access */ PRIVATE(ACC_PRIVATE); - private int value; + private final int value; private Flag(final int value) { this.value = value; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jul 05 20:41:30 2017 +0200 @@ -213,7 +213,7 @@ private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS); private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type()); - private static final Integer INT_ZERO = Integer.valueOf(0); + private static final Integer INT_ZERO = 0; /** Constant data & installation. The only reason the compiler keeps this is because it is assigned * by reflection in class installation */ @@ -742,7 +742,7 @@ method.convert(Type.NUMBER); } - private static final Type undefinedToNumber(final Type type) { + private static Type undefinedToNumber(final Type type) { return type == Type.UNDEFINED ? Type.NUMBER : type; } @@ -4877,7 +4877,7 @@ if(propertyValue instanceof String || propertyValue == null) { method.load((String)propertyValue); } else if(propertyValue instanceof Integer) { - method.load(((Integer)propertyValue).intValue()); + method.load(((Integer)propertyValue)); method.convert(Type.OBJECT); } else { throw new AssertionError(); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Wed Jul 05 20:41:30 2017 +0200 @@ -56,7 +56,7 @@ private transient Class clazz; - private transient Map functions = new IdentityHashMap<>(); + private final transient Map functions = new IdentityHashMap<>(); private transient boolean isUsed; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java Wed Jul 05 20:41:30 2017 +0200 @@ -437,7 +437,7 @@ baseName = baseName.replace('.', '_').replace('-', '_'); if (!env._loader_per_compile) { - baseName = baseName + installer.getUniqueScriptId(); + baseName += installer.getUniqueScriptId(); } // ASM's bytecode verifier does not allow JVM allowed safe escapes using '\' as escape char. diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ConstantData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ConstantData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ConstantData.java Wed Jul 05 20:41:30 2017 +0200 @@ -162,7 +162,7 @@ final Integer value = stringMap.get(string); if (value != null) { - return value.intValue(); + return value; } constants.add(string); @@ -191,7 +191,7 @@ final Integer value = objectMap.get(entry); if (value != null) { - return value.intValue(); + return value; } constants.add(object); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/DumpBytecode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/DumpBytecode.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/DumpBytecode.java Wed Jul 05 20:41:30 2017 +0200 @@ -51,7 +51,7 @@ if (env._print_code) { final StringBuilder sb = new StringBuilder(); - sb.append("class: " + className). + sb.append("class: ").append(className). append('\n'). append(ClassEmitter.disassemble(bytecode)). append("====="); @@ -88,7 +88,7 @@ } - // should code be dumped to disk - only valid in compile_only mode? + // should code be dumped to disk if (env._dest_dir != null) { final String fileName = className.replace('.', File.separatorChar) + ".class"; final int index = fileName.lastIndexOf(File.separatorChar); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Jul 05 20:41:30 2017 +0200 @@ -121,11 +121,9 @@ private static boolean definedInBlock(final Block block, final Symbol symbol) { if (symbol.isGlobal()) { - if (block.isGlobalScope()) { - return true; - } //globals cannot be defined anywhere else - return false; + + return block.isGlobalScope(); } return block.getExistingSymbol(symbol.getName()) == symbol; } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Jul 05 20:41:30 2017 +0200 @@ -272,12 +272,12 @@ } private static class SymbolConversions { - private static byte I2L = 1 << 0; - private static byte I2D = 1 << 1; - private static byte I2O = 1 << 2; - private static byte L2D = 1 << 3; - private static byte L2O = 1 << 4; - private static byte D2O = 1 << 5; + private static final byte I2L = 1 << 0; + private static final byte I2D = 1 << 1; + private static final byte I2O = 1 << 2; + private static final byte L2D = 1 << 3; + private static final byte L2O = 1 << 4; + private static final byte D2O = 1 << 5; private byte conversions; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Wed Jul 05 20:41:30 2017 +0200 @@ -101,7 +101,7 @@ // Conservative pattern to test if element names consist of characters valid for identifiers. // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit. - private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*"); + private static final Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*"); /** * Constructor. diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Jul 05 20:41:30 2017 +0200 @@ -69,7 +69,6 @@ import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.logging.Loggable; import jdk.nashorn.internal.runtime.logging.Logger; -import jdk.nashorn.internal.runtime.options.Options; /** * Generates the ScriptObject subclass structure with fields for a user objects. diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java Wed Jul 05 20:41:30 2017 +0200 @@ -89,7 +89,7 @@ public Type ldc(final MethodVisitor method, final Object c) { assert c instanceof Integer; - final int value = ((Integer) c).intValue(); + final int value = ((Integer) c); switch (value) { case -1: diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornClassReader.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornClassReader.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornClassReader.java Wed Jul 05 20:41:30 2017 +0200 @@ -88,7 +88,7 @@ c = bytecode[i++]; switch (st) { case 0: - c = c & 0xFF; + c &= 0xFF; if (c < 0x80) { // 0xxxxxxx buf[strLen++] = (char) c; } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx @@ -457,7 +457,7 @@ @SuppressWarnings("unused") final String getType() { - String str = type[tag]; + String str = TYPE[tag]; while (str.length() < 16) { str += " "; } @@ -507,7 +507,7 @@ } } - private static String type[] = { + private static final String[] TYPE = { //0 "", //1 diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jul 05 20:41:30 2017 +0200 @@ -535,7 +535,7 @@ addText(sb); } - private static final boolean noFallThru(final int opcode) { + private static boolean noFallThru(final int opcode) { switch (opcode) { case Opcodes.GOTO: case Opcodes.ATHROW: @@ -901,7 +901,7 @@ appendDescriptor(sb, INTERNAL_NAME, desc); } } else if (o[i] instanceof Integer) { - switch (((Integer)o[i]).intValue()) { + switch (((Integer)o[i])) { case 0: appendDescriptor(sb, FIELD_DESCRIPTOR, "T"); break; @@ -1090,7 +1090,7 @@ public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append("digraph " + dottyFriendly(name) + " {"); + sb.append("digraph ").append(dottyFriendly(name)).append(" {"); sb.append("\n"); sb.append("\tgraph [fontname=courier]\n"); sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n"); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java Wed Jul 05 20:41:30 2017 +0200 @@ -450,7 +450,7 @@ for (final Object mp : memoryPoolMXBeans) { final Object usage = getUsage.invoke(mp); final Object max = getMax.invoke(usage); - maxMemory += ((Long)max).longValue(); + maxMemory += ((Long)max); } } catch (IllegalAccessException | IllegalArgumentException | diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jul 05 20:41:30 2017 +0200 @@ -88,14 +88,14 @@ */ @ScriptClass("Global") public final class Global extends Scope { - // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__) - private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object(); + // This special value is used to flag a lazily initialized global property. + // This also serves as placeholder value used in place of a location property + // (__FILE__, __DIR__, __LINE__) + private static final Object LAZY_SENTINEL = new Object(); + private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class); - // placeholder value for lazily initialized global objects - private static final Object LAZY_SENTINEL = new Object(); - /** * Optimistic builtin names that require switchpoint invalidation * upon assignment. Overly conservative, but works for now, to avoid @@ -182,15 +182,15 @@ /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final double NaN = Double.NaN; + public static final double NaN = Double.NaN; /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final double Infinity = Double.POSITIVE_INFINITY; + public static final double Infinity = Double.POSITIVE_INFINITY; /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final Object undefined = UNDEFINED; + public static final Object undefined = UNDEFINED; /** ECMA 15.1.2.1 eval(x) */ @Property(attributes = Attribute.NOT_ENUMERABLE) @@ -830,15 +830,15 @@ /** Nashorn extension: current script's file name */ @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER; + public static final Object __FILE__ = LAZY_SENTINEL; /** Nashorn extension: current script's directory */ @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER; + public static final Object __DIR__ = LAZY_SENTINEL; /** Nashorn extension: current source line number being executed */ @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER; + public static final Object __LINE__ = LAZY_SENTINEL; private volatile NativeDate DEFAULT_DATE; @@ -1768,38 +1768,10 @@ return ScriptFunction.getPrototype(getBuiltinFloat64Array()); } - private ScriptFunction getBuiltinArray() { - return builtinArray; - } - ScriptFunction getTypeErrorThrower() { return typeErrorThrower; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin array has not been overridden - */ - public static boolean isBuiltinArray() { - final Global instance = Global.instance(); - return instance.array == instance.getBuiltinArray(); - } - - private ScriptFunction getBuiltinBoolean() { - return builtinBoolean; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin boolean has not been overridden - */ - public static boolean isBuiltinBoolean() { - final Global instance = Global.instance(); - return instance._boolean == instance.getBuiltinBoolean(); - } - private synchronized ScriptFunction getBuiltinDate() { if (this.builtinDate == null) { this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class); @@ -1810,30 +1782,6 @@ return this.builtinDate; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin date has not been overridden - */ - public static boolean isBuiltinDate() { - final Global instance = Global.instance(); - return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate(); - } - - private ScriptFunction getBuiltinError() { - return builtinError; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin error has not been overridden - */ - public static boolean isBuiltinError() { - final Global instance = Global.instance(); - return instance.error == instance.getBuiltinError(); - } - private synchronized ScriptFunction getBuiltinEvalError() { if (this.builtinEvalError == null) { this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype()); @@ -1841,31 +1789,11 @@ return this.builtinEvalError; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin eval error has not been overridden - */ - public static boolean isBuiltinEvalError() { - final Global instance = Global.instance(); - return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError(); - } - private ScriptFunction getBuiltinFunction() { return builtinFunction; } /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin function has not been overridden - */ - public static boolean isBuiltinFunction() { - final Global instance = Global.instance(); - return instance.function == instance.getBuiltinFunction(); - } - - /** * Get the switchpoint used to check property changes for Function.prototype.apply * @return the switchpoint guarding apply (same as guarding call, and everything else in function) */ @@ -1906,16 +1834,6 @@ return builtinJSAdapter; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin JSAdapter has not been overridden - */ - public static boolean isBuiltinJSAdapter() { - final Global instance = Global.instance(); - return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter(); - } - private synchronized ScriptObject getBuiltinJSON() { if (this.builtinJSON == null) { this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class); @@ -1923,44 +1841,6 @@ return this.builtinJSON; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin JSON has has not been overridden - */ - public static boolean isBuiltinJSON() { - final Global instance = Global.instance(); - return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON(); - } - - private ScriptObject getBuiltinJava() { - return builtinJava; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin Java has not been overridden - */ - public static boolean isBuiltinJava() { - final Global instance = Global.instance(); - return instance.java == instance.getBuiltinJava(); - } - - private ScriptObject getBuiltinJavax() { - return builtinJavax; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin Javax has not been overridden - */ - public static boolean isBuiltinJavax() { - final Global instance = Global.instance(); - return instance.javax == instance.getBuiltinJavax(); - } - private synchronized ScriptFunction getBuiltinJavaImporter() { if (this.builtinJavaImporter == null) { this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); @@ -1975,68 +1855,6 @@ return this.builtinJavaApi; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin Java importer has not been overridden - */ - public static boolean isBuiltinJavaImporter() { - final Global instance = Global.instance(); - return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter(); - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin math has not been overridden - */ - public static boolean isBuiltinMath() { - final Global instance = Global.instance(); - return instance.math == instance.builtinMath; - } - - private ScriptFunction getBuiltinNumber() { - return builtinNumber; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin number has not been overridden - */ - public static boolean isBuiltinNumber() { - final Global instance = Global.instance(); - return instance.number == instance.getBuiltinNumber(); - } - - private ScriptFunction getBuiltinObject() { - return builtinObject; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin object has not been overridden - */ - public static boolean isBuiltinObject() { - final Global instance = Global.instance(); - return instance.object == instance.getBuiltinObject(); - } - - private ScriptObject getBuiltinPackages() { - return builtinPackages; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin package has not been overridden - */ - public static boolean isBuiltinPackages() { - final Global instance = Global.instance(); - return instance.packages == instance.getBuiltinPackages(); - } - private synchronized ScriptFunction getBuiltinRangeError() { if (this.builtinRangeError == null) { this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype()); @@ -2044,30 +1862,6 @@ return builtinRangeError; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin range error has not been overridden - */ - public static boolean isBuiltinRangeError() { - final Global instance = Global.instance(); - return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError(); - } - - private synchronized ScriptFunction getBuiltinReferenceError() { - return builtinReferenceError; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin reference error has not been overridden - */ - public static boolean isBuiltinReferenceError() { - final Global instance = Global.instance(); - return instance.referenceError == instance.getBuiltinReferenceError(); - } - private synchronized ScriptFunction getBuiltinRegExp() { if (this.builtinRegExp == null) { this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class); @@ -2081,58 +1875,6 @@ return builtinRegExp; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin regexp has not been overridden - */ - public static boolean isBuiltinRegExp() { - final Global instance = Global.instance(); - return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp(); - } - - private ScriptFunction getBuiltinString() { - return builtinString; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin Java has not been overridden - */ - public static boolean isBuiltinString() { - final Global instance = Global.instance(); - return instance.string == instance.getBuiltinString(); - } - - private ScriptFunction getBuiltinSyntaxError() { - return builtinSyntaxError; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin syntax error has not been overridden - */ - public static boolean isBuiltinSyntaxError() { - final Global instance = Global.instance(); - return instance.syntaxError == instance.getBuiltinSyntaxError(); - } - - private ScriptFunction getBuiltinTypeError() { - return builtinTypeError; - } - - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin type error has not been overridden - */ - public static boolean isBuiltinTypeError() { - final Global instance = Global.instance(); - return instance.typeError == instance.getBuiltinTypeError(); - } - private synchronized ScriptFunction getBuiltinURIError() { if (this.builtinURIError == null) { this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype()); @@ -2140,16 +1882,6 @@ return this.builtinURIError; } - /** - * Called from compiled script code to test if builtin has been overridden - * - * @return true if builtin URI error has not been overridden - */ - public static boolean isBuiltinURIError() { - final Global instance = Global.instance(); - return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError(); - } - @Override public String getClassName() { return "global"; @@ -2288,7 +2020,7 @@ * @return true if the value is a placeholder, false otherwise. */ public static boolean isLocationPropertyPlaceholder(final Object placeholder) { - return placeholder == LOCATION_PROPERTY_PLACEHOLDER; + return placeholder == LAZY_SENTINEL; } /** diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Jul 05 20:41:30 2017 +0200 @@ -1874,7 +1874,7 @@ //TODO - fold these into the Link logics, but I'll do that as a later step, as I want to do a checkin //where everything works first - private static final ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class clazz) { + private static ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class clazz) { try { @SuppressWarnings("unchecked") final ContinuousArrayData data = (ContinuousArrayData)(T)((NativeArray)self).getArray(); @@ -1887,7 +1887,7 @@ throw new ClassCastException(); } - private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self) { + private static ContinuousArrayData getContinuousArrayDataCCE(final Object self) { try { return (ContinuousArrayData)((NativeArray)self).getArray(); } catch (final NullPointerException e) { @@ -1895,7 +1895,7 @@ } } - private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class elementType) { + private static ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class elementType) { try { return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType" } catch (final NullPointerException e) { diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java Wed Jul 05 20:41:30 2017 +0200 @@ -218,7 +218,7 @@ @Override public String toString() { - return isValidDate() ? toString(this).toString() : INVALID_DATE; + return isValidDate() ? toString(this) : INVALID_DATE; } /** diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java Wed Jul 05 20:41:30 2017 +0200 @@ -803,7 +803,7 @@ private static final Object REPLACE_VALUE = new Object(); - private static final MethodHandle getReplaceValueInvoker() { + private static MethodHandle getReplaceValueInvoker() { return Global.instance().getDynamicInvoker(REPLACE_VALUE, new Callable() { @Override diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Jul 05 20:41:30 2017 +0200 @@ -1044,9 +1044,9 @@ try { final long value = Long.parseLong(valueString, radix); if(value >= MIN_INT_L && value <= MAX_INT_L) { - return Integer.valueOf((int)value); + return (int)value; } - return Long.valueOf(value); + return value; } catch (final NumberFormatException e) { if (radix == 10) { return Double.valueOf(valueString); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jul 05 20:41:30 2017 +0200 @@ -907,7 +907,7 @@ OptimismInfo(final RecompilableScriptFunctionData data, final Map invalidatedProgramPoints) { this.data = data; this.log = data.getLogger(); - this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap() : invalidatedProgramPoints; + this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap<>() : invalidatedProgramPoints; newOptimisticAssumptions(); } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Jul 05 20:41:30 2017 +0200 @@ -994,7 +994,7 @@ * @return a long */ public static long toLong(final Object obj) { - return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj)); + return obj instanceof Long ? ((Long)obj) : toLong(toNumber(obj)); } /** @@ -1056,7 +1056,7 @@ */ public static int toInt32Optimistic(final Object obj, final int programPoint) { if (obj != null && obj.getClass() == Integer.class) { - return ((Integer)obj).intValue(); + return ((Integer)obj); } throw new UnwarrantedOptimismException(obj, programPoint); } @@ -1954,11 +1954,11 @@ public static MethodHandle unboxConstant(final Object o) { if (o != null) { if (o.getClass() == Integer.class) { - return MH.constant(int.class, ((Integer)o).intValue()); + return MH.constant(int.class, ((Integer)o)); } else if (o.getClass() == Long.class) { - return MH.constant(long.class, ((Long)o).longValue()); + return MH.constant(long.class, ((Long)o)); } else if (o.getClass() == Double.class) { - return MH.constant(double.class, ((Double)o).doubleValue()); + return MH.constant(double.class, ((Double)o)); } } return MH.constant(Object.class, o); @@ -1983,7 +1983,7 @@ } } - private static final List toUnmodifiableList(final MethodHandle... methodHandles) { + private static List toUnmodifiableList(final MethodHandle... methodHandles) { return Collections.unmodifiableList(Arrays.asList(methodHandles)); } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java Wed Jul 05 20:41:30 2017 +0200 @@ -156,7 +156,7 @@ } // If the file does not exist, then assume that it's a directory if (!file.isFile()) { - name = name + "/"; + name += "/"; } try { return new URL("file", "", name); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Jul 05 20:41:30 2017 +0200 @@ -260,7 +260,7 @@ final Class c = arg.getClass(); if (c == Long.class) { // Must check for Long separately, as Long.doubleValue() isn't precise. - return ((Long)arg).longValue(); + return ((Long)arg); } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class || c == Byte.class) { return ensureLong(((Number)arg).doubleValue(), programPoint); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Wed Jul 05 20:41:30 2017 +0200 @@ -562,8 +562,8 @@ @Override public int hashCode() { - final Class type = getLocalType(); - return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode()); + final Class t = getLocalType(); + return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (t == null ? 0 : t.hashCode()); } @Override @@ -588,7 +588,7 @@ getKey().equals(otherProperty.getKey()); } - private static final String type(final Class type) { + private static String type(final Class type) { if (type == null) { return "undef"; } else if (type == int.class) { @@ -608,8 +608,8 @@ */ public final String toStringShort() { final StringBuilder sb = new StringBuilder(); - final Class type = getLocalType(); - sb.append(getKey()).append(" (").append(type(type)).append(')'); + final Class t = getLocalType(); + sb.append(getKey()).append(" (").append(type(t)).append(')'); return sb.toString(); } @@ -625,7 +625,7 @@ @Override public String toString() { final StringBuilder sb = new StringBuilder(); - final Class type = getLocalType(); + final Class t = getLocalType(); sb.append(indent(getKey(), 20)). append(" id="). @@ -635,7 +635,7 @@ append(") "). append(getClass().getSimpleName()). append(" {"). - append(indent(type(type), 5)). + append(indent(type(t), 5)). append('}'); if (slot != -1) { diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jul 05 20:41:30 2017 +0200 @@ -999,10 +999,10 @@ for (final Property p : map0.getProperties()) { final Property p2 = map1.findProperty(p.getKey()); if (p2 == null) { - sb.append("FIRST ONLY : [" + p + "]"); + sb.append("FIRST ONLY : [").append(p).append("]"); found = true; } else if (p2 != p) { - sb.append("DIFFERENT : [" + p + "] != [" + p2 + "]"); + sb.append("DIFFERENT : [").append(p).append("] != [").append(p2).append("]"); found = true; } } @@ -1010,7 +1010,7 @@ for (final Property p2 : map1.getProperties()) { final Property p1 = map0.findProperty(p2.getKey()); if (p1 == null) { - sb.append("SECOND ONLY: [" + p2 + "]"); + sb.append("SECOND ONLY: [").append(p2).append("]"); found = true; } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java Wed Jul 05 20:41:30 2017 +0200 @@ -359,9 +359,9 @@ if (returnValue instanceof String) { str = '\'' + str + '\''; } else if (returnValue instanceof Double) { - str = str + 'd'; + str += 'd'; } else if (returnValue instanceof Long) { - str = str + 'l'; + str += 'l'; } return str; } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 20:41:30 2017 +0200 @@ -611,7 +611,7 @@ obj = ((ScriptObject)obj).get(property); if(Global.isLocationPropertyPlaceholder(obj)) { if(CompilerConstants.__LINE__.name().equals(property)) { - obj = Integer.valueOf(0); + obj = 0; } else { obj = ""; } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java Wed Jul 05 20:41:30 2017 +0200 @@ -995,7 +995,7 @@ return initLogger(Context.getContextTrusted()); } - private File dumpFile(final String dir) { + private File dumpFile(final File dirFile) { final URL u = getURL(); final StringBuilder buf = new StringBuilder(); // make it unique by prefixing current date & time @@ -1010,11 +1010,17 @@ buf.append(getName()); } - return new File(dir, buf.toString()); + return new File(dirFile, buf.toString()); } void dump(final String dir) { - final File file = dumpFile(dir); + final File dirFile = new File(dir); + final File file = dumpFile(dirFile); + if (!dirFile.exists() && !dirFile.mkdirs()) { + debug("Skipping source dump for " + name); + return; + } + try (final FileOutputStream fos = new FileOutputStream(file)) { final PrintWriter pw = new PrintWriter(fos); pw.print(data.toString()); @@ -1025,7 +1031,7 @@ ": " + ECMAErrors.getMessage( "io.error.cant.write", - dir.toString() + + dir + " : " + ioExp.toString())); } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Jul 05 20:41:30 2017 +0200 @@ -215,11 +215,8 @@ int.class); @SuppressWarnings("unused") - private static final boolean guard(final Class clazz, final ScriptObject sobj) { - if (sobj != null && sobj.getArray().getClass() == clazz) { - return true; - } - return false; + private static boolean guard(final Class clazz, final ScriptObject sobj) { + return sobj != null && sobj.getArray().getClass() == clazz; } /** diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Jul 05 20:41:30 2017 +0200 @@ -138,7 +138,7 @@ final Object[] oarray = new Object[trim ? len : array.length]; for (int index = 0; index < len; index++) { - oarray[index] = Integer.valueOf(array[index]); + oarray[index] = array[index]; } return oarray; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Jul 05 20:41:30 2017 +0200 @@ -91,7 +91,7 @@ final Object[] oarray = new Object[trim ? len : array.length]; for (int index = 0; index < len; index++) { - oarray[index] = Long.valueOf(array[index]); + oarray[index] = array[index]; } return oarray; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Jul 05 20:41:30 2017 +0200 @@ -91,7 +91,7 @@ final Object[] oarray = new Object[trim ? len : array.length]; for (int index = 0; index < len; index++) { - oarray[index] = Double.valueOf(array[index]); + oarray[index] = array[index]; } return oarray; } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Jul 05 20:41:30 2017 +0200 @@ -95,11 +95,11 @@ final TreeMap newSparseMap = new TreeMap<>(); for (final Map.Entry entry : sparseMap.entrySet()) { - final long newIndex = entry.getKey().longValue() - by; + final long newIndex = entry.getKey() - by; if (newIndex < maxDenseLength) { underlying = underlying.set((int) newIndex, entry.getValue(), false); } else if (newIndex >= 0) { - newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); + newSparseMap.put(newIndex, entry.getValue()); } } @@ -114,7 +114,7 @@ if (len + by > maxDenseLength) { for (long i = maxDenseLength - by; i < len; i++) { if (underlying.has((int) i)) { - newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i)); + newSparseMap.put(i + by, underlying.getObject((int) i)); } } underlying = underlying.shrink((int) (maxDenseLength - by)); @@ -123,8 +123,8 @@ underlying.shiftRight(by); for (final Map.Entry entry : sparseMap.entrySet()) { - final long newIndex = entry.getKey().longValue() + by; - newSparseMap.put(Long.valueOf(newIndex), entry.getValue()); + final long newIndex = entry.getKey() + by; + newSparseMap.put(newIndex, entry.getValue()); } sparseMap = newSparseMap; @@ -158,7 +158,7 @@ setLength(newLength); } - sparseMap.subMap(Long.valueOf(newLength), Long.MAX_VALUE).clear(); + sparseMap.subMap(newLength, Long.MAX_VALUE).clear(); setLength(newLength); return this; } @@ -333,7 +333,7 @@ } private static Long indexToKey(final int index) { - return Long.valueOf(ArrayIndex.toLongIndex(index)); + return ArrayIndex.toLongIndex(index); } @Override @@ -355,7 +355,7 @@ return result; } setLength(len - 1); - final Long key = Long.valueOf(len - 1); + final Long key = len - 1; return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED; } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 05 20:41:30 2017 +0200 @@ -47,7 +47,6 @@ import jdk.internal.dynalink.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; -import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; import jdk.nashorn.internal.objects.ScriptFunctionImpl; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Jul 05 20:41:30 2017 +0200 @@ -107,7 +107,7 @@ if (o instanceof Number) { final int ival = ((Number)o).intValue(); if (ival >= Character.MIN_VALUE && ival <= Character.MAX_VALUE) { - return Character.valueOf((char) ival); + return (char) ival; } throw typeError("cant.convert.number.to.char"); @@ -196,13 +196,13 @@ return ((Integer)obj).longValue(); } else if (obj instanceof Double) { final Double d = (Double)obj; - if(Double.isInfinite(d.doubleValue())) { + if(Double.isInfinite(d)) { return 0L; } return d.longValue(); } else if (obj instanceof Float) { final Float f = (Float)obj; - if(Float.isInfinite(f.floatValue())) { + if(Float.isInfinite(f)) { return 0L; } return f.longValue(); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java Wed Jul 05 20:41:30 2017 +0200 @@ -101,9 +101,7 @@ } public void copy(final BitSet other) { - for (int i=0; i"); + s.append("<").append(getAddressName()).append(" (").append(parent == null ? "NULL" : parent.getAddressName()).append(")>"); return s + toString(0); } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java Wed Jul 05 20:41:30 2017 +0200 @@ -118,14 +118,14 @@ @Override public String toString(final int level) { final StringBuilder value = new StringBuilder(super.toString(level)); - value.append("\n target: " + pad(target, level + 1)); - value.append("\n lower: " + lower); - value.append("\n upper: " + upper); - value.append("\n greedy: " + greedy); - value.append("\n targetEmptyInfo: " + targetEmptyInfo); - value.append("\n headExact: " + pad(headExact, level + 1)); - value.append("\n nextHeadExact: " + pad(nextHeadExact, level + 1)); - value.append("\n isRefered: " + isRefered); + value.append("\n target: ").append(pad(target, level + 1)); + value.append("\n lower: ").append(lower); + value.append("\n upper: ").append(upper); + value.append("\n greedy: ").append(greedy); + value.append("\n targetEmptyInfo: ").append(targetEmptyInfo); + value.append("\n headExact: ").append(pad(headExact, level + 1)); + value.append("\n nextHeadExact: ").append(pad(nextHeadExact, level + 1)); + value.append("\n isRefered: ").append(isRefered); return value.toString(); } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java Wed Jul 05 20:41:30 2017 +0200 @@ -71,7 +71,7 @@ final char[] tmp = new char[len + NODE_STR_MARGIN]; System.arraycopy(chars, p, tmp, 0, end - p); chars = tmp; - end = end - p; + end -= p; p = 0; clearShared(); } else { diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Jul 05 20:41:30 2017 +0200 @@ -54,7 +54,6 @@ import jdk.nashorn.internal.runtime.ScriptEnvironment; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.options.Options; /** diff -r b050dcca193f -r 9b3a9d72f07b nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java Wed Jul 05 20:41:30 2017 +0200 @@ -29,10 +29,8 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import jdk.nashorn.internal.runtime.JSType; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java --- a/nashorn/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java Wed Jul 05 20:41:30 2017 +0200 @@ -176,7 +176,7 @@ } public Boolean booleanBoxingMethod(final Boolean arg) { - return !arg.booleanValue(); + return !arg; } public boolean[] booleanArrayMethod(final boolean arg[]) { diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java --- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -573,7 +573,7 @@ } // properties that can be read by any code - private static String[] propNames = { + private static final String[] PROP_NAMES = { "java.version", "java.vendor", "java.vendor.url", @@ -601,7 +601,7 @@ final ScriptEngineManager m = new ScriptEngineManager(); final ScriptEngine e = m.getEngineByName("nashorn"); - for (final String name : propNames) { + for (final String name : PROP_NAMES) { checkProperty(e, name); } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java --- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -278,7 +278,7 @@ ScriptObjectMirror obj = (ScriptObjectMirror)e.eval( "({ valueOf: function() { return 42 } })"); - assertEquals(Double.valueOf(42.0), obj.to(Double.class)); + assertEquals(42.0, obj.to(Double.class)); obj = (ScriptObjectMirror)e.eval( "({ toString: function() { return 'foo' } })"); diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/api/tree/test/ParseAPITest.java --- a/nashorn/test/src/jdk/nashorn/api/tree/test/ParseAPITest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/api/tree/test/ParseAPITest.java Wed Jul 05 20:41:30 2017 +0200 @@ -67,7 +67,7 @@ parseTestSet(TEST262_SUITE_DIR, new TestFilter() { @Override public boolean exclude(final File file, final String content) { - return content.indexOf("@negative") != -1; + return content.contains("@negative"); } }); } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java --- a/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java Wed Jul 05 20:41:30 2017 +0200 @@ -272,10 +272,10 @@ Double nashornToRhino = null; Double nashornToV8 = null; if (rhino != null && rhino != 0) { - nashornToRhino = nashorn.doubleValue() / rhino.doubleValue(); + nashornToRhino = nashorn / rhino; } if (v8 != null && rhino != 0) { - nashornToV8 = nashorn.doubleValue() / v8.doubleValue(); + nashornToV8 = nashorn / v8; } final String normalizedBenchmark=benchmark.replace("-", ""); System.out.println("benchmark-" + normalizedBenchmark + "-nashorn=" + nashorn); @@ -300,20 +300,12 @@ boolean checkRhinoPresence() { final String rhinojar = System.getProperty("rhino.jar"); - if (rhinojar != null) { - // System.out.println("Rhino jar found; performing comparison testing"); - return true; - } - return false; + return rhinojar != null; } boolean checkV8Presence() { final String v8shell = System.getProperty("v8.shell.full.path"); - if (v8shell != null) { - // System.out.println("d8 found; performing comparison testing"); - return true; - } - return false; + return v8shell != null; } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java --- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java Wed Jul 05 20:41:30 2017 +0200 @@ -62,7 +62,7 @@ @Test public void unwarrantedOptimismExceptionNotSerializable() { - tryToSerialize(new UnwarrantedOptimismException(new Double(1.0), 128)); + tryToSerialize(new UnwarrantedOptimismException(1.0, 128)); } private static void tryToSerialize(final Object obj) { diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java --- a/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java Wed Jul 05 20:41:30 2017 +0200 @@ -159,7 +159,7 @@ forkJVMOptions = (vmOptions != null)? vmOptions.split(" ") : new String[0]; } - private static ThreadLocal evaluators = new ThreadLocal<>(); + private static final ThreadLocal EVALUATORS = new ThreadLocal<>(); /** * Create a script evaluator or return from cache @@ -167,7 +167,7 @@ */ protected ScriptEvaluator getEvaluator() { synchronized (AbstractScriptRunnable.class) { - ScriptEvaluator evaluator = evaluators.get(); + ScriptEvaluator evaluator = EVALUATORS.get(); if (evaluator == null) { if (sharedContext) { final String[] args; @@ -177,10 +177,10 @@ args = new String[] { framework }; } evaluator = new SharedContextEvaluator(args); - evaluators.set(evaluator); + EVALUATORS.set(evaluator); } else { evaluator = new SeparateContextEvaluator(); - evaluators.set(evaluator); + EVALUATORS.set(evaluator); } } return evaluator; diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java --- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java Wed Jul 05 20:41:30 2017 +0200 @@ -378,7 +378,7 @@ * @return true if optimistic type override has been set by test suite */ public static boolean hasOptimisticOverride() { - return Boolean.valueOf(OPTIMISTIC_OVERRIDE).toString().equals(System.getProperty("optimistic.override")); + return Boolean.toString(OPTIMISTIC_OVERRIDE).equals(System.getProperty("optimistic.override")); } /** @@ -391,8 +391,8 @@ public static String[] addExplicitOptimisticTypes(final String[] args) { if (hasOptimisticOverride()) { final List newList = new ArrayList<>(Arrays.asList(args)); - newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); - return newList.toArray(new String[0]); + newList.add("--optimistic-types=" + OPTIMISTIC_OVERRIDE); + return newList.toArray(new String[newList.size()]); } return args; } @@ -405,7 +405,7 @@ */ public static void addExplicitOptimisticTypes(final List args) { if (hasOptimisticOverride()) { - args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE)); + args.add("--optimistic-types=" + OPTIMISTIC_OVERRIDE); } } diff -r b050dcca193f -r 9b3a9d72f07b nashorn/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java --- a/nashorn/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java Wed Jul 05 20:40:53 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java Wed Jul 05 20:41:30 2017 +0200 @@ -64,9 +64,9 @@ private static void walkCollection(final Collection c) { final Iterator it = c.iterator(); - assertEquals(it.next(), Integer.valueOf(1)); - assertEquals(it.next(), Integer.valueOf(2)); - assertEquals(it.next(), Double.valueOf(3.3)); + assertEquals(it.next(), 1); + assertEquals(it.next(), 2); + assertEquals(it.next(), 3.3); assertEquals(it.next(), "foo"); assertFalse(it.hasNext()); }