diff --git a/.hgtags b/.hgtags index 75a7d82083f..722b0b67512 100644 --- a/.hgtags +++ b/.hgtags @@ -19,3 +19,8 @@ a2879b2837f5a4c87e9542efe69ef138194af8ff jdk7-b38 caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42 41bd0a702bc8ec6feebd725a63e7c3227f82ab11 jdk7-b43 5843778bda89b1d5ac8e1aa05e26930ac90b3145 jdk7-b44 +54dffad0bf066791a2793305875250c395011d5f jdk7-b45 +04b2620edc72de93671646e4720c5992c74ac8b5 jdk7-b46 +0c4657194eec95c08ba478aee9cfc3c295e41657 jdk7-b47 +1bf51a4c2627c2f0e0cbcc2cf0421bdb37f1f2b2 jdk7-b48 +6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 45f6c86faf1..241e1cd4090 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -19,3 +19,8 @@ ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39 94052b87287303527125026fe4b2698cf867ea83 jdk7-b42 848e684279d2ba42577d9621d5b2e5af3823d12d jdk7-b43 a395e3aac4744cc9033fcd819fad1239a45add52 jdk7-b44 +99846f001ca214015578d593802d26e27246a802 jdk7-b45 +e8a2a4d187773a62f3309b0fa265c13425bc2258 jdk7-b46 +d7744e86dedc21a8ecf6bdb73eb191b8eaf5b0da jdk7-b47 +4ae9f4bfdb98f65bd957e3fe72471b320150b38e jdk7-b48 +aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49 diff --git a/corba/.hgtags b/corba/.hgtags index a08aaca8282..434fb013994 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -19,3 +19,8 @@ c90eeda9594ed2983403e2049aed8d503126c62e jdk7-b41 ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42 9cd740d48a4855321d69f137a7109c00bcda76be jdk7-b43 9803dac7254041b30ca65e3852d4c566b9757c3b jdk7-b44 +68814aa5b44b1f16931a97e7cd4028c70eb9586b jdk7-b45 +1691dbfc08f8ee3f4e23a1ff30cdff920718696c jdk7-b46 +167ad0164301f318b069a947e1c9c07ed667748a jdk7-b47 +0be222241fd405e48915647facfaa176621b39b9 jdk7-b48 +d70978bc64bc7a04be7797ab0dcd9b7b1b3a6bff jdk7-b49 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 2b249bae719..c1cb5d2f77a 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -19,3 +19,8 @@ f9d938ede1960d18cb7cf23c645b026519c1a678 jdk7-b41 ad8c8ca4ab0f4c86e74c061958f44a8f4a930f2c jdk7-b42 fc6a5ae3fef5ebacfa896dbb3ae37715e388e282 jdk7-b43 809e899c638bd9b21836abf9d09ab2a30ff3900b jdk7-b44 +945bf754069766e76873c53102fae48abf04cf5b jdk7-b45 +16bb38eeda35b46268eefa4c1f829eb086e0ca46 jdk7-b46 +fcb923bad68e2b10380a030ea83a723f4dc3d4d6 jdk7-b47 +bcb33806d186561c781992e5f4d8a90bb033f9f0 jdk7-b48 +8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 diff --git a/hotspot/agent/src/os/linux/ps_core.c b/hotspot/agent/src/os/linux/ps_core.c index 3562f2d31f6..a6156f0a8d4 100644 --- a/hotspot/agent/src/os/linux/ps_core.c +++ b/hotspot/agent/src/os/linux/ps_core.c @@ -238,8 +238,8 @@ struct FileMapHeader { // Ignore the rest of the FileMapHeader. We don't need those fields here. }; -static bool read_int(struct ps_prochandle* ph, uintptr_t addr, int* pvalue) { - int i; +static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) { + jboolean i; if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) { *pvalue = i; return true; @@ -295,7 +295,7 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) { int fd = -1, m = 0; uintptr_t base = 0, useSharedSpacesAddr = 0; uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; - int useSharedSpaces = 0; + jboolean useSharedSpaces = 0; map_info* mi = 0; memset(classes_jsa, 0, sizeof(classes_jsa)); @@ -306,12 +306,15 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) { return false; } - if (read_int(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { + // Hotspot vm types are not exported to build this library. So + // using equivalent type jboolean to read the value of + // UseSharedSpaces which is same as hotspot type "bool". + if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { print_debug("can't read the value of 'UseSharedSpaces' flag\n"); return false; } - if (useSharedSpaces == 0) { + if ((int)useSharedSpaces == 0) { print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); return true; } diff --git a/hotspot/agent/src/os/solaris/proc/saproc.cpp b/hotspot/agent/src/os/solaris/proc/saproc.cpp index 231773c5647..415e28af658 100644 --- a/hotspot/agent/src/os/solaris/proc/saproc.cpp +++ b/hotspot/agent/src/os/solaris/proc/saproc.cpp @@ -502,8 +502,8 @@ struct FileMapHeader { }; static bool -read_int(struct ps_prochandle* ph, psaddr_t addr, int* pvalue) { - int i; +read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) { + jboolean i; if (ps_pread(ph, addr, &i, sizeof(i)) == PS_OK) { *pvalue = i; return true; @@ -575,10 +575,13 @@ init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name } // read the value of the flag "UseSharedSpaces" - int value = 0; - if (read_int(ph, useSharedSpacesAddr, &value) != true) { + // Since hotspot types are not available to build this library. So + // equivalent type "jboolean" is used to read the value of "UseSharedSpaces" + // which is same as hotspot type "bool". + jboolean value = 0; + if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) { THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1); - } else if (value == 0) { + } else if ((int)value == 0) { print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); return 1; } diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 4454f180b5b..eea8597c7cf 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -33,9 +33,9 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_COPYRIGHT=Copyright 2008 -HS_MAJOR_VER=14 +HS_MAJOR_VER=15 HS_MINOR_VER=0 -HS_BUILD_NUMBER=10 +HS_BUILD_NUMBER=02 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff --git a/hotspot/src/cpu/sparc/vm/jni_sparc.h b/hotspot/src/cpu/sparc/vm/jni_sparc.h index 7d2845e0162..33a494b6066 100644 --- a/hotspot/src/cpu/sparc/vm/jni_sparc.h +++ b/hotspot/src/cpu/sparc/vm/jni_sparc.h @@ -28,5 +28,11 @@ #define JNICALL typedef int jint; -typedef long long jlong; + +#ifdef _LP64 + typedef long jlong; +#else + typedef long long jlong; +#endif + typedef signed char jbyte; diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 06af021d1fd..b4a94ac240a 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -762,7 +762,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te case Assembler::stdf_op3: st_op = Op_StoreD; break; case Assembler::ldsb_op3: ld_op = Op_LoadB; break; - case Assembler::lduh_op3: ld_op = Op_LoadC; break; + case Assembler::lduh_op3: ld_op = Op_LoadUS; break; case Assembler::ldsh_op3: ld_op = Op_LoadS; break; case Assembler::ldx_op3: // may become LoadP or stay LoadI case Assembler::ldsw_op3: // may become LoadP or stay LoadI @@ -3869,6 +3869,8 @@ operand regD() %{ constraint(ALLOC_IN_RC(dflt_reg)); match(RegD); + match(regD_low); + format %{ %} interface(REG_INTER); %} @@ -3883,7 +3885,7 @@ operand regF() %{ operand regD_low() %{ constraint(ALLOC_IN_RC(dflt_low_reg)); - match(RegD); + match(regD); format %{ %} interface(REG_INTER); @@ -5314,9 +5316,9 @@ instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{ ins_pipe(iload_mask_mem); %} -// Load Char (16bit UNsigned) into a Long Register -instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{ - match(Set dst (AndL (ConvI2L (LoadC mem)) bytemask)); +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register +instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{ + match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask)); ins_cost(MEMORY_REF_COST); size(4); @@ -5326,9 +5328,9 @@ instruct loadUCL(iRegL dst, memory mem, immL_FFFF bytemask) %{ ins_pipe(iload_mask_mem); %} -// Load Char (16bit unsigned) -instruct loadC(iRegI dst, memory mem) %{ - match(Set dst (LoadC mem)); +// Load Unsigned Short/Char (16bit unsigned) +instruct loadUS(iRegI dst, memory mem) %{ + match(Set dst (LoadUS mem)); ins_cost(MEMORY_REF_COST); size(4); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index edf0d3dbcaf..d6433f0e176 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -5212,15 +5212,15 @@ void MacroAssembler::pushptr(AddressLiteral src) { void MacroAssembler::reset_last_Java_frame(bool clear_fp, bool clear_pc) { // we must set sp to zero to clear frame - movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), (int32_t)NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); // must clear fp, so that compiled frames are not confused; it is // possible that we need it only for debugging if (clear_fp) { - movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), (int32_t)NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); } if (clear_pc) { - movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), (int32_t)NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); } } @@ -5670,7 +5670,7 @@ void MacroAssembler::call_VM_base(Register oop_result, // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); - movptr(Address(java_thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); + movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); verify_oop(oop_result, "broken oop in call_VM_base"); } } @@ -6426,13 +6426,13 @@ void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp, get_thread(java_thread); } // we must set sp to zero to clear frame - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), (int32_t)NULL_WORD); + movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); if (clear_fp) { - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), (int32_t)NULL_WORD); + movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); } if (clear_pc) - movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), (int32_t)NULL_WORD); + movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); } @@ -6943,29 +6943,32 @@ void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) { Label slow_case, done; - // x ?<= pi/4 - fld_d(ExternalAddress((address)&pi_4)); - fld_s(1); // Stack: X PI/4 X - fabs(); // Stack: |X| PI/4 X - fcmp(tmp); - jcc(Assembler::above, slow_case); + ExternalAddress pi4_adr = (address)&pi_4; + if (reachable(pi4_adr)) { + // x ?<= pi/4 + fld_d(pi4_adr); + fld_s(1); // Stack: X PI/4 X + fabs(); // Stack: |X| PI/4 X + fcmp(tmp); + jcc(Assembler::above, slow_case); - // fastest case: -pi/4 <= x <= pi/4 - switch(trig) { - case 's': - fsin(); - break; - case 'c': - fcos(); - break; - case 't': - ftan(); - break; - default: - assert(false, "bad intrinsic"); - break; + // fastest case: -pi/4 <= x <= pi/4 + switch(trig) { + case 's': + fsin(); + break; + case 'c': + fcos(); + break; + case 't': + ftan(); + break; + default: + assert(false, "bad intrinsic"); + break; + } + jmp(done); } - jmp(done); // slow case: runtime call bind(slow_case); diff --git a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp index 0e41dbc4a21..f66bfd4d309 100644 --- a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.inline.hpp @@ -213,7 +213,7 @@ inline jint BytecodeInterpreter::VMintAnd(jint op1, jint op2) { inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) { /* it's possible we could catch this special case implicitly */ - if (op1 == 0x80000000 && op2 == -1) return op1; + if ((juint)op1 == 0x80000000 && op2 == -1) return op1; else return op1 / op2; } @@ -231,7 +231,7 @@ inline jint BytecodeInterpreter::VMintOr(jint op1, jint op2) { inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) { /* it's possible we could catch this special case implicitly */ - if (op1 == 0x80000000 && op2 == -1) return 0; + if ((juint)op1 == 0x80000000 && op2 == -1) return 0; else return op1 % op2; } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 4300d196c28..cdf508fab01 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -779,7 +779,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi case T_OBJECT: // fall through case T_ARRAY: if (c->as_jobject() == NULL) { - __ movptr(as_Address(addr), (int32_t)NULL_WORD); + __ movptr(as_Address(addr), NULL_WORD); } else { if (is_literal_address(addr)) { ShouldNotReachHere(); diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index eed2ad68de4..12aea3fde07 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -78,10 +78,10 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e movptr(rax, Address(thread, Thread::pending_exception_offset())); // make sure that the vm_results are cleared if (oop_result1->is_valid()) { - movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); } if (oop_result2->is_valid()) { - movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); } if (frame_size() == no_frame_size) { leave(); @@ -96,12 +96,12 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e // get oop results if there are any and reset the values in the thread if (oop_result1->is_valid()) { movptr(oop_result1, Address(thread, JavaThread::vm_result_offset())); - movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); verify_oop(oop_result1); } if (oop_result2->is_valid()) { movptr(oop_result2, Address(thread, JavaThread::vm_result_2_offset())); - movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); + movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); verify_oop(oop_result2); } return call_offset; @@ -728,8 +728,8 @@ void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_map // clear exception fields in JavaThread because they are no longer needed // (fields must be cleared because they are processed by GC otherwise) - __ movptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); - __ movptr(Address(thread, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); + __ movptr(Address(thread, JavaThread::exception_oop_offset()), NULL_WORD); + __ movptr(Address(thread, JavaThread::exception_pc_offset()), NULL_WORD); // pop the stub frame off __ leave(); @@ -878,7 +878,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { // load and clear pending exception __ movptr(rax, Address(thread, Thread::pending_exception_offset())); - __ movptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); // check that there is really a valid exception __ verify_not_null_oop(rax); @@ -971,14 +971,14 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // load pending exception oop into rax, __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); // clear pending exception - __ movptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); // load issuing PC (the return address for this stub) into rdx __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); // make sure that the vm_results are cleared (may be unnecessary) - __ movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); - __ movptr(Address(thread, JavaThread::vm_result_2_offset()), (int32_t)NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); // verify that that there is really a valid exception in rax, __ verify_not_null_oop(exception_oop); @@ -1393,7 +1393,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ ret(0); __ bind(miss); - __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), 0); // result + __ movptr(Address(rsp, (super_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result __ pop(rax); __ pop(rcx); __ pop(rsi); diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp index ecaa3ec21af..a3621ad886c 100644 --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp @@ -594,7 +594,7 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax); // for c++ interpreter can rsi really be munged? - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); // restore state + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); // restore state __ movptr(rbx, Address(state, byte_offset_of(BytecodeInterpreter, _method))); // restore method __ movptr(rdi, Address(state, byte_offset_of(BytecodeInterpreter, _locals))); // get locals pointer @@ -658,7 +658,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) { const Address size_of_stack (rbx, methodOopDesc::max_stack_offset()); // Always give one monitor to allow us to start interp if sync method. // Any additional monitors need a check when moving the expression stack - const one_monitor = frame::interpreter_frame_monitor_size() * wordSize; + const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; __ load_unsigned_word(rax, size_of_stack); // get size of expression stack in words __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor)); __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size)); @@ -1829,7 +1829,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { Label unwind_and_forward; // restore state pointer. - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); __ movptr(rbx, STATE(_method)); // get method #ifdef _LP64 @@ -1877,14 +1877,14 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases if (UseSSE < 2) { - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); __ movptr(rbx, STATE(_result._to_call._callee)); // get method just executed __ movl(rcx, Address(rbx, methodOopDesc::result_index_offset())); __ cmpl(rcx, AbstractInterpreter::BasicType_as_index(T_FLOAT)); // Result stub address array index __ jcc(Assembler::equal, do_float); __ cmpl(rcx, AbstractInterpreter::BasicType_as_index(T_DOUBLE)); // Result stub address array index __ jcc(Assembler::equal, do_double); -#ifdef COMPILER2 +#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) __ empty_FPU_stack(); #endif // COMPILER2 __ jmp(done_conv); @@ -1928,7 +1928,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // Restore rsi/r13 as compiled code may not preserve it - __ lea(state, Address(rbp, -sizeof(BytecodeInterpreter))); + __ lea(state, Address(rbp, -(int)sizeof(BytecodeInterpreter))); // restore stack to what we had when we left (in case i2c extended it) @@ -1942,7 +1942,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { #else __ movptr(rcx, STATE(_thread)); // get thread __ cmpptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); -#endif / __LP64 +#endif // _LP64 __ jcc(Assembler::notZero, return_with_exception); // get method just executed diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index f06b40de350..82c37fd41da 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -139,7 +139,7 @@ inline address* frame::native_param_addr(int idx) const { return (address*) addr #ifdef CC_INTERP inline interpreterState frame::get_interpreterState() const { - return ((interpreterState)addr_at( -sizeof(BytecodeInterpreter)/wordSize )); + return ((interpreterState)addr_at( -((int)sizeof(BytecodeInterpreter))/wordSize )); } inline intptr_t* frame::sender_sp() const { diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index 78f0f123833..c11c3bc5404 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -133,7 +133,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { + in_ByteSize(wordSize)); switch (state) { case atos: movptr(rax, oop_addr); - movptr(oop_addr, (int32_t)NULL_WORD); + movptr(oop_addr, NULL_WORD); verify_oop(rax, state); break; case ltos: movl(rdx, val_addr1); // fall through @@ -148,8 +148,8 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { } // Clean up tos value in the thread object movl(tos_addr, (int32_t) ilgl); - movptr(val_addr, (int32_t)NULL_WORD); - NOT_LP64(movl(val_addr1, (int32_t)NULL_WORD)); + movptr(val_addr, NULL_WORD); + NOT_LP64(movptr(val_addr1, NULL_WORD)); } @@ -944,7 +944,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); // Free entry - movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); + movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); if (UseBiasedLocking) { biased_locking_exit(obj_reg, header_reg, done); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp index 247f4ec3b47..57cd7f325fe 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp @@ -120,7 +120,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void empty_expression_stack() { movptr(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); // NULL last_sp until next java call - movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); } // Tagged stack helpers for swap and dup diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index 9809649d37e..ebcac0fddf9 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -30,7 +30,7 @@ #ifdef CC_INTERP void InterpreterMacroAssembler::get_method(Register reg) { - movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); + movptr(reg, Address(rbp, -((int)sizeof(BytecodeInterpreter) + 2 * wordSize))); movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); } #endif // CC_INTERP diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp index 96a1c3073d4..60af2f45735 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp @@ -54,7 +54,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::box(int from_offset, int to_ __ cmpptr(Address(from(), Interpreter::local_offset_in_bytes(from_offset)), (int32_t)NULL_WORD); // do not use temp() to avoid AGI Label L; __ jcc(Assembler::notZero, L); - __ movptr(temp(), ((int32_t)NULL_WORD)); + __ movptr(temp(), NULL_WORD); __ bind(L); __ movptr(Address(to(), to_offset * wordSize), temp()); } @@ -110,7 +110,7 @@ class SlowSignatureHandler: public NativeSignatureIterator { virtual void pass_object() { // pass address of from intptr_t from_addr = (intptr_t)(_from + Interpreter::local_offset_in_bytes(0)); - *_to++ = (*(intptr_t*)from_addr == 0) ? NULL : from_addr; + *_to++ = (*(intptr_t*)from_addr == 0) ? NULL_WORD : from_addr; debug_only(verify_tag(frame::TagReference)); _from -= Interpreter::stackElementSize(); } diff --git a/hotspot/src/cpu/x86/vm/jni_x86.h b/hotspot/src/cpu/x86/vm/jni_x86.h index 89f95e35749..625562bb3f2 100644 --- a/hotspot/src/cpu/x86/vm/jni_x86.h +++ b/hotspot/src/cpu/x86/vm/jni_x86.h @@ -32,7 +32,13 @@ #define JNICALL typedef int jint; + +#ifdef _LP64 + typedef long jlong; +#else typedef long long jlong; +#endif + #else #define JNIEXPORT __declspec(dllexport) #define JNIIMPORT __declspec(dllimport) diff --git a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp index 72870e11e07..6a92a2c053e 100644 --- a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp @@ -129,11 +129,11 @@ void OptoRuntime::generate_exception_blob() { // Get the exception pc in case we are deoptimized __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); #ifdef ASSERT - __ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), (int32_t)NULL_WORD); - __ movptr(Address(rcx, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), NULL_WORD); + __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); #endif // Clear the exception oop so GC no longer processes it as a root. - __ movptr(Address(rcx, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); __ pop(rcx); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 7c0aa6bf556..3cf22d7fa05 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -39,6 +39,8 @@ RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; RuntimeStub* SharedRuntime::_resolve_static_call_blob; +const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; + class RegisterSaver { enum { FPU_regs_live = 8 /*for the FPU stack*/+8/*eight more for XMM registers*/ }; // Capture info about frame layout @@ -1299,7 +1301,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); + stack_slots = round_to(stack_slots, StackAlignmentInSlots); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -1793,7 +1795,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // reset handle block __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // Any exception pending? __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); @@ -1865,7 +1867,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Save pending exception around call to VM (which contains an EXCEPTION_MARK) __ pushptr(Address(thread, in_bytes(Thread::pending_exception_offset()))); - __ movptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); + __ movptr(Address(thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); // should be a peal @@ -2431,7 +2433,7 @@ void SharedRuntime::generate_deopt_blob() { __ get_thread(rdi); __ movptr(rdx, Address(rdi, JavaThread::exception_pc_offset())); __ movptr(Address(rbp, wordSize), rdx); - __ movptr(Address(rdi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rdi, JavaThread::exception_pc_offset()), NULL_WORD); #ifdef ASSERT // verify that there is really an exception oop in JavaThread @@ -2489,8 +2491,8 @@ void SharedRuntime::generate_deopt_blob() { __ jcc(Assembler::notEqual, noException); __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); - __ movptr(Address(rcx, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); - __ movptr(Address(rcx, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); + __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); __ verify_oop(rax); @@ -2582,7 +2584,7 @@ void SharedRuntime::generate_deopt_blob() { rbx); // Make it walkable #else /* CC_INTERP */ // This value is corrected by layout_activation_impl - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable #endif /* CC_INTERP */ __ movptr(sp_temp, rsp); // pass to next frame @@ -2802,7 +2804,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { rbx); // Make it walkable #else /* CC_INTERP */ // This value is corrected by layout_activation_impl - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable #endif /* CC_INTERP */ __ movptr(sp_temp, rsp); // pass to next frame @@ -3020,7 +3022,7 @@ static RuntimeStub* generate_resolve_blob(address destination, const char* name) // exception pending => remove activation and forward to exception handler __ get_thread(thread); - __ movptr(Address(thread, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); __ movptr(rax, Address(thread, Thread::pending_exception_offset())); __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 26e7e148968..7fc2b6685e4 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -39,6 +39,8 @@ RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; RuntimeStub* SharedRuntime::_resolve_static_call_blob; +const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; + #define __ masm-> class SimpleRuntimeFrame { @@ -1286,7 +1288,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word); + stack_slots = round_to(stack_slots, StackAlignmentInSlots); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -2954,10 +2956,16 @@ void SharedRuntime::generate_uncommon_trap_blob() { __ pushptr(Address(rcx, 0)); // Save return address __ enter(); // Save old & set new rbp __ subptr(rsp, rbx); // Prolog +#ifdef CC_INTERP + __ movptr(Address(rbp, + -(sizeof(BytecodeInterpreter)) + in_bytes(byte_offset_of(BytecodeInterpreter, _sender_sp))), + sender_sp); // Make it walkable +#else // CC_INTERP __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), sender_sp); // Make it walkable // This value is corrected by layout_activation_impl __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD ); +#endif // CC_INTERP __ mov(sender_sp, rsp); // Pass sender_sp to next frame __ addptr(rsi, wordSize); // Bump array pointer (sizes) __ addptr(rcx, wordSize); // Bump array pointer (pcs) diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 06435cb0005..9b220e20449 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -407,7 +407,7 @@ class StubGenerator: public StubCodeGenerator { __ get_thread(rcx); __ pop(rdx); __ movptr(rax, Address(rcx, Thread::pending_exception_offset())); - __ movptr(Address(rcx, Thread::pending_exception_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, Thread::pending_exception_offset()), NULL_WORD); #ifdef ASSERT // make sure exception is set diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 33f6e88ee6d..6c2fb5694e8 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -472,7 +472,7 @@ class StubGenerator: public StubCodeGenerator { // setup rax & rdx, remove return address & clear pending exception __ pop(rdx); __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); - __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); + __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); #ifdef ASSERT // make sure exception is set @@ -954,9 +954,9 @@ class StubGenerator: public StubCodeGenerator { __ jcc(Assembler::zero, exit); // if obj is NULL it is OK // Check if the oop is in the right area of memory __ movptr(c_rarg2, rax); - __ movptr(c_rarg3, (int64_t) Universe::verify_oop_mask()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_mask()); __ andptr(c_rarg2, c_rarg3); - __ movptr(c_rarg3, (int64_t) Universe::verify_oop_bits()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_bits()); __ cmpptr(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); @@ -969,9 +969,9 @@ class StubGenerator: public StubCodeGenerator { __ jcc(Assembler::zero, error); // if klass is NULL it is broken // Check if the klass is in the right area of memory __ mov(c_rarg2, rax); - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); __ andptr(c_rarg2, c_rarg3); - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); __ cmpptr(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); @@ -980,9 +980,9 @@ class StubGenerator: public StubCodeGenerator { __ testptr(rax, rax); __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken // Check if the klass' klass is in the right area of memory - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); __ andptr(rax, c_rarg3); - __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); + __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); __ cmpptr(rax, c_rarg3); __ jcc(Assembler::notZero, error); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index ca186af69a1..ed40fb70124 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -110,7 +110,7 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch if (message != NULL) { __ lea(rbx, ExternalAddress((address)message)); } else { - __ movptr(rbx, (int32_t)NULL_WORD); + __ movptr(rbx, NULL_WORD); } __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), rax, rbx); } @@ -123,7 +123,7 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { address entry = __ pc(); // NULL last_sp until next java call - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ dispatch_next(state); return entry; } @@ -176,7 +176,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, // Restore stack bottom in case i2c adjusted stack __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); // and NULL it as marker that rsp is now tos until next java call - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); __ restore_locals(); @@ -211,7 +211,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i // The stack is not extended by deopt but we must NULL last_sp as this // entry is like a "return". - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); __ restore_locals(); // handle exceptions @@ -382,7 +382,7 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { // indicating if the counter overflow occurs at a backwards branch (non-NULL bcp). // The call returns the address of the verified entry point for the method or NULL // if the compilation did not complete (either went background or bailed out). - __ movptr(rax, (int32_t)false); + __ movptr(rax, (intptr_t)false); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rax); __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop @@ -1028,7 +1028,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // reset handle block __ movptr(t, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // If result was an oop then unbox and save it in the frame { Label L; @@ -1488,7 +1488,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Restore sp to interpreter_frame_last_sp even though we are going // to empty the expression stack for the exception processing. - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); // rax,: exception // rdx: return address/pc that threw exception __ restore_bcp(); // rsi points to call/send @@ -1608,7 +1608,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ reset_last_Java_frame(rcx, true, true); // Restore the last_sp and null it out __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); __ restore_locals(); @@ -1636,7 +1636,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // restore exception __ get_thread(rcx); __ movptr(rax, Address(rcx, JavaThread::vm_result_offset())); - __ movptr(Address(rcx, JavaThread::vm_result_offset()), (int32_t)NULL_WORD); + __ movptr(Address(rcx, JavaThread::vm_result_offset()), NULL_WORD); __ verify_oop(rax); // Inbetween activations - previous activation type unknown yet diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 5acd696b2b0..13242651c7e 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -137,7 +137,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, // Do the actual store // noreg means NULL if (val == noreg) { - __ movl(Address(rdx, 0), NULL_WORD); + __ movptr(Address(rdx, 0), NULL_WORD); // No post barrier for NULL } else { __ movl(Address(rdx, 0), val); @@ -152,7 +152,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, case BarrierSet::CardTableExtension: { if (val == noreg) { - __ movl(obj, NULL_WORD); + __ movptr(obj, NULL_WORD); } else { __ movl(obj, val); // flatten object address if needed @@ -168,7 +168,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, case BarrierSet::ModRef: case BarrierSet::Other: if (val == noreg) { - __ movl(obj, NULL_WORD); + __ movptr(obj, NULL_WORD); } else { __ movl(obj, val); } diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 5f6f8724adb..edc6a63e79f 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -3371,7 +3371,7 @@ encode %{ masm.movptr(Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty masm.get_thread (scrReg) ; masm.movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] - masm.movptr(tmpReg, 0); // consider: xor vs mov + masm.movptr(tmpReg, NULL_WORD); // consider: xor vs mov if (os::is_MP()) { masm.lock(); } masm.cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; } else @@ -3387,7 +3387,7 @@ encode %{ if ((EmitSync & 64) == 0) { // Optimistic form: consider XORL tmpReg,tmpReg - masm.movptr(tmpReg, 0 ) ; + masm.movptr(tmpReg, NULL_WORD) ; } else { // Can suffer RTS->RTO upgrades on shared or cold $ lines // Test-And-CAS instead of CAS @@ -3587,7 +3587,7 @@ encode %{ masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; masm.jccb (Assembler::notZero, DONE_LABEL) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; masm.jmpb (DONE_LABEL) ; } else { masm.xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; @@ -3596,7 +3596,7 @@ encode %{ masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; masm.orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; masm.jccb (Assembler::notZero, CheckSucc) ; - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; masm.jmpb (DONE_LABEL) ; } @@ -3644,7 +3644,7 @@ encode %{ // We currently use (3), although it's likely that switching to (2) // is correct for the future. - masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), 0) ; + masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD) ; if (os::is_MP()) { if (VM_Version::supports_sse2() && 1 == FenceInstruction) { masm.mfence(); @@ -6413,9 +6413,9 @@ instruct loadUB(xRegI dst, memory mem, immI_255 bytemask) %{ ins_pipe( ialu_reg_mem ); %} -// Load Char (16bit unsigned) -instruct loadC(eRegI dst, memory mem) %{ - match(Set dst (LoadC mem)); +// Load Unsigned Short/Char (16bit unsigned) +instruct loadUS(eRegI dst, memory mem) %{ + match(Set dst (LoadUS mem)); ins_cost(125); format %{ "MOVZX $dst,$mem" %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 9b5621f3903..ad4f03b23a3 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -6096,25 +6096,25 @@ instruct loadS(rRegI dst, memory mem) // ins_pipe(ialu_reg_mem); // %} -// Load Char (16 bit UNsigned) -instruct loadC(rRegI dst, memory mem) +// Load Unsigned Short/Char (16 bit UNsigned) +instruct loadUS(rRegI dst, memory mem) %{ - match(Set dst (LoadC mem)); + match(Set dst (LoadUS mem)); ins_cost(125); - format %{ "movzwl $dst, $mem\t# char" %} + format %{ "movzwl $dst, $mem\t# ushort/char" %} opcode(0x0F, 0xB7); ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); ins_pipe(ialu_reg_mem); %} -// Load Char (16 bit UNsigned) into long -// instruct loadC2L(rRegL dst, memory mem) +// Load Unsigned Short/Char (16 bit UNsigned) into long +// instruct loadUS2L(rRegL dst, memory mem) // %{ -// match(Set dst (ConvI2L (LoadC mem))); +// match(Set dst (ConvI2L (LoadUS mem))); // ins_cost(125); -// format %{ "movzwl $dst, $mem\t# char -> long" %} +// format %{ "movzwl $dst, $mem\t# ushort/char -> long" %} // opcode(0x0F, 0xB7); // ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem)); // ins_pipe(ialu_reg_mem); @@ -9490,14 +9490,14 @@ instruct andL_rReg_imm255(rRegL dst, immL_255 src) %{ match(Set dst (AndL dst src)); - format %{ "movzbq $dst, $src\t# long & 0xFF" %} + format %{ "movzbq $dst, $dst\t# long & 0xFF" %} opcode(0x0F, 0xB6); ins_encode(REX_reg_reg_wide(dst, dst), OpcP, OpcS, reg_reg(dst, dst)); ins_pipe(ialu_reg); %} // And Register with Immediate 65535 -instruct andL_rReg_imm65535(rRegI dst, immL_65535 src) +instruct andL_rReg_imm65535(rRegL dst, immL_65535 src) %{ match(Set dst (AndL dst src)); diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3b8c0b4dc03..846906951d4 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -279,7 +279,11 @@ void os::init_system_properties_values() { * ... * 7: The default directories, normally /lib and /usr/lib. */ +#if defined(AMD64) || defined(_LP64) && (defined(SPARC) || defined(PPC) || defined(S390)) +#define DEFAULT_LIBPATH "/usr/lib64:/lib64:/lib:/usr/lib" +#else #define DEFAULT_LIBPATH "/lib:/usr/lib" +#endif #define EXTENSIONS_DIR "/lib/ext" #define ENDORSED_DIR "/lib/endorsed" @@ -1160,7 +1164,10 @@ void os::Linux::capture_initial_stack(size_t max_size) { /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */ /* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */ - i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu", + i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld " + UINTX_FORMAT UINTX_FORMAT UINTX_FORMAT + " %lu " + UINTX_FORMAT UINTX_FORMAT UINTX_FORMAT, &state, /* 3 %c */ &ppid, /* 4 %d */ &pgrp, /* 5 %d */ @@ -1180,13 +1187,13 @@ void os::Linux::capture_initial_stack(size_t max_size) { &nice, /* 19 %ld */ &junk, /* 20 %ld */ &it_real, /* 21 %ld */ - &start, /* 22 %lu */ - &vsize, /* 23 %lu */ - &rss, /* 24 %ld */ + &start, /* 22 UINTX_FORMAT */ + &vsize, /* 23 UINTX_FORMAT */ + &rss, /* 24 UINTX_FORMAT */ &rsslim, /* 25 %lu */ - &scodes, /* 26 %lu */ - &ecode, /* 27 %lu */ - &stack_start); /* 28 %lu */ + &scodes, /* 26 UINTX_FORMAT */ + &ecode, /* 27 UINTX_FORMAT */ + &stack_start); /* 28 UINTX_FORMAT */ } if (i != 28 - 2) { @@ -1425,6 +1432,10 @@ char * os::local_time_string(char *buf, size_t buflen) { return buf; } +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + return localtime_r(clock, res); +} + //////////////////////////////////////////////////////////////////////////////// // runtime exit support @@ -2024,7 +2035,8 @@ void os::jvm_path(char *buf, jint len) { CAST_FROM_FN_PTR(address, os::jvm_path), dli_fname, sizeof(dli_fname), NULL); assert(ret != 0, "cannot locate libjvm"); - realpath(dli_fname, buf); + if (realpath(dli_fname, buf) == NULL) + return; if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { // Support for the gamma launcher. Typical value for buf is @@ -2048,7 +2060,8 @@ void os::jvm_path(char *buf, jint len) { assert(strstr(p, "/libjvm") == p, "invalid library name"); p = strstr(p, "_g") ? "_g" : ""; - realpath(java_home_var, buf); + if (realpath(java_home_var, buf) == NULL) + return; sprintf(buf + strlen(buf), "/jre/lib/%s", cpu_arch); if (0 == access(buf, F_OK)) { // Use current module name "libjvm[_g].so" instead of @@ -2059,7 +2072,8 @@ void os::jvm_path(char *buf, jint len) { sprintf(buf + strlen(buf), "/hotspot/libjvm%s.so", p); } else { // Go back to path of .so - realpath(dli_fname, buf); + if (realpath(dli_fname, buf) == NULL) + return; } } } @@ -4184,11 +4198,11 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { // Skip blank chars do s++; while (isspace(*s)); - count = sscanf(s,"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu", - &idummy, &idummy, &idummy, &idummy, &idummy, &idummy, + count = sscanf(s,"%*c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu", + &idummy, &idummy, &idummy, &idummy, &idummy, &ldummy, &ldummy, &ldummy, &ldummy, &ldummy, &user_time, &sys_time); - if ( count != 13 ) return -1; + if ( count != 12 ) return -1; if (user_sys_cpu_time) { return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec); } else { diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index f74967ab079..c5c83883f48 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -323,6 +323,10 @@ size_t os::current_stack_size() { return (size_t)(base - bottom); } +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + return localtime_r(clock, res); +} + // interruptible infrastructure // setup_interruptible saves the thread state before going into an diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index d674d434b90..dce602e8ecb 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -327,6 +327,14 @@ size_t os::current_stack_size() { return sz; } +struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + const struct tm* time_struct_ptr = localtime(clock); + if (time_struct_ptr != NULL) { + *res = *time_struct_ptr; + return res; + } + return NULL; +} LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo); diff --git a/hotspot/src/share/vm/adlc/dict2.cpp b/hotspot/src/share/vm/adlc/dict2.cpp index 640fad4af11..f46693fd06c 100644 --- a/hotspot/src/share/vm/adlc/dict2.cpp +++ b/hotspot/src/share/vm/adlc/dict2.cpp @@ -316,9 +316,12 @@ int cmpstr(const void *k1, const void *k2) { return strcmp((const char *)k1,(const char *)k2); } -// Slimey cheap key comparator. +// Cheap key comparator. int cmpkey(const void *key1, const void *key2) { - return (int)((intptr_t)key1 - (intptr_t)key2); + if (key1 == key2) return 0; + intptr_t delta = (intptr_t)key1 - (intptr_t)key2; + if (delta > 0) return 1; + return -1; } //============================================================================= diff --git a/hotspot/src/share/vm/adlc/forms.cpp b/hotspot/src/share/vm/adlc/forms.cpp index e2083c68259..cfcfd0a36d8 100644 --- a/hotspot/src/share/vm/adlc/forms.cpp +++ b/hotspot/src/share/vm/adlc/forms.cpp @@ -248,7 +248,7 @@ Form::DataType Form::ideal_to_Reg_type(const char *name) const { // True if 'opType', an ideal name, loads or stores. Form::DataType Form::is_load_from_memory(const char *opType) const { if( strcmp(opType,"LoadB")==0 ) return Form::idealB; - if( strcmp(opType,"LoadC")==0 ) return Form::idealC; + if( strcmp(opType,"LoadUS")==0 ) return Form::idealC; if( strcmp(opType,"LoadD")==0 ) return Form::idealD; if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD; if( strcmp(opType,"LoadF")==0 ) return Form::idealF; diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 65b511bcdb1..c265c1d04c7 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -3314,7 +3314,7 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , "StoreB","StoreC","Store" ,"StoreFP", "LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , - "LoadB" ,"LoadC" ,"LoadS" ,"Load" , + "LoadB" ,"LoadUS" ,"LoadS" ,"Load" , "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B", "Store8B","Store4B","Store8C","Store4C","Store2C", "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" , diff --git a/hotspot/src/share/vm/asm/codeBuffer.cpp b/hotspot/src/share/vm/asm/codeBuffer.cpp index cbd16d3e8b3..7ae4a13232a 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.cpp +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp @@ -123,6 +123,10 @@ CodeBuffer::~CodeBuffer() { // addresses constructed before expansions will not be confused. cb->free_blob(); } + + // free any overflow storage + delete _overflow_arena; + #ifdef ASSERT Copy::fill_to_bytes(this, sizeof(*this), badResourceValue); #endif diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 703217f9255..4f8ec88f866 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -232,7 +232,9 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { length >= 1, "Illegal constant pool size %u in class file %s", length, CHECK_(nullHandle)); constantPoolOop constant_pool = - oopFactory::new_constantPool(length, CHECK_(nullHandle)); + oopFactory::new_constantPool(length, + methodOopDesc::IsSafeConc, + CHECK_(nullHandle)); constantPoolHandle cp (THREAD, constant_pool); cp->set_partially_loaded(); // Enables heap verify to work on partial constantPoolOops @@ -1675,7 +1677,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf // All sizing information for a methodOop is finally available, now create it methodOop m_oop = oopFactory::new_method( code_length, access_flags, linenumber_table_length, - total_lvt_length, checked_exceptions_length, CHECK_(nullHandle)); + total_lvt_length, checked_exceptions_length, + methodOopDesc::IsSafeConc, CHECK_(nullHandle)); methodHandle m (THREAD, m_oop); ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index ea68a366740..385e6a16e7f 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -441,6 +441,7 @@ oop java_lang_Class::primitive_mirror(BasicType t) { bool java_lang_Class::offsets_computed = false; int java_lang_Class::classRedefinedCount_offset = -1; +int java_lang_Class::parallelCapable_offset = -1; void java_lang_Class::compute_offsets() { assert(!offsets_computed, "offsets should be initialized only once"); @@ -451,6 +452,23 @@ void java_lang_Class::compute_offsets() { // so don't go fatal. compute_optional_offset(classRedefinedCount_offset, k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); + + // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, + klassOop k1 = SystemDictionary::classloader_klass(); + compute_optional_offset(parallelCapable_offset, + k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); +} + +// For class loader classes, parallelCapable defined +// based on non-null field +// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it +bool java_lang_Class::parallelCapable(oop class_loader) { + if (!JDK_Version::is_gte_jdk17x_version() + || parallelCapable_offset == -1) { + // Default for backward compatibility is false + return false; + } + return (class_loader->obj_field(parallelCapable_offset) != NULL); } int java_lang_Class::classRedefinedCount(oop the_class_mirror) { @@ -866,7 +884,7 @@ char* java_lang_Throwable::print_stack_element_to_buffer(methodOop method, int b } nmethod* nm = method->code(); if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod %#x)", nm); + sprintf(buf + (int)strlen(buf), "(nmethod " PTR_FORMAT ")", (intptr_t)nm); } } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 933d5b82d83..612a0013562 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -141,6 +141,7 @@ class java_lang_Class : AllStatic { static void compute_offsets(); static bool offsets_computed; static int classRedefinedCount_offset; + static int parallelCapable_offset; public: // Instance creation @@ -168,6 +169,8 @@ class java_lang_Class : AllStatic { // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); static void set_classRedefinedCount(oop the_class_mirror, int value); + // Support for parallelCapable field + static bool parallelCapable(oop the_class_mirror); // Debugging friend class JavaClasses; friend class instanceKlass; // verification code accesses offsets diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 0908e1c8785..9ab749afb3e 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -89,6 +89,14 @@ bool SystemDictionary::is_internal_format(symbolHandle class_name) { #endif +// ---------------------------------------------------------------------------- +// Parallel class loading check + +bool SystemDictionary::is_parallelCapable(Handle class_loader) { + if (UnsyncloadClass || class_loader.is_null()) return true; + if (AlwaysLockClassLoader) return false; + return java_lang_Class::parallelCapable(class_loader()); +} // ---------------------------------------------------------------------------- // Resolving of classes @@ -196,7 +204,8 @@ klassOop SystemDictionary::resolve_array_class_or_null(symbolHandle class_name, // super-class callers: // ClassFileParser - for defineClass & jvmtiRedefineClasses // load_shared_class - while loading a class from shared archive -// resolve_instance_class_or_fail: +// resolve_instance_class_or_null: +// via: handle_parallel_super_load // when resolving a class that has an existing placeholder with // a saved superclass [i.e. a defineClass is currently in progress] // if another thread is trying to resolve the class, it must do @@ -283,12 +292,9 @@ klassOop SystemDictionary::resolve_super_or_fail(symbolHandle child_name, if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) { throw_circularity_error = true; } - - // add placeholder entry even if error - callers will remove on error + } + if (!throw_circularity_error) { PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, child_name, class_loader, PlaceholderTable::LOAD_SUPER, class_name, THREAD); - if (throw_circularity_error) { - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER); - } } } if (throw_circularity_error) { @@ -325,7 +331,6 @@ klassOop SystemDictionary::resolve_super_or_fail(symbolHandle child_name, return superk_h(); } - void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, Handle class_loader, Handle protection_domain, @@ -421,7 +426,7 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { bool calledholdinglock = ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject); assert(calledholdinglock,"must hold lock for notify"); - assert(!UnsyncloadClass, "unexpected double_lock_wait"); + assert((!(lockObject() == _system_loader_lock_obj) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait"); ObjectSynchronizer::notifyall(lockObject, THREAD); intptr_t recursions = ObjectSynchronizer::complete_exit(lockObject, THREAD); SystemDictionary_lock->wait(); @@ -439,7 +444,7 @@ void SystemDictionary::double_lock_wait(Handle lockObject, TRAPS) { // even in non-circularity situations. // Note: only one thread can define the class, but multiple can resolve // Note: must call resolve_super_or_fail even if null super - -// to force placeholder entry creation for this class +// to force placeholder entry creation for this class for circularity detection // Caller must check for pending exception // Returns non-null klassOop if other thread has completed load // and we are done, @@ -477,9 +482,9 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( SystemDictionary_lock->notify_all(); } - // UnsyncloadClass does NOT wait for parallel superclass loads to complete - // Bootstrap classloader does wait for parallel superclass loads - if (UnsyncloadClass) { + // parallelCapable class loaders do NOT wait for parallel superclass loads to complete + // Serial class loaders and bootstrap classloader do wait for superclass loads + if (!class_loader.is_null() && is_parallelCapable(class_loader)) { MutexLocker mu(SystemDictionary_lock, THREAD); // Check if classloading completed while we were loading superclass or waiting klassOop check = find_class(d_index, d_hash, name, class_loader); @@ -566,10 +571,10 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam // This lock must be acquired here so the waiter will find // any successful result in the SystemDictionary and not attempt // the define - // Classloaders that support parallelism, e.g. bootstrap classloader, + // ParallelCapable Classloaders and the bootstrap classloader, // or all classloaders with UnsyncloadClass do not acquire lock here bool DoObjectLock = true; - if (UnsyncloadClass || (class_loader.is_null())) { + if (is_parallelCapable(class_loader)) { DoObjectLock = false; } @@ -627,6 +632,9 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam // Five cases: // All cases need to prevent modifying bootclasssearchpath // in parallel with a classload of same classname + // Redefineclasses uses existence of the placeholder for the duration + // of the class load to prevent concurrent redefinition of not completely + // defined classes. // case 1. traditional classloaders that rely on the classloader object lock // - no other need for LOAD_INSTANCE // case 2. traditional classloaders that break the classloader object lock @@ -642,12 +650,13 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam // This classloader supports parallelism at the classloader level, // but only allows a single load of a class/classloader pair. // No performance benefit and no deadlock issues. - // case 5. Future: parallel user level classloaders - without objectLocker + // case 5. parallelCapable user level classloaders - without objectLocker + // Allow parallel classloading of a class/classloader pair symbolHandle nullsymbolHandle; bool throw_circularity_error = false; { MutexLocker mu(SystemDictionary_lock, THREAD); - if (!UnsyncloadClass) { + if (class_loader.is_null() || !is_parallelCapable(class_loader)) { PlaceholderEntry* oldprobe = placeholders()->get_entry(p_index, p_hash, name, class_loader); if (oldprobe) { // only need check_seen_thread once, not on each loop @@ -681,25 +690,25 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam } } // All cases: add LOAD_INSTANCE - // case 3: UnsyncloadClass: allow competing threads to try + // case 3: UnsyncloadClass || case 5: parallelCapable: allow competing threads to try // LOAD_INSTANCE in parallel // add placeholder entry even if error - callers will remove on error - if (!class_has_been_loaded) { + if (!throw_circularity_error && !class_has_been_loaded) { PlaceholderEntry* newprobe = placeholders()->find_and_add(p_index, p_hash, name, class_loader, PlaceholderTable::LOAD_INSTANCE, nullsymbolHandle, THREAD); - if (throw_circularity_error) { - newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); - } // For class loaders that do not acquire the classloader object lock, // if they did not catch another thread holding LOAD_INSTANCE, // need a check analogous to the acquire ObjectLocker/find_class // i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL // one final check if the load has already completed + // class loaders holding the ObjectLock shouldn't find the class here klassOop check = find_class(d_index, d_hash, name, class_loader); if (check != NULL) { // Klass is already loaded, so just return it k = instanceKlassHandle(THREAD, check); class_has_been_loaded = true; newprobe->remove_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE); + placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD); + SystemDictionary_lock->notify_all(); } } } @@ -714,18 +723,14 @@ klassOop SystemDictionary::resolve_instance_class_or_null(symbolHandle class_nam // Do actual loading k = load_instance_class(name, class_loader, THREAD); - // In custom class loaders, the usual findClass calls - // findLoadedClass, which directly searches the SystemDictionary, then - // defineClass. If these are not atomic with respect to other threads, - // the findLoadedClass can fail, but the defineClass can get a - // LinkageError:: duplicate class definition. + // For UnsyncloadClass and AllowParallelDefineClass only: // If they got a linkageError, check if a parallel class load succeeded. // If it did, then for bytecode resolution the specification requires // that we return the same result we did for the other thread, i.e. the // successfully loaded instanceKlass - // Note: Class can not be unloaded as long as any classloader refs exist // Should not get here for classloaders that support parallelism - // with the new cleaner mechanism, e.g. bootstrap classloader + // with the new cleaner mechanism + // Bootstrap goes through here to allow for an extra guarantee check if (UnsyncloadClass || (class_loader.is_null())) { if (k.is_null() && HAS_PENDING_EXCEPTION && PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { @@ -841,6 +846,12 @@ klassOop SystemDictionary::find(symbolHandle class_name, Handle protection_domain, TRAPS) { + // UseNewReflection + // The result of this call should be consistent with the result + // of the call to resolve_instance_class_or_null(). + // See evaluation 6790209 and 4474172 for more details. + class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); + unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader); int d_index = dictionary()->hash_to_index(d_hash); @@ -955,10 +966,10 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name, instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, class_loader, protection_domain, - cp_patches, parsed_name, THREAD); + // We don't redefine the class, so we just need to clean up whether there // was an error or not (don't want to modify any system dictionary // data structures). @@ -1013,11 +1024,17 @@ klassOop SystemDictionary::resolve_from_stream(symbolHandle class_name, ClassFileStream* st, TRAPS) { - // Make sure we are synchronized on the class loader before we initiate - // loading. + // Classloaders that support parallelism, e.g. bootstrap classloader, + // or all classloaders with UnsyncloadClass do not acquire lock here + bool DoObjectLock = true; + if (is_parallelCapable(class_loader)) { + DoObjectLock = false; + } + + // Make sure we are synchronized on the class loader before we proceed Handle lockObject = compute_loader_lock_object(class_loader, THREAD); check_loader_lock_contention(lockObject, THREAD); - ObjectLocker ol(lockObject, THREAD); + ObjectLocker ol(lockObject, THREAD, DoObjectLock); symbolHandle parsed_name; @@ -1069,7 +1086,13 @@ klassOop SystemDictionary::resolve_from_stream(symbolHandle class_name, "external class name format used internally"); // Add class just loaded - define_instance_class(k, THREAD); + // If a class loader supports parallel classloading handle parallel define requests + // find_or_define_instance_class may return a different instanceKlass + if (is_parallelCapable(class_loader)) { + k = find_or_define_instance_class(class_name, class_loader, k, THREAD); + } else { + define_instance_class(k, THREAD); + } } // If parsing the class file or define_instance_class failed, we @@ -1299,7 +1322,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam } #endif // KERNEL - // find_or_define_instance_class may return a different k + // find_or_define_instance_class may return a different instanceKlass if (!k.is_null()) { k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); } @@ -1316,14 +1339,24 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_nam KlassHandle spec_klass (THREAD, SystemDictionary::classloader_klass()); - // UnsyncloadClass option means don't synchronize loadClass() calls. - // loadClassInternal() is synchronized and public loadClass(String) is not. - // This flag is for diagnostic purposes only. It is risky to call + // Call public unsynchronized loadClass(String) directly for all class loaders + // for parallelCapable class loaders. JDK >=7, loadClass(String, boolean) will + // acquire a class-name based lock rather than the class loader object lock. + // JDK < 7 already acquire the class loader lock in loadClass(String, boolean), + // so the call to loadClassInternal() was not required. + // + // UnsyncloadClass flag means both call loadClass(String) and do + // not acquire the class loader lock even for class loaders that are + // not parallelCapable. This was a risky transitional + // flag for diagnostic purposes only. It is risky to call // custom class loaders without synchronization. // WARNING If a custom class loader does NOT synchronizer findClass, or callers of - // findClass, this flag risks unexpected timing bugs in the field. + // findClass, the UnsyncloadClass flag risks unexpected timing bugs in the field. // Do NOT assume this will be supported in future releases. - if (!UnsyncloadClass && has_loadClassInternal()) { + // + // Added MustCallLoadClassInternal in case we discover in the field + // a customer that counts on this call + if (MustCallLoadClassInternal && has_loadClassInternal()) { JavaCalls::call_special(&result, class_loader, spec_klass, @@ -1365,14 +1398,17 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { Handle class_loader_h(THREAD, k->class_loader()); - // for bootstrap classloader don't acquire lock - if (!class_loader_h.is_null()) { + // for bootstrap and other parallel classloaders don't acquire lock, + // use placeholder token + // If a parallelCapable class loader calls define_instance_class instead of + // find_or_define_instance_class to get here, we have a timing + // hole with systemDictionary updates and check_constraints + if (!class_loader_h.is_null() && !is_parallelCapable(class_loader_h)) { assert(ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, compute_loader_lock_object(class_loader_h, THREAD)), "define called without lock"); } - // Check class-loading constraints. Throw exception if violation is detected. // Grabs and releases SystemDictionary_lock // The check_constraints/find_class call and update_dictionary sequence @@ -1427,59 +1463,63 @@ void SystemDictionary::define_instance_class(instanceKlassHandle k, TRAPS) { // Support parallel classloading // Initial implementation for bootstrap classloader -// For future: // For custom class loaders that support parallel classloading, -// in case they do not synchronize around -// FindLoadedClass/DefineClass calls, we check for parallel +// With AllowParallelDefine flag==true, in case they do not synchronize around +// FindLoadedClass/DefineClass, calls, we check for parallel // loading for them, wait if a defineClass is in progress // and return the initial requestor's results +// With AllowParallelDefine flag==false, call through to define_instance_class +// which will throw LinkageError: duplicate class definition. // For better performance, the class loaders should synchronize -// findClass(), i.e. FindLoadedClass/DefineClass or they +// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they // potentially waste time reading and parsing the bytestream. // Note: VM callers should ensure consistency of k/class_name,class_loader instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle class_name, Handle class_loader, instanceKlassHandle k, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle + symbolHandle name_h(THREAD, k->name()); // passed in class_name may be null - unsigned int d_hash = dictionary()->compute_hash(class_name, class_loader); + unsigned int d_hash = dictionary()->compute_hash(name_h, class_loader); int d_index = dictionary()->hash_to_index(d_hash); // Hold SD lock around find_class and placeholder creation for DEFINE_CLASS - unsigned int p_hash = placeholders()->compute_hash(class_name, class_loader); + unsigned int p_hash = placeholders()->compute_hash(name_h, class_loader); int p_index = placeholders()->hash_to_index(p_hash); PlaceholderEntry* probe; { MutexLocker mu(SystemDictionary_lock, THREAD); // First check if class already defined - klassOop check = find_class(d_index, d_hash, class_name, class_loader); + klassOop check = find_class(d_index, d_hash, name_h, class_loader); if (check != NULL) { return(instanceKlassHandle(THREAD, check)); } // Acquire define token for this class/classloader symbolHandle nullsymbolHandle; - probe = placeholders()->find_and_add(p_index, p_hash, class_name, class_loader, PlaceholderTable::DEFINE_CLASS, nullsymbolHandle, THREAD); - // Check if another thread defining in parallel - if (probe->definer() == NULL) { - // Thread will define the class - probe->set_definer(THREAD); - } else { - // Wait for defining thread to finish and return results - while (probe->definer() != NULL) { - SystemDictionary_lock->wait(); - } - if (probe->instanceKlass() != NULL) { + probe = placeholders()->find_and_add(p_index, p_hash, name_h, class_loader, PlaceholderTable::DEFINE_CLASS, nullsymbolHandle, THREAD); + // Wait if another thread defining in parallel + // All threads wait - even those that will throw duplicate class: otherwise + // caller is surprised by LinkageError: duplicate, but findLoadedClass fails + // if other thread has not finished updating dictionary + while (probe->definer() != NULL) { + SystemDictionary_lock->wait(); + } + // Only special cases allow parallel defines and can use other thread's results + // Other cases fall through, and may run into duplicate defines + // caught by finding an entry in the SystemDictionary + if ((UnsyncloadClass || AllowParallelDefineClass) && (probe->instanceKlass() != NULL)) { probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); - return(instanceKlassHandle(THREAD, probe->instanceKlass())); - } else { - // If definer had an error, try again as any new thread would - probe->set_definer(THREAD); + placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD); + SystemDictionary_lock->notify_all(); #ifdef ASSERT - klassOop check = find_class(d_index, d_hash, class_name, class_loader); - assert(check == NULL, "definer missed recording success"); + klassOop check = find_class(d_index, d_hash, name_h, class_loader); + assert(check != NULL, "definer missed recording success"); #endif - } + return(instanceKlassHandle(THREAD, probe->instanceKlass())); + } else { + // This thread will define the class (even if earlier thread tried and had an error) + probe->set_definer(THREAD); } } @@ -1490,7 +1530,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle // definer must notify any waiting threads { MutexLocker mu(SystemDictionary_lock, THREAD); - PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, class_name, class_loader); + PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, name_h, class_loader); assert(probe != NULL, "DEFINE_CLASS placeholder lost?"); if (probe != NULL) { if (HAS_PENDING_EXCEPTION) { @@ -1501,6 +1541,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle } probe->set_definer(NULL); probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); + placeholders()->find_and_remove(p_index, p_hash, name_h, class_loader, THREAD); SystemDictionary_lock->notify_all(); } } @@ -1512,7 +1553,6 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(symbolHandle return k; } - Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) { // If class_loader is NULL we synchronize on _system_loader_lock_obj if (class_loader.is_null()) { @@ -1902,11 +1942,11 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { warning("Cannot find sun/jkernel/DownloadManager"); } #endif // KERNEL + { // Compute whether we should use loadClass or loadClassInternal when loading classes. methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); } - { // Compute whether we should use checkPackageAccess or NOT methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::checkPackageAccess_name(), vmSymbols::class_protectiondomain_signature()); _has_checkPackageAccess = (method != NULL); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index beade180fcd..38abf2d3c0a 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -526,6 +526,7 @@ private: static instanceKlassHandle load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS); static Handle compute_loader_lock_object(Handle class_loader, TRAPS); static void check_loader_lock_contention(Handle loader_lock, TRAPS); + static bool is_parallelCapable(Handle class_loader); static klassOop find_shared_class(symbolHandle class_name); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 6a5a796d010..8379af9c414 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -362,6 +362,7 @@ template(class_signature, "Ljava/lang/Class;") \ template(string_signature, "Ljava/lang/String;") \ template(reference_signature, "Ljava/lang/ref/Reference;") \ + template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ @@ -374,6 +375,9 @@ /* used by ClassFormatError when class name is not known yet */ \ template(unknown_class_name, "") \ \ + /* used to identify class loaders handling parallel class loading */ \ + template(parallelCapable_name, "parallelLockMap;") \ + \ /* JVM monitoring and management support */ \ template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \ template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \ diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 4b1fecd7cb3..6c6272a2f84 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -706,6 +706,30 @@ void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) { } } +// Apply the given closure to each live object in the space +// The usage of CompactibleFreeListSpace +// by the ConcurrentMarkSweepGeneration for concurrent GC's allows +// objects in the space with references to objects that are no longer +// valid. For example, an object may reference another object +// that has already been sweep up (collected). This method uses +// obj_is_alive() to determine whether it is safe to apply the closure to +// an object. See obj_is_alive() for details on how liveness of an +// object is decided. + +void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) { + assert_lock_strong(freelistLock()); + NOT_PRODUCT(verify_objects_initialized()); + HeapWord *cur, *limit; + size_t curSize; + for (cur = bottom(), limit = end(); cur < limit; + cur += curSize) { + curSize = block_size(cur); + if (block_is_obj(cur) && obj_is_alive(cur)) { + blk->do_object(oop(cur)); + } + } +} + void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) { assert_locked(); @@ -861,7 +885,9 @@ const { } else { // must read from what 'p' points to in each loop. klassOop k = ((volatile oopDesc*)p)->klass_or_null(); - if (k != NULL && ((oopDesc*)p)->is_parsable()) { + if (k != NULL && + ((oopDesc*)p)->is_parsable() && + ((oopDesc*)p)->is_conc_safe()) { assert(k->is_oop(), "Should really be klass oop."); oop o = (oop)p; assert(o->is_oop(), "Should be an oop"); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 5306a8f3085..e0c48a1b79a 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -481,6 +481,15 @@ class CompactibleFreeListSpace: public CompactibleSpace { void oop_iterate(OopClosure* cl); void object_iterate(ObjectClosure* blk); + // Apply the closure to each object in the space whose references + // point to objects in the heap. The usage of CompactibleFreeListSpace + // by the ConcurrentMarkSweepGeneration for concurrent GC's allows + // objects in the space with references to objects that are no longer + // valid. For example, an object may reference another object + // that has already been sweep up (collected). This method uses + // obj_is_alive() to determine whether it is safe to iterate of + // an object. + void safe_object_iterate(ObjectClosure* blk); void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); // Requires that "mr" be entirely within the space. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index e8344107659..d716797bab4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -3017,6 +3017,16 @@ ConcurrentMarkSweepGeneration::object_iterate(ObjectClosure* cl) { } } +void +ConcurrentMarkSweepGeneration::safe_object_iterate(ObjectClosure* cl) { + if (freelistLock()->owned_by_self()) { + Generation::safe_object_iterate(cl); + } else { + MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); + Generation::safe_object_iterate(cl); + } +} + void ConcurrentMarkSweepGeneration::pre_adjust_pointers() { } @@ -6623,7 +6633,11 @@ size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m( if (_bitMap->isMarked(addr)) { // it's marked; is it potentially uninitialized? if (p->klass_or_null() != NULL) { - if (CMSPermGenPrecleaningEnabled && !p->is_parsable()) { + // If is_conc_safe is false, the object may be undergoing + // change by the VM outside a safepoint. Don't try to + // scan it, but rather leave it for the remark phase. + if (CMSPermGenPrecleaningEnabled && + (!p->is_conc_safe() || !p->is_parsable())) { // Signal precleaning to redirty the card since // the klass pointer is already installed. assert(size == 0, "Initial value"); @@ -7001,7 +7015,6 @@ void MarkFromRootsClosure::scanOopsInOop(HeapWord* ptr) { _mut->clear_range(mr); } DEBUG_ONLY(}) - // Note: the finger doesn't advance while we drain // the stack below. PushOrMarkClosure pushOrMarkClosure(_collector, @@ -8062,9 +8075,13 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { #ifdef DEBUG if (oop(addr)->klass_or_null() != NULL && ( !_collector->should_unload_classes() - || oop(addr)->is_parsable())) { + || (oop(addr)->is_parsable()) && + oop(addr)->is_conc_safe())) { // Ignore mark word because we are running concurrent with mutators assert(oop(addr)->is_oop(true), "live block should be an oop"); + // is_conc_safe is checked before performing this assertion + // because an object that is not is_conc_safe may yet have + // the return from size() correct. assert(size == CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()), "P-mark and computed size do not agree"); @@ -8077,6 +8094,13 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { (!_collector->should_unload_classes() || oop(addr)->is_parsable()), "Should be an initialized object"); + // Note that there are objects used during class redefinition + // (e.g., merge_cp in VM_RedefineClasses::merge_cp_and_rewrite() + // which are discarded with their is_conc_safe state still + // false. These object may be floating garbage so may be + // seen here. If they are floating garbage their size + // should be attainable from their klass. Do not that + // is_conc_safe() is true for oop(addr). // Ignore mark word because we are running concurrent with mutators assert(oop(addr)->is_oop(true), "live block should be an oop"); // Verify that the bit map has no bits marked between @@ -8484,7 +8508,7 @@ bool CMSCollector::take_from_overflow_list(size_t num, CMSMarkStack* stack) { size_t i = num; oop cur = _overflow_list; const markOop proto = markOopDesc::prototype(); - NOT_PRODUCT(size_t n = 0;) + NOT_PRODUCT(ssize_t n = 0;) for (oop next; i > 0 && cur != NULL; cur = next, i--) { next = oop(cur->mark()); cur->set_mark(proto); // until proven otherwise @@ -8501,45 +8525,131 @@ bool CMSCollector::take_from_overflow_list(size_t num, CMSMarkStack* stack) { return !stack->isEmpty(); } -// Multi-threaded; use CAS to break off a prefix +#define BUSY (oop(0x1aff1aff)) +// (MT-safe) Get a prefix of at most "num" from the list. +// The overflow list is chained through the mark word of +// each object in the list. We fetch the entire list, +// break off a prefix of the right size and return the +// remainder. If other threads try to take objects from +// the overflow list at that time, they will wait for +// some time to see if data becomes available. If (and +// only if) another thread places one or more object(s) +// on the global list before we have returned the suffix +// to the global list, we will walk down our local list +// to find its end and append the global list to +// our suffix before returning it. This suffix walk can +// prove to be expensive (quadratic in the amount of traffic) +// when there are many objects in the overflow list and +// there is much producer-consumer contention on the list. +// *NOTE*: The overflow list manipulation code here and +// in ParNewGeneration:: are very similar in shape, +// except that in the ParNew case we use the old (from/eden) +// copy of the object to thread the list via its klass word. +// Because of the common code, if you make any changes in +// the code below, please check the ParNew version to see if +// similar changes might be needed. +// CR 6797058 has been filed to consolidate the common code. bool CMSCollector::par_take_from_overflow_list(size_t num, OopTaskQueue* work_q) { - assert(work_q->size() == 0, "That's the current policy"); + assert(work_q->size() == 0, "First empty local work queue"); assert(num < work_q->max_elems(), "Can't bite more than we can chew"); if (_overflow_list == NULL) { return false; } // Grab the entire list; we'll put back a suffix - oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list); - if (prefix == NULL) { // someone grabbed it before we did ... - // ... we could spin for a short while, but for now we don't - return false; + oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); + Thread* tid = Thread::current(); + size_t CMSOverflowSpinCount = (size_t)ParallelGCThreads; + size_t sleep_time_millis = MAX2((size_t)1, num/100); + // If the list is busy, we spin for a short while, + // sleeping between attempts to get the list. + for (size_t spin = 0; prefix == BUSY && spin < CMSOverflowSpinCount; spin++) { + os::sleep(tid, sleep_time_millis, false); + if (_overflow_list == NULL) { + // Nothing left to take + return false; + } else if (_overflow_list != BUSY) { + // Try and grab the prefix + prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); + } } + // If the list was found to be empty, or we spun long + // enough, we give up and return empty-handed. If we leave + // the list in the BUSY state below, it must be the case that + // some other thread holds the overflow list and will set it + // to a non-BUSY state in the future. + if (prefix == NULL || prefix == BUSY) { + // Nothing to take or waited long enough + if (prefix == NULL) { + // Write back the NULL in case we overwrote it with BUSY above + // and it is still the same value. + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); + } + return false; + } + assert(prefix != NULL && prefix != BUSY, "Error"); size_t i = num; oop cur = prefix; + // Walk down the first "num" objects, unless we reach the end. for (; i > 1 && cur->mark() != NULL; cur = oop(cur->mark()), i--); - if (cur->mark() != NULL) { + if (cur->mark() == NULL) { + // We have "num" or fewer elements in the list, so there + // is nothing to return to the global list. + // Write back the NULL in lieu of the BUSY we wrote + // above, if it is still the same value. + if (_overflow_list == BUSY) { + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); + } + } else { + // Chop off the suffix and rerturn it to the global list. + assert(cur->mark() != BUSY, "Error"); oop suffix_head = cur->mark(); // suffix will be put back on global list cur->set_mark(NULL); // break off suffix - // Find tail of suffix so we can prepend suffix to global list - for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark())); - oop suffix_tail = cur; - assert(suffix_tail != NULL && suffix_tail->mark() == NULL, - "Tautology"); + // It's possible that the list is still in the empty(busy) state + // we left it in a short while ago; in that case we may be + // able to place back the suffix without incurring the cost + // of a walk down the list. oop observed_overflow_list = _overflow_list; - do { - cur = observed_overflow_list; - suffix_tail->set_mark(markOop(cur)); + oop cur_overflow_list = observed_overflow_list; + bool attached = false; + while (observed_overflow_list == BUSY || observed_overflow_list == NULL) { observed_overflow_list = - (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur); - } while (cur != observed_overflow_list); + (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list); + if (cur_overflow_list == observed_overflow_list) { + attached = true; + break; + } else cur_overflow_list = observed_overflow_list; + } + if (!attached) { + // Too bad, someone else sneaked in (at least) an element; we'll need + // to do a splice. Find tail of suffix so we can prepend suffix to global + // list. + for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark())); + oop suffix_tail = cur; + assert(suffix_tail != NULL && suffix_tail->mark() == NULL, + "Tautology"); + observed_overflow_list = _overflow_list; + do { + cur_overflow_list = observed_overflow_list; + if (cur_overflow_list != BUSY) { + // Do the splice ... + suffix_tail->set_mark(markOop(cur_overflow_list)); + } else { // cur_overflow_list == BUSY + suffix_tail->set_mark(NULL); + } + // ... and try to place spliced list back on overflow_list ... + observed_overflow_list = + (oop) Atomic::cmpxchg_ptr(suffix_head, &_overflow_list, cur_overflow_list); + } while (cur_overflow_list != observed_overflow_list); + // ... until we have succeeded in doing so. + } } // Push the prefix elements on work_q assert(prefix != NULL, "control point invariant"); const markOop proto = markOopDesc::prototype(); oop next; - NOT_PRODUCT(size_t n = 0;) + NOT_PRODUCT(ssize_t n = 0;) for (cur = prefix; cur != NULL; cur = next) { next = oop(cur->mark()); cur->set_mark(proto); // until proven otherwise @@ -8573,11 +8683,16 @@ void CMSCollector::par_push_on_overflow_list(oop p) { oop cur_overflow_list; do { cur_overflow_list = observed_overflow_list; - p->set_mark(markOop(cur_overflow_list)); + if (cur_overflow_list != BUSY) { + p->set_mark(markOop(cur_overflow_list)); + } else { + p->set_mark(NULL); + } observed_overflow_list = (oop) Atomic::cmpxchg_ptr(p, &_overflow_list, cur_overflow_list); } while (cur_overflow_list != observed_overflow_list); } +#undef BUSY // Single threaded // General Note on GrowableArray: pushes may silently fail @@ -8586,7 +8701,7 @@ void CMSCollector::par_push_on_overflow_list(oop p) { // a lot of code in the JVM. The prudent thing for GrowableArray // to do (for now) is to exit with an error. However, that may // be too draconian in some cases because the caller may be -// able to recover without much harm. For suych cases, we +// able to recover without much harm. For such cases, we // should probably introduce a "soft_push" method which returns // an indication of success or failure with the assumption that // the caller may be able to recover from a failure; code in @@ -8594,8 +8709,6 @@ void CMSCollector::par_push_on_overflow_list(oop p) { // failures where possible, thus, incrementally hardening the VM // in such low resource situations. void CMSCollector::preserve_mark_work(oop p, markOop m) { - int PreserveMarkStackSize = 128; - if (_preserved_oop_stack == NULL) { assert(_preserved_mark_stack == NULL, "bijection with preserved_oop_stack"); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index 44ef14e8db3..d36c6fc47df 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -595,7 +595,7 @@ class CMSCollector: public CHeapObj { size_t _ser_kac_preclean_ovflw; size_t _ser_kac_ovflw; size_t _par_kac_ovflw; - NOT_PRODUCT(size_t _num_par_pushes;) + NOT_PRODUCT(ssize_t _num_par_pushes;) // ("Weak") Reference processing support ReferenceProcessor* _ref_processor; @@ -1212,6 +1212,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // More iteration support virtual void oop_iterate(MemRegion mr, OopClosure* cl); virtual void oop_iterate(OopClosure* cl); + virtual void safe_object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl); // Need to declare the full complement of closures, whether we'll diff --git a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp index 60d8bf2057e..2c23680ced6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp @@ -24,7 +24,7 @@ // We need to sort heap regions by collection desirability. -class CSetChooserCache { +class CSetChooserCache VALUE_OBJ_CLASS_SPEC { private: enum { CacheLength = 16 diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp index ea9a997d7a6..1436e5a1c52 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp @@ -33,7 +33,7 @@ enum PostYieldAction { PYA_cancel // It's been completed by somebody else: cancel. }; -class ConcurrentG1Refine { +class ConcurrentG1Refine: public CHeapObj { ConcurrentG1RefineThread* _cg1rThread; volatile jint _pya; diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index a572f74f3a7..db4b4dfb834 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -30,7 +30,7 @@ typedef GenericTaskQueueSet CMTaskQueueSet; // A generic CM bit map. This is essentially a wrapper around the BitMap // class, with one bit per (1<<_shifter) HeapWords. -class CMBitMapRO { +class CMBitMapRO VALUE_OBJ_CLASS_SPEC { protected: HeapWord* _bmStartWord; // base address of range covered by map size_t _bmWordSize; // map size (in #HeapWords covered) @@ -139,7 +139,7 @@ class CMBitMap : public CMBitMapRO { // Represents a marking stack used by the CM collector. // Ideally this should be GrowableArray<> just like MSC's marking stack(s). -class CMMarkStack { +class CMMarkStack VALUE_OBJ_CLASS_SPEC { ConcurrentMark* _cm; oop* _base; // bottom of stack jint _index; // one more than last occupied index @@ -237,7 +237,7 @@ class CMMarkStack { void oops_do(OopClosure* f); }; -class CMRegionStack { +class CMRegionStack VALUE_OBJ_CLASS_SPEC { MemRegion* _base; jint _capacity; jint _index; @@ -312,7 +312,7 @@ typedef enum { class ConcurrentMarkThread; -class ConcurrentMark { +class ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; friend class CMTask; friend class CMBitMapClosure; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 3aa19ccb85d..1c6766b9947 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -141,7 +141,7 @@ YoungList::YoungList(G1CollectedHeap* g1h) _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL), _length(0), _scan_only_length(0), _last_sampled_rs_lengths(0), - _survivor_head(NULL), _survivors_tail(NULL), _survivor_length(0) + _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { guarantee( check_list_empty(false), "just making sure..." ); } @@ -159,16 +159,15 @@ void YoungList::push_region(HeapRegion *hr) { } void YoungList::add_survivor_region(HeapRegion* hr) { - assert(!hr->is_survivor(), "should not already be for survived"); + assert(hr->is_survivor(), "should be flagged as survivor region"); assert(hr->get_next_young_region() == NULL, "cause it should!"); hr->set_next_young_region(_survivor_head); if (_survivor_head == NULL) { - _survivors_tail = hr; + _survivor_tail = hr; } _survivor_head = hr; - hr->set_survivor(); ++_survivor_length; } @@ -239,7 +238,7 @@ void YoungList::empty_list() { empty_list(_survivor_head); _survivor_head = NULL; - _survivors_tail = NULL; + _survivor_tail = NULL; _survivor_length = 0; _last_sampled_rs_lengths = 0; @@ -391,6 +390,7 @@ YoungList::reset_auxilary_lists() { // Add survivor regions to SurvRateGroup. _g1h->g1_policy()->note_start_adding_survivor_regions(); + _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */); for (HeapRegion* curr = _survivor_head; curr != NULL; curr = curr->get_next_young_region()) { @@ -401,7 +401,7 @@ YoungList::reset_auxilary_lists() { if (_survivor_head != NULL) { _head = _survivor_head; _length = _survivor_length + _scan_only_length; - _survivors_tail->set_next_young_region(_scan_only_head); + _survivor_tail->set_next_young_region(_scan_only_head); } else { _head = _scan_only_head; _length = _scan_only_length; @@ -418,9 +418,9 @@ YoungList::reset_auxilary_lists() { _curr_scan_only = NULL; _survivor_head = NULL; - _survivors_tail = NULL; + _survivor_tail = NULL; _survivor_length = 0; - _g1h->g1_policy()->finished_recalculating_age_indexes(); + _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */); assert(check_list_well_formed(), "young list should be well formed"); } @@ -553,7 +553,7 @@ HeapRegion* G1CollectedHeap::newAllocRegionWithExpansion(int purpose, if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) { alloc_region = newAllocRegion_work(word_size, true, zero_filled); if (purpose == GCAllocForSurvived && alloc_region != NULL) { - _young_list->add_survivor_region(alloc_region); + alloc_region->set_survivor(); } ++_gc_alloc_region_counts[purpose]; } else { @@ -949,6 +949,10 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs, GCOverheadReporter::recordSTWEnd(end); g1_policy()->record_full_collection_end(); +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif + gc_epilogue(true); // Abandon concurrent refinement. This must happen last: in the @@ -1285,7 +1289,9 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _unclean_regions_coming(false), _young_list(new YoungList(this)), _gc_time_stamp(0), - _surviving_young_words(NULL) + _surviving_young_words(NULL), + _in_cset_fast_test(NULL), + _in_cset_fast_test_base(NULL) { _g1h = this; // To catch bugs. if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { @@ -2485,6 +2491,19 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { g1_policy()->record_collection_pause_start(start_time_sec, start_used_bytes); + guarantee(_in_cset_fast_test == NULL, "invariant"); + guarantee(_in_cset_fast_test_base == NULL, "invariant"); + _in_cset_fast_test_length = n_regions(); + _in_cset_fast_test_base = + NEW_C_HEAP_ARRAY(bool, _in_cset_fast_test_length); + memset(_in_cset_fast_test_base, false, + _in_cset_fast_test_length * sizeof(bool)); + // We're biasing _in_cset_fast_test to avoid subtracting the + // beginning of the heap every time we want to index; basically + // it's the same with what we do with the card table. + _in_cset_fast_test = _in_cset_fast_test_base - + ((size_t) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes); + #if SCAN_ONLY_VERBOSE _young_list->print(); #endif // SCAN_ONLY_VERBOSE @@ -2553,6 +2572,12 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { free_collection_set(g1_policy()->collection_set()); g1_policy()->clear_collection_set(); + FREE_C_HEAP_ARRAY(bool, _in_cset_fast_test_base); + // this is more for peace of mind; we're nulling them here and + // we're expecting them to be null at the beginning of the next GC + _in_cset_fast_test = NULL; + _in_cset_fast_test_base = NULL; + if (popular_region != NULL) { // We have to wait until now, because we don't want the region to // be rescheduled for pop-evac during RS update. @@ -2572,6 +2597,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { _young_list->print(); #endif // SCAN_ONLY_VERBOSE + g1_policy()->record_survivor_regions(_young_list->survivor_length(), + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); _young_list->reset_auxilary_lists(); } } else { @@ -2598,7 +2626,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { #endif // SCAN_ONLY_VERBOSE double end_time_sec = os::elapsedTime(); - g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); + if (!evacuation_failed()) { + g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0); + } GCOverheadReporter::recordSTWEnd(end_time_sec); g1_policy()->record_collection_pause_end(popular_region != NULL, abandoned); @@ -2621,8 +2651,13 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) { } } - if (mark_in_progress()) + if (mark_in_progress()) { concurrent_mark()->update_g1_committed(); + } + +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif gc_epilogue(false); } @@ -2733,6 +2768,13 @@ void G1CollectedHeap::forget_alloc_region_list() { _gc_alloc_region_list = r->next_gc_alloc_region(); r->set_next_gc_alloc_region(NULL); r->set_is_gc_alloc_region(false); + if (r->is_survivor()) { + if (r->is_empty()) { + r->set_not_young(); + } else { + _young_list->add_survivor_region(r); + } + } if (r->is_empty()) { ++_free_regions; } @@ -3129,6 +3171,20 @@ HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose, return block; } +void G1CollectedHeap::retire_alloc_region(HeapRegion* alloc_region, + bool par) { + // Another thread might have obtained alloc_region for the given + // purpose, and might be attempting to allocate in it, and might + // succeed. Therefore, we can't do the "finalization" stuff on the + // region below until we're sure the last allocation has happened. + // We ensure this by allocating the remaining space with a garbage + // object. + if (par) par_allocate_remaining_space(alloc_region); + // Now we can do the post-GC stuff on the region. + alloc_region->note_end_of_copying(); + g1_policy()->record_after_bytes(alloc_region->used()); +} + HeapWord* G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, HeapRegion* alloc_region, @@ -3146,16 +3202,7 @@ G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, // Otherwise, continue; this new region is empty, too. } assert(alloc_region != NULL, "We better have an allocation region"); - // Another thread might have obtained alloc_region for the given - // purpose, and might be attempting to allocate in it, and might - // succeed. Therefore, we can't do the "finalization" stuff on the - // region below until we're sure the last allocation has happened. - // We ensure this by allocating the remaining space with a garbage - // object. - if (par) par_allocate_remaining_space(alloc_region); - // Now we can do the post-GC stuff on the region. - alloc_region->note_end_of_copying(); - g1_policy()->record_after_bytes(alloc_region->used()); + retire_alloc_region(alloc_region, par); if (_gc_alloc_region_counts[purpose] >= g1_policy()->max_regions(purpose)) { // Cannot allocate more regions for the given purpose. @@ -3164,7 +3211,7 @@ G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, if (purpose != alt_purpose) { HeapRegion* alt_region = _gc_alloc_regions[alt_purpose]; // Has not the alternative region been aliased? - if (alloc_region != alt_region) { + if (alloc_region != alt_region && alt_region != NULL) { // Try to allocate in the alternative region. if (par) { block = alt_region->par_allocate(word_size); @@ -3173,9 +3220,10 @@ G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose, } // Make an alias. _gc_alloc_regions[purpose] = _gc_alloc_regions[alt_purpose]; - } - if (block != NULL) { - return block; + if (block != NULL) { + return block; + } + retire_alloc_region(alt_region, par); } // Both the allocation region and the alternative one are full // and aliased, replace them with a new allocation region. @@ -3476,6 +3524,7 @@ protected: OverflowQueue* _overflowed_refs; G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount]; + ageTable _age_table; size_t _alloc_buffer_waste; size_t _undo_waste; @@ -3517,6 +3566,7 @@ public: _refs(g1h->task_queue(queue_num)), _hash_seed(17), _queue_num(queue_num), _term_attempts(0), + _age_table(false), #if G1_DETAILED_STATS _pushes(0), _pops(0), _steals(0), _steal_attempts(0), _overflow_pushes(0), @@ -3551,8 +3601,9 @@ public: RefToScanQueue* refs() { return _refs; } OverflowQueue* overflowed_refs() { return _overflowed_refs; } + ageTable* age_table() { return &_age_table; } - inline G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { + G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) { return &_alloc_buffers[purpose]; } @@ -3560,6 +3611,9 @@ public: size_t undo_waste() { return _undo_waste; } void push_on_queue(oop* ref) { + assert(ref != NULL, "invariant"); + assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), "invariant"); + if (!refs()->push(ref)) { overflowed_refs()->push(ref); IF_G1_DETAILED_STATS(note_overflow_push()); @@ -3572,6 +3626,10 @@ public: if (!refs()->pop_local(ref)) { ref = NULL; } else { + assert(ref != NULL, "invariant"); + assert(has_partial_array_mask(ref) || _g1h->obj_in_cs(*ref), + "invariant"); + IF_G1_DETAILED_STATS(note_pop()); } } @@ -3601,8 +3659,7 @@ public: obj = alloc_buf->allocate(word_sz); assert(obj != NULL, "buffer was definitely big enough..."); - } - else { + } else { obj = _g1h->par_allocate_during_gc(purpose, word_sz); } return obj; @@ -3695,24 +3752,57 @@ public: } } +private: + void deal_with_reference(oop* ref_to_scan) { + if (has_partial_array_mask(ref_to_scan)) { + _partial_scan_cl->do_oop_nv(ref_to_scan); + } else { + // Note: we can use "raw" versions of "region_containing" because + // "obj_to_scan" is definitely in the heap, and is not in a + // humongous region. + HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); + _evac_cl->set_region(r); + _evac_cl->do_oop_nv(ref_to_scan); + } + } + +public: void trim_queue() { + // I've replicated the loop twice, first to drain the overflow + // queue, second to drain the task queue. This is better than + // having a single loop, which checks both conditions and, inside + // it, either pops the overflow queue or the task queue, as each + // loop is tighter. Also, the decision to drain the overflow queue + // first is not arbitrary, as the overflow queue is not visible + // to the other workers, whereas the task queue is. So, we want to + // drain the "invisible" entries first, while allowing the other + // workers to potentially steal the "visible" entries. + while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) { - oop *ref_to_scan = NULL; - if (overflowed_refs_to_scan() == 0) { - pop_from_queue(ref_to_scan); - } else { + while (overflowed_refs_to_scan() > 0) { + oop *ref_to_scan = NULL; pop_from_overflow_queue(ref_to_scan); + assert(ref_to_scan != NULL, "invariant"); + // We shouldn't have pushed it on the queue if it was not + // pointing into the CSet. + assert(ref_to_scan != NULL, "sanity"); + assert(has_partial_array_mask(ref_to_scan) || + _g1h->obj_in_cs(*ref_to_scan), "sanity"); + + deal_with_reference(ref_to_scan); } - if (ref_to_scan != NULL) { - if ((intptr_t)ref_to_scan & G1_PARTIAL_ARRAY_MASK) { - _partial_scan_cl->do_oop_nv(ref_to_scan); - } else { - // Note: we can use "raw" versions of "region_containing" because - // "obj_to_scan" is definitely in the heap, and is not in a - // humongous region. - HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan); - _evac_cl->set_region(r); - _evac_cl->do_oop_nv(ref_to_scan); + + while (refs_to_scan() > 0) { + oop *ref_to_scan = NULL; + pop_from_queue(ref_to_scan); + + if (ref_to_scan != NULL) { + // We shouldn't have pushed it on the queue if it was not + // pointing into the CSet. + assert(has_partial_array_mask(ref_to_scan) || + _g1h->obj_in_cs(*ref_to_scan), "sanity"); + + deal_with_reference(ref_to_scan); } } } @@ -3728,16 +3818,25 @@ G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* // Should probably be made inline and moved in g1OopClosures.inline.hpp. void G1ParScanClosure::do_oop_nv(oop* p) { oop obj = *p; + if (obj != NULL) { - if (_g1->obj_in_cs(obj)) { - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - _par_scan_state->push_on_queue(p); - return; - } + if (_g1->in_cset_fast_test(obj)) { + // We're not going to even bother checking whether the object is + // already forwarded or not, as this usually causes an immediate + // stall. We'll try to prefetch the object (for write, given that + // we might need to install the forwarding reference) and we'll + // get back to it when pop it from the queue + Prefetch::write(obj->mark_addr(), 0); + Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); + + // slightly paranoid test; I'm trying to catch potential + // problems before we go into push_on_queue to know where the + // problem is coming from + assert(obj == *p, "the value of *p should not have changed"); + _par_scan_state->push_on_queue(p); + } else { + _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); } - _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); } } @@ -3765,7 +3864,9 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { (!from_region->is_young() && young_index == 0), "invariant" ); G1CollectorPolicy* g1p = _g1->g1_policy(); markOop m = old->mark(); - GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, m->age(), + int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() + : m->age(); + GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, word_sz); HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); oop obj = oop(obj_ptr); @@ -3777,13 +3878,39 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { return _g1->handle_evacuation_failure_par(cl, old); } + // We're going to allocate linearly, so might as well prefetch ahead. + Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); + oop forward_ptr = old->forward_to_atomic(obj); if (forward_ptr == NULL) { Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz); - obj->set_mark(m); if (g1p->track_object_age(alloc_purpose)) { - obj->incr_age(); + // We could simply do obj->incr_age(). However, this causes a + // performance issue. obj->incr_age() will first check whether + // the object has a displaced mark by checking its mark word; + // getting the mark word from the new location of the object + // stalls. So, given that we already have the mark word and we + // are about to install it anyway, it's better to increase the + // age on the mark word, when the object does not have a + // displaced mark word. We're not expecting many objects to have + // a displaced marked word, so that case is not optimized + // further (it could be...) and we simply call obj->incr_age(). + + if (m->has_displaced_mark_helper()) { + // in this case, we have to install the mark word first, + // otherwise obj looks to be forwarded (the old mark word, + // which contains the forward pointer, was copied) + obj->set_mark(m); + obj->incr_age(); + } else { + m = m->incr_age(); + obj->set_mark(m); + } + _par_scan_state->age_table()->add(obj, word_sz); + } else { + obj->set_mark(m); } + // preserve "next" mark bit if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { if (!use_local_bitmaps || @@ -3805,9 +3932,11 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { arrayOop(old)->set_length(0); - _par_scan_state->push_on_queue((oop*) ((intptr_t)old | G1_PARTIAL_ARRAY_MASK)); + _par_scan_state->push_on_queue(set_partial_array_mask(old)); } else { - _scanner->set_region(_g1->heap_region_containing(obj)); + // No point in using the slower heap_region_containing() method, + // given that we know obj is in the heap. + _scanner->set_region(_g1->heap_region_containing_raw(obj)); obj->oop_iterate_backwards(_scanner); } } else { @@ -3817,47 +3946,55 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { return obj; } -template -void G1ParCopyClosure::do_oop_work(oop* p) { +template +void G1ParCopyClosure::do_oop_work(oop* p) { oop obj = *p; assert(barrier != G1BarrierRS || obj != NULL, "Precondition: G1BarrierRS implies obj is nonNull"); - if (obj != NULL) { - if (_g1->obj_in_cs(obj)) { + // The only time we skip the cset test is when we're scanning + // references popped from the queue. And we only push on the queue + // references that we know point into the cset, so no point in + // checking again. But we'll leave an assert here for peace of mind. + assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant"); + + // here the null check is implicit in the cset_fast_test() test + if (skip_cset_test || _g1->in_cset_fast_test(obj)) { #if G1_REM_SET_LOGGING - gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" into CS.", - p, (void*) obj); + gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" " + "into CS.", p, (void*) obj); #endif - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - *p = copy_to_survivor_space(obj); - } - // When scanning the RS, we only care about objs in CS. - if (barrier == G1BarrierRS) { - _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); - } + if (obj->is_forwarded()) { + *p = obj->forwardee(); + } else { + *p = copy_to_survivor_space(obj); } - // When scanning moved objs, must look at all oops. - if (barrier == G1BarrierEvac) { + // When scanning the RS, we only care about objs in CS. + if (barrier == G1BarrierRS) { _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); } + } - if (do_gen_barrier) { - par_do_barrier(p); - } + // When scanning moved objs, must look at all oops. + if (barrier == G1BarrierEvac && obj != NULL) { + _g1_rem->par_write_ref(_from, p, _par_scan_state->queue_num()); + } + + if (do_gen_barrier && obj != NULL) { + par_do_barrier(p); } } -template void G1ParCopyClosure::do_oop_work(oop* p); +template void G1ParCopyClosure::do_oop_work(oop* p); -template void G1ParScanPartialArrayClosure::process_array_chunk( +template void G1ParScanPartialArrayClosure::process_array_chunk( oop obj, int start, int end) { // process our set of indices (include header in first chunk) assert(start < end, "invariant"); T* const base = (T*)objArrayOop(obj)->base(); - T* const start_addr = base + start; + T* const start_addr = (start == 0) ? (T*) obj : base + start; T* const end_addr = base + end; MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); _scanner.set_region(_g1->heap_region_containing(obj)); @@ -3866,7 +4003,8 @@ template void G1ParScanPartialArrayClosure::process_array_chunk( void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) { assert(!UseCompressedOops, "Needs to be fixed to work with compressed oops"); - oop old = oop((intptr_t)p & ~G1_PARTIAL_ARRAY_MASK); + assert(has_partial_array_mask(p), "invariant"); + oop old = clear_partial_array_mask(p); assert(old->is_objArray(), "must be obj array"); assert(old->is_forwarded(), "must be forwarded"); assert(Universe::heap()->is_in_reserved(old), "must be in heap."); @@ -3884,7 +4022,7 @@ void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) { end = start + ParGCArrayScanChunk; arrayOop(old)->set_length(end); // Push remainder. - _par_scan_state->push_on_queue((oop*) ((intptr_t) old | G1_PARTIAL_ARRAY_MASK)); + _par_scan_state->push_on_queue(set_partial_array_mask(old)); } else { // Restore length so that the heap remains parsable in // case of evacuation failure. @@ -3893,11 +4031,6 @@ void G1ParScanPartialArrayClosure::do_oop_nv(oop* p) { // process our set of indices (include header in first chunk) process_array_chunk(obj, start, end); - oop* start_addr = start == 0 ? (oop*)obj : obj->obj_at_addr(start); - oop* end_addr = (oop*)(obj->base()) + end; // obj_at_addr(end) asserts end < length - MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); - _scanner.set_region(_g1->heap_region_containing(obj)); - obj->oop_iterate(&_scanner, mr); } int G1ScanAndBalanceClosure::_nq = 0; @@ -3931,6 +4064,13 @@ public: pss->hash_seed(), ref_to_scan)) { IF_G1_DETAILED_STATS(pss->note_steal()); + + // slightly paranoid tests; I'm trying to catch potential + // problems before we go into push_on_queue to know where the + // problem is coming from + assert(ref_to_scan != NULL, "invariant"); + assert(has_partial_array_mask(ref_to_scan) || + _g1h->obj_in_cs(*ref_to_scan), "invariant"); pss->push_on_queue(ref_to_scan); continue; } @@ -3976,10 +4116,10 @@ public: ResourceMark rm; HandleMark hm; - G1ParScanThreadState pss(_g1h, i); - G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); - G1ParScanHeapEvacClosure evac_failure_cl(_g1h, &pss); - G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); + G1ParScanThreadState pss(_g1h, i); + G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss); + G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss); + G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss); pss.set_evac_closure(&scan_evac_cl); pss.set_evac_failure_closure(&evac_failure_cl); @@ -4024,6 +4164,9 @@ public: _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms); _g1h->g1_policy()->record_termination_time(i, term_ms); } + if (G1UseSurvivorSpace) { + _g1h->g1_policy()->record_thread_age_table(pss.age_table()); + } _g1h->update_surviving_young_words(pss.surviving_young_words()+1); // Clean up any par-expanded rem sets. @@ -4263,7 +4406,7 @@ void G1CollectedHeap::evacuate_collection_set() { // Is this the right thing to do here? We don't save marks // on individual heap regions when we allocate from // them in parallel, so this seems like the correct place for this. - all_alloc_regions_note_end_of_copying(); + retire_all_alloc_regions(); { G1IsAliveClosure is_alive(this); G1KeepAliveClosure keep_alive(this); @@ -4903,7 +5046,7 @@ bool G1CollectedHeap::all_alloc_regions_no_allocs_since_save_marks() { return no_allocs; } -void G1CollectedHeap::all_alloc_regions_note_end_of_copying() { +void G1CollectedHeap::retire_all_alloc_regions() { for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { HeapRegion* r = _gc_alloc_regions[ap]; if (r != NULL) { @@ -4916,8 +5059,7 @@ void G1CollectedHeap::all_alloc_regions_note_end_of_copying() { } } if (!has_processed_alias) { - r->note_end_of_copying(); - g1_policy()->record_after_bytes(r->used()); + retire_alloc_region(r, false /* par */); } } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index e83b1a7de1c..2e139b7f2d2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -90,7 +90,7 @@ private: HeapRegion* _curr_scan_only; HeapRegion* _survivor_head; - HeapRegion* _survivors_tail; + HeapRegion* _survivor_tail; size_t _survivor_length; void empty_list(HeapRegion* list); @@ -105,6 +105,7 @@ public: bool is_empty() { return _length == 0; } size_t length() { return _length; } size_t scan_only_length() { return _scan_only_length; } + size_t survivor_length() { return _survivor_length; } void rs_length_sampling_init(); bool rs_length_sampling_more(); @@ -120,6 +121,7 @@ public: HeapRegion* first_region() { return _head; } HeapRegion* first_scan_only_region() { return _scan_only_head; } HeapRegion* first_survivor_region() { return _survivor_head; } + HeapRegion* last_survivor_region() { return _survivor_tail; } HeapRegion* par_get_next_scan_only_region() { MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); HeapRegion* ret = _curr_scan_only; @@ -219,7 +221,7 @@ private: // The to-space memory regions into which objects are being copied during // a GC. HeapRegion* _gc_alloc_regions[GCAllocPurposeCount]; - uint _gc_alloc_region_counts[GCAllocPurposeCount]; + size_t _gc_alloc_region_counts[GCAllocPurposeCount]; // A list of the regions that have been set to be alloc regions in the // current collection. @@ -247,6 +249,27 @@ private: NumberSeq _pop_obj_rc_at_copy; void print_popularity_summary_info() const; + // This is used for a quick test on whether a reference points into + // the collection set or not. Basically, we have an array, with one + // byte per region, and that byte denotes whether the corresponding + // region is in the collection set or not. The entry corresponding + // the bottom of the heap, i.e., region 0, is pointed to by + // _in_cset_fast_test_base. The _in_cset_fast_test field has been + // biased so that it actually points to address 0 of the address + // space, to make the test as fast as possible (we can simply shift + // the address to address into it, instead of having to subtract the + // bottom of the heap from the address before shifting it; basically + // it works in the same way the card table works). + bool* _in_cset_fast_test; + + // The allocated array used for the fast test on whether a reference + // points into the collection set or not. This field is also used to + // free the array. + bool* _in_cset_fast_test_base; + + // The length of the _in_cset_fast_test_base array. + size_t _in_cset_fast_test_length; + volatile unsigned _gc_time_stamp; size_t* _surviving_young_words; @@ -260,8 +283,8 @@ protected: // Returns "true" iff none of the gc alloc regions have any allocations // since the last call to "save_marks". bool all_alloc_regions_no_allocs_since_save_marks(); - // Calls "note_end_of_copying on all gc alloc_regions. - void all_alloc_regions_note_end_of_copying(); + // Perform finalization stuff on all allocation regions. + void retire_all_alloc_regions(); // The number of regions allocated to hold humongous objects. int _num_humongous_regions; @@ -330,6 +353,10 @@ protected: // that parallel threads might be attempting allocations. void par_allocate_remaining_space(HeapRegion* r); + // Retires an allocation region when it is full or at the end of a + // GC pause. + void retire_alloc_region(HeapRegion* alloc_region, bool par); + // Helper function for two callbacks below. // "full", if true, indicates that the GC is for a System.gc() request, // and should collect the entire heap. If "clear_all_soft_refs" is true, @@ -368,6 +395,38 @@ public: virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); + // We register a region with the fast "in collection set" test. We + // simply set to true the array slot corresponding to this region. + void register_region_with_in_cset_fast_test(HeapRegion* r) { + assert(_in_cset_fast_test_base != NULL, "sanity"); + assert(r->in_collection_set(), "invariant"); + int index = r->hrs_index(); + assert(0 <= (size_t) index && (size_t) index < _in_cset_fast_test_length, + "invariant"); + assert(!_in_cset_fast_test_base[index], "invariant"); + _in_cset_fast_test_base[index] = true; + } + + // This is a fast test on whether a reference points into the + // collection set or not. It does not assume that the reference + // points into the heap; if it doesn't, it will return false. + bool in_cset_fast_test(oop obj) { + assert(_in_cset_fast_test != NULL, "sanity"); + if (_g1_committed.contains((HeapWord*) obj)) { + // no need to subtract the bottom of the heap from obj, + // _in_cset_fast_test is biased + size_t index = ((size_t) obj) >> HeapRegion::LogOfHRGrainBytes; + bool ret = _in_cset_fast_test[index]; + // let's make sure the result is consistent with what the slower + // test returns + assert( ret || !obj_in_cs(obj), "sanity"); + assert(!ret || obj_in_cs(obj), "sanity"); + return ret; + } else { + return false; + } + } + protected: // Shrink the garbage-first heap by at most the given size (in bytes!). @@ -850,6 +909,7 @@ public: // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl); + virtual void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } // Iterate over all objects allocated since the last collection, calling // "cl.do_object" on each. The heap must have been initialized properly diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index 8cafe3d9885..4d88ee4cbb6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -36,8 +36,11 @@ G1CollectedHeap::heap_region_containing(const void* addr) const { inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const void* addr) const { - HeapRegion* res = _hrs->addr_to_region(addr); - assert(res != NULL, "addr outside of heap?"); + assert(_g1_reserved.contains(addr), "invariant"); + size_t index = ((intptr_t) addr - (intptr_t) _g1_reserved.start()) + >> HeapRegion::LogOfHRGrainBytes; + HeapRegion* res = _hrs->at(index); + assert(res == _hrs->addr_to_region(addr), "sanity"); return res; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index a5d0165bb4d..949e3f99700 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -196,8 +196,13 @@ G1CollectorPolicy::G1CollectorPolicy() : _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived", G1YoungSurvRateNumRegionsSummary)), _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor", - G1YoungSurvRateNumRegionsSummary)) + G1YoungSurvRateNumRegionsSummary)), // add here any more surv rate groups + _recorded_survivor_regions(0), + _recorded_survivor_head(NULL), + _recorded_survivor_tail(NULL), + _survivors_age_table(true) + { _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; @@ -272,6 +277,15 @@ G1CollectorPolicy::G1CollectorPolicy() : _concurrent_mark_cleanup_times_ms->add(0.20); _tenuring_threshold = MaxTenuringThreshold; + if (G1UseSurvivorSpace) { + // if G1FixedSurvivorSpaceSize is 0 which means the size is not + // fixed, then _max_survivor_regions will be calculated at + // calculate_young_list_target_config during initialization + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; + } else { + _max_survivor_regions = 0; + } + initialize_all(); } @@ -283,6 +297,9 @@ static void inc_mod(int& i, int len) { void G1CollectorPolicy::initialize_flags() { set_min_alignment(HeapRegion::GrainBytes); set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name())); + if (SurvivorRatio < 1) { + vm_exit_during_initialization("Invalid survivor ratio specified"); + } CollectorPolicy::initialize_flags(); } @@ -301,6 +318,8 @@ void G1CollectorPolicy::init() { "-XX:+UseConcMarkSweepGC."); } + initialize_gc_policy_counters(); + if (G1Gen) { _in_young_gc_mode = true; @@ -322,6 +341,12 @@ void G1CollectorPolicy::init() { } } +// Create the jstat counters for the policy. +void G1CollectorPolicy::initialize_gc_policy_counters() +{ + _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 2 + G1Gen); +} + void G1CollectorPolicy::calculate_young_list_min_length() { _young_list_min_length = 0; @@ -352,6 +377,7 @@ void G1CollectorPolicy::calculate_young_list_target_config() { guarantee( so_length < _young_list_target_length, "invariant" ); _young_list_so_prefix_length = so_length; } + calculate_survivors_policy(); } // This method calculate the optimal scan-only set for a fixed young @@ -448,6 +474,9 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { // we are in fully-young mode and there are free regions in the heap + double survivor_regions_evac_time = + predict_survivor_regions_evac_time(); + size_t min_so_length = 0; size_t max_so_length = 0; @@ -497,9 +526,8 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { scanned_cards = predict_non_young_card_num(adj_rs_lengths); // calculate this once, so that we don't have to recalculate it in // the innermost loop - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, - scanned_cards); - + double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) + + survivor_regions_evac_time; // the result size_t final_young_length = 0; size_t final_so_length = 0; @@ -548,14 +576,14 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { bool done = false; // this is the outermost loop while (!done) { -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr("searching between " SIZE_FORMAT " and " SIZE_FORMAT ", incr " SIZE_FORMAT ", pass %s", from_so_length, to_so_length, so_length_incr, (pass == pass_type_coarse) ? "coarse" : (pass == pass_type_fine) ? "fine" : "final"); -#endif // 0 +#endif // TRACE_CALC_YOUNG_CONFIG size_t so_length = from_so_length; size_t init_free_regions = @@ -651,11 +679,11 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { guarantee( so_length_incr == so_coarse_increments, "invariant" ); guarantee( final_so_length >= min_so_length, "invariant" ); -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr(" coarse pass: SO length " SIZE_FORMAT, final_so_length); -#endif // 0 +#endif // TRACE_CALC_YOUNG_CONFIG from_so_length = (final_so_length - min_so_length > so_coarse_increments) ? @@ -687,12 +715,12 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { // of the optimal size_t new_so_length = 950 * final_so_length / 1000; -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr(" fine pass: SO length " SIZE_FORMAT ", setting it to " SIZE_FORMAT, final_so_length, new_so_length); -#endif // 0 +#endif // TRACE_CALC_YOUNG_CONFIG from_so_length = new_so_length; to_so_length = new_so_length; @@ -719,7 +747,8 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { } // we should have at least one region in the target young length - _young_list_target_length = MAX2((size_t) 1, final_young_length); + _young_list_target_length = + MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); if (final_so_length >= final_young_length) // and we need to ensure that the S-O length is not greater than // the target young length (this is being a bit careful) @@ -734,7 +763,7 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { double end_time_sec = os::elapsedTime(); double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT ", SO = " SIZE_FORMAT ", " @@ -747,9 +776,9 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { calculations, full_young_gcs() ? "full" : "partial", should_initiate_conc_mark() ? " i-m" : "", - in_marking_window(), - in_marking_window_im()); -#endif // 0 + _in_marking_window, + _in_marking_window_im); +#endif // TRACE_CALC_YOUNG_CONFIG if (_young_list_target_length < _young_list_min_length) { // bummer; this means that, if we do a pause when the optimal @@ -768,14 +797,14 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { // S-O length so_length = calculate_optimal_so_length(_young_list_min_length); -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr("adjusted target length from " SIZE_FORMAT " to " SIZE_FORMAT ", SO " SIZE_FORMAT, _young_list_target_length, _young_list_min_length, so_length); -#endif // 0 +#endif // TRACE_CALC_YOUNG_CONFIG _young_list_target_length = MAX2(_young_list_min_length, (size_t)1); @@ -785,12 +814,12 @@ void G1CollectorPolicy::calculate_young_list_target_config(size_t rs_lengths) { // we are in a partially-young mode or we've run out of regions (due // to evacuation failure) -#if 0 +#ifdef TRACE_CALC_YOUNG_CONFIG // leave this in for debugging, just in case gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT ", SO " SIZE_FORMAT, _young_list_min_length, 0); -#endif // 0 +#endif // TRACE_CALC_YOUNG_CONFIG // we'll do the pause as soon as possible and with no S-O prefix // (see above for the reasons behind the latter) @@ -884,6 +913,16 @@ G1CollectorPolicy::predict_gc_eff(size_t young_length, return true; } +double G1CollectorPolicy::predict_survivor_regions_evac_time() { + double survivor_regions_evac_time = 0.0; + for (HeapRegion * r = _recorded_survivor_head; + r != NULL && r != _recorded_survivor_tail->get_next_young_region(); + r = r->get_next_young_region()) { + survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true); + } + return survivor_regions_evac_time; +} + void G1CollectorPolicy::check_prediction_validity() { guarantee( adaptive_young_list_length(), "should not call this otherwise" ); @@ -995,11 +1034,15 @@ void G1CollectorPolicy::record_full_collection_end() { _short_lived_surv_rate_group->start_adding_regions(); // also call this on any additional surv rate groups + record_survivor_regions(0, NULL, NULL); + _prev_region_num_young = _region_num_young; _prev_region_num_tenured = _region_num_tenured; _free_regions_at_end_of_collection = _g1->free_regions(); _scan_only_regions_at_end_of_collection = 0; + // Reset survivors SurvRateGroup. + _survivor_surv_rate_group->reset(); calculate_young_list_min_length(); calculate_young_list_target_config(); } @@ -1104,6 +1147,10 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length); tag_scan_only(short_lived_so_length); + if (G1UseSurvivorSpace) { + _survivors_age_table.clear(); + } + assert( verify_young_ages(), "region age verification" ); } @@ -1965,9 +2012,6 @@ void G1CollectorPolicy::record_collection_pause_end(bool popular, // _target_pause_time_ms = -1.0; - - // TODO: calculate tenuring threshold - _tenuring_threshold = MaxTenuringThreshold; } // @@ -2058,7 +2102,7 @@ G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) { guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant" ); int age = hr->age_in_surv_rate_group(); - double yg_surv_rate = predict_yg_surv_rate(age); + double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate); } @@ -2091,7 +2135,7 @@ G1CollectorPolicy::record_cset_region(HeapRegion* hr, bool young) { } #if PREDICTIONS_VERBOSE if (young) { - _recorded_young_bytes += hr->asSpace()->used(); + _recorded_young_bytes += hr->used(); } else { _recorded_marked_bytes += hr->max_live_bytes(); } @@ -2119,11 +2163,6 @@ G1CollectorPolicy::end_recording_regions() { predict_non_young_card_num(_predicted_rs_lengths); _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions; - _predicted_young_survival_ratio = 0.0; - for (int i = 0; i < _recorded_young_regions; ++i) - _predicted_young_survival_ratio += predict_yg_surv_rate(i); - _predicted_young_survival_ratio /= (double) _recorded_young_regions; - _predicted_scan_only_scan_time_ms = predict_scan_only_time_ms(_recorded_scan_only_regions); _predicted_rs_update_time_ms = @@ -2673,8 +2712,11 @@ G1CollectorPolicy::should_add_next_region_to_young_list() { assert(in_young_gc_mode(), "should be in young GC mode"); bool ret; size_t young_list_length = _g1->young_list_length(); - - if (young_list_length < _young_list_target_length) { + size_t young_list_max_length = _young_list_target_length; + if (G1FixedEdenSize) { + young_list_max_length -= _max_survivor_regions; + } + if (young_list_length < young_list_max_length) { ret = true; ++_region_num_young; } else { @@ -2710,17 +2752,39 @@ G1CollectorPolicy::checkpoint_conc_overhead() { } -uint G1CollectorPolicy::max_regions(int purpose) { +size_t G1CollectorPolicy::max_regions(int purpose) { switch (purpose) { case GCAllocForSurvived: - return G1MaxSurvivorRegions; + return _max_survivor_regions; case GCAllocForTenured: - return UINT_MAX; + return REGIONS_UNLIMITED; default: - return UINT_MAX; + ShouldNotReachHere(); + return REGIONS_UNLIMITED; }; } +// Calculates survivor space parameters. +void G1CollectorPolicy::calculate_survivors_policy() +{ + if (!G1UseSurvivorSpace) { + return; + } + if (G1FixedSurvivorSpaceSize == 0) { + _max_survivor_regions = _young_list_target_length / SurvivorRatio; + } else { + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; + } + + if (G1FixedTenuringThreshold) { + _tenuring_threshold = MaxTenuringThreshold; + } else { + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( + HeapRegion::GrainWords * _max_survivor_regions); + } +} + + void G1CollectorPolicy_BestRegionsFirst:: set_single_region_collection_set(HeapRegion* hr) { @@ -2743,7 +2807,11 @@ G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; size_t young_list_length = _g1->young_list_length(); - bool reached_target_length = young_list_length >= _young_list_target_length; + size_t young_list_max_length = _young_list_target_length; + if (G1FixedEdenSize) { + young_list_max_length -= _max_survivor_regions; + } + bool reached_target_length = young_list_length >= young_list_max_length; if (in_young_gc_mode()) { if (reached_target_length) { @@ -2985,6 +3053,7 @@ add_to_collection_set(HeapRegion* hr) { _collection_set = hr; _collection_set_size++; _collection_set_bytes_used_before += hr->used(); + _g1->register_region_with_in_cset_fast_test(hr); } void diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 110f81fef0e..1649584cd31 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -49,7 +49,7 @@ public: \ class MainBodySummary; class PopPreambleSummary; -class PauseSummary { +class PauseSummary: public CHeapObj { define_num_seq(total) define_num_seq(other) @@ -58,7 +58,7 @@ public: virtual PopPreambleSummary* pop_preamble_summary() { return NULL; } }; -class MainBodySummary { +class MainBodySummary: public CHeapObj { define_num_seq(satb_drain) // optional define_num_seq(parallel) // parallel only define_num_seq(ext_root_scan) @@ -75,7 +75,7 @@ class MainBodySummary { define_num_seq(clear_ct) // parallel only }; -class PopPreambleSummary { +class PopPreambleSummary: public CHeapObj { define_num_seq(pop_preamble) define_num_seq(pop_update_rs) define_num_seq(pop_scan_rs) @@ -557,6 +557,8 @@ public: return get_new_neg_prediction(_young_gc_eff_seq); } + double predict_survivor_regions_evac_time(); + // public: @@ -599,8 +601,8 @@ public: // Returns an estimate of the survival rate of the region at yg-age // "yg_age". - double predict_yg_surv_rate(int age) { - TruncatedSeq* seq = _short_lived_surv_rate_group->get_seq(age); + double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) { + TruncatedSeq* seq = surv_rate_group->get_seq(age); if (seq->num() == 0) gclog_or_tty->print("BARF! age is %d", age); guarantee( seq->num() > 0, "invariant" ); @@ -610,6 +612,10 @@ public: return pred; } + double predict_yg_surv_rate(int age) { + return predict_yg_surv_rate(age, _short_lived_surv_rate_group); + } + double accum_yg_surv_rate_pred(int age) { return _short_lived_surv_rate_group->accum_surv_rate_pred(age); } @@ -822,6 +828,9 @@ public: virtual void init(); + // Create jstat counters for the policy. + virtual void initialize_gc_policy_counters(); + virtual HeapWord* mem_allocate_work(size_t size, bool is_tlab, bool* gc_overhead_limit_was_exceeded); @@ -1047,8 +1056,12 @@ public: // Print stats on young survival ratio void print_yg_surv_rate_info() const; - void finished_recalculating_age_indexes() { - _short_lived_surv_rate_group->finished_recalculating_age_indexes(); + void finished_recalculating_age_indexes(bool is_survivors) { + if (is_survivors) { + _survivor_surv_rate_group->finished_recalculating_age_indexes(); + } else { + _short_lived_surv_rate_group->finished_recalculating_age_indexes(); + } // do that for any other surv rate groups } @@ -1097,6 +1110,17 @@ protected: // maximum amount of suvivors regions. int _tenuring_threshold; + // The limit on the number of regions allocated for survivors. + size_t _max_survivor_regions; + + // The amount of survor regions after a collection. + size_t _recorded_survivor_regions; + // List of survivor regions. + HeapRegion* _recorded_survivor_head; + HeapRegion* _recorded_survivor_tail; + + ageTable _survivors_age_table; + public: inline GCAllocPurpose @@ -1116,7 +1140,9 @@ public: return GCAllocForTenured; } - uint max_regions(int purpose); + static const size_t REGIONS_UNLIMITED = ~(size_t)0; + + size_t max_regions(int purpose); // The limit on regions for a particular purpose is reached. void note_alloc_region_limit_reached(int purpose) { @@ -1132,6 +1158,23 @@ public: void note_stop_adding_survivor_regions() { _survivor_surv_rate_group->stop_adding_regions(); } + + void record_survivor_regions(size_t regions, + HeapRegion* head, + HeapRegion* tail) { + _recorded_survivor_regions = regions; + _recorded_survivor_head = head; + _recorded_survivor_tail = tail; + } + + void record_thread_age_table(ageTable* age_table) + { + _survivors_age_table.merge_par(age_table); + } + + // Calculates survivor space parameters. + void calculate_survivors_policy(); + }; // This encapsulates a particular strategy for a g1 Collector. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp index 88a3707626b..8eb83a8bef6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp @@ -28,7 +28,7 @@ /***** ALL TIMES ARE IN SECS!!!!!!! *****/ // this is the "interface" -class G1MMUTracker { +class G1MMUTracker: public CHeapObj { protected: double _time_slice; double _max_gc_time; // this is per time slice @@ -67,7 +67,7 @@ public: } }; -class G1MMUTrackerQueueElem { +class G1MMUTrackerQueueElem VALUE_OBJ_CLASS_SPEC { private: double _start_time; double _end_time; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 58653196a36..2791bf6ee6b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -77,6 +77,18 @@ public: #define G1_PARTIAL_ARRAY_MASK 1 +inline bool has_partial_array_mask(oop* ref) { + return (intptr_t) ref & G1_PARTIAL_ARRAY_MASK; +} + +inline oop* set_partial_array_mask(oop obj) { + return (oop*) ((intptr_t) obj | G1_PARTIAL_ARRAY_MASK); +} + +inline oop clear_partial_array_mask(oop* ref) { + return oop((intptr_t) ref & ~G1_PARTIAL_ARRAY_MASK); +} + class G1ParScanPartialArrayClosure : public G1ParClosureSuper { G1ParScanClosure _scanner; template void process_array_chunk(oop obj, int start, int end); @@ -101,7 +113,8 @@ public: G1ParClosureSuper(g1, par_scan_state), _scanner(scanner) { } }; -template +template class G1ParCopyClosure : public G1ParCopyHelper { G1ParScanClosure _scanner; void do_oop_work(oop* p); @@ -119,14 +132,22 @@ public: virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; -typedef G1ParCopyClosure G1ParScanExtRootClosure; -typedef G1ParCopyClosure G1ParScanPermClosure; -typedef G1ParCopyClosure G1ParScanAndMarkExtRootClosure; -typedef G1ParCopyClosure G1ParScanAndMarkPermClosure; -typedef G1ParCopyClosure G1ParScanHeapRSClosure; -typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; -typedef G1ParCopyClosure G1ParScanHeapEvacClosure; - +typedef G1ParCopyClosure G1ParScanExtRootClosure; +typedef G1ParCopyClosure G1ParScanPermClosure; +typedef G1ParCopyClosure G1ParScanAndMarkExtRootClosure; +typedef G1ParCopyClosure G1ParScanAndMarkPermClosure; +typedef G1ParCopyClosure G1ParScanHeapRSClosure; +typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; +// This is the only case when we set skip_cset_test. Basically, this +// closure is (should?) only be called directly while we're draining +// the overflow and task queues. In that case we know that the +// reference in question points into the collection set, otherwise we +// would not have pushed it on the queue. +typedef G1ParCopyClosure G1ParScanHeapEvacClosure; +// We need a separate closure to handle references during evacuation +// failure processing, as it cannot asume that the reference already + // points to the collection set (like G1ParScanHeapEvacClosure does). +typedef G1ParCopyClosure G1ParScanHeapEvacFailureClosure; class FilterIntoCSClosure: public OopClosure { G1CollectedHeap* _g1; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 462be9a689e..7946c41ff79 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -572,6 +572,9 @@ prepare_for_oops_into_collection_set_do() { } guarantee( _cards_scanned == NULL, "invariant" ); _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers()); + for (uint i = 0; i < n_workers(); ++i) { + _cards_scanned[i] = 0; + } _total_cards_scanned = 0; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp index a07ba882a2c..9f03d394db2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp @@ -30,7 +30,7 @@ class CardTableModRefBarrierSet; class HRInto_G1RemSet; class ConcurrentG1Refine; -class G1RemSet { +class G1RemSet: public CHeapObj { protected: G1CollectedHeap* _g1; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 72a684812d5..43b1d59c852 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -28,7 +28,7 @@ #define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \ \ - product(intx, ParallelGCG1AllocBufferSize, 4*K, \ + product(intx, ParallelGCG1AllocBufferSize, 8*K, \ "Size of parallel G1 allocation buffers in to-space.") \ \ product(intx, G1TimeSliceMS, 500, \ @@ -281,7 +281,17 @@ develop(bool, G1HRRSFlushLogBuffersOnVerify, false, \ "Forces flushing of log buffers before verification.") \ \ - product(intx, G1MaxSurvivorRegions, 0, \ - "The maximum number of survivor regions") + product(bool, G1UseSurvivorSpace, true, \ + "When true, use survivor space.") \ + \ + product(bool, G1FixedTenuringThreshold, false, \ + "When set, G1 will not adjust the tenuring threshold") \ + \ + product(bool, G1FixedEdenSize, false, \ + "When set, G1 will not allocate unused survivor space regions") \ + \ + product(uintx, G1FixedSurvivorSpaceSize, 0, \ + "If non-0 is the size of the G1 survivor space, " \ + "otherwise SurvivorRatio is used to determine the size") G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp index 39f72a616b7..4cfb76464e4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp @@ -32,11 +32,13 @@ enum G1Barrier { G1BarrierNone, G1BarrierRS, G1BarrierEvac }; -template +template class G1ParCopyClosure; class G1ParScanClosure; -typedef G1ParCopyClosure G1ParScanHeapEvacClosure; +typedef G1ParCopyClosure + G1ParScanHeapEvacClosure; class FilterIntoCSClosure; class FilterOutOfRegionClosure; diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 5c8d02f045d..10ed5a7d19b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -566,7 +566,11 @@ class HeapRegion: public G1OffsetTableContigSpace { void note_end_of_copying() { assert(top() >= _next_top_at_mark_start, "Increase only"); - _next_top_at_mark_start = top(); + // Survivor regions will be scanned on the start of concurrent + // marking. + if (!is_survivor()) { + _next_top_at_mark_start = top(); + } } // Returns "false" iff no object in the region was allocated when the @@ -829,7 +833,7 @@ class HeapRegionClosure : public StackObj { // A linked lists of heap regions. It leaves the "next" field // unspecified; that's up to subtypes. -class RegionList { +class RegionList VALUE_OBJ_CLASS_SPEC { protected: virtual HeapRegion* get_next(HeapRegion* chr) = 0; virtual void set_next(HeapRegion* chr, diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index e2b15ca37c9..5e54b091976 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -65,9 +65,11 @@ protected: // We need access in order to union things into the base table. BitMap* bm() { return &_bm; } +#if PRT_COUNT_OCCUPIED void recount_occupied() { _occupied = (jint) bm()->count_one_bits(); } +#endif PerRegionTable(HeapRegion* hr) : _hr(hr), @@ -1144,7 +1146,9 @@ void HeapRegionRemSet::clear_outgoing_entries() { size_t i = _outgoing_region_map.get_next_one_offset(0); while (i < _outgoing_region_map.size()) { HeapRegion* to_region = g1h->region_at(i); - to_region->rem_set()->clear_incoming_entry(hr()); + if (!to_region->in_collection_set()) { + to_region->rem_set()->clear_incoming_entry(hr()); + } i = _outgoing_region_map.get_next_one_offset(i+1); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp index bad558a6c46..e5a713109f9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp @@ -58,7 +58,7 @@ class SparsePRT; // is represented. If a deleted PRT is re-used, a thread adding a bit, // thinking the PRT is for a different region, does no harm. -class OtherRegionsTable: public CHeapObj { +class OtherRegionsTable VALUE_OBJ_CLASS_SPEC { friend class HeapRegionRemSetIterator; G1CollectedHeap* _g1h; diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp index 029aac48c2f..df5557c29a6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp @@ -29,7 +29,7 @@ class PtrQueueSet; -class PtrQueue: public CHeapObj { +class PtrQueue VALUE_OBJ_CLASS_SPEC { protected: // The ptr queue set to which this queue belongs. @@ -130,7 +130,7 @@ public: // In particular, the individual queues allocate buffers from this shared // set, and return completed buffers to the set. // All these variables are are protected by the TLOQ_CBL_mon. XXX ??? -class PtrQueueSet: public CHeapObj { +class PtrQueueSet VALUE_OBJ_CLASS_SPEC { protected: diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp index e8fa9b00be1..7c914c7f65c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp @@ -33,7 +33,7 @@ // old versions synchronously. -class SparsePRTEntry { +class SparsePRTEntry: public CHeapObj { public: enum SomePublicConstants { CardsPerEntry = (short)4, @@ -167,7 +167,7 @@ public: }; // ValueObj because will be embedded in HRRS iterator. -class RSHashTableIter: public CHeapObj { +class RSHashTableIter VALUE_OBJ_CLASS_SPEC { short _tbl_ind; short _bl_ind; short _card_ind; @@ -213,7 +213,7 @@ class RSHashTableIter: public CHeapObj { class SparsePRTIter; -class SparsePRT : public CHeapObj { +class SparsePRT VALUE_OBJ_CLASS_SPEC { // Iterations are done on the _cur hash table, since they only need to // see entries visible at the start of a collection pause. // All other operations are done using the _next hash table. diff --git a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp index 0f2a5c95bc1..dbd709a95f4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp @@ -29,23 +29,14 @@ SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p, const char* name, size_t summary_surv_rates_len) : _g1p(g1p), _name(name), - _all_regions_allocated(0), - _curr_length(0), _scan_only_prefix(0), _setup_seq_num(0), - _array_length(0), _surv_rate(NULL), _accum_surv_rate_pred(NULL), - _accum_surv_rate(0.0), _surv_rate_pred(NULL), _last_pred(0.0), _summary_surv_rates_len(summary_surv_rates_len), _summary_surv_rates_max_len(0), - _summary_surv_rates(NULL) { - - // the following will set up the arrays with length 1 - _curr_length = 1; - stop_adding_regions(); - guarantee( _array_length == 1, "invariant" ); - guarantee( _surv_rate_pred[0] != NULL, "invariant" ); - _surv_rate_pred[0]->add(0.4); - all_surviving_words_recorded(false); - _curr_length = 0; - + _summary_surv_rates(NULL), + _surv_rate(NULL), + _accum_surv_rate_pred(NULL), + _surv_rate_pred(NULL) +{ + reset(); if (summary_surv_rates_len > 0) { size_t length = summary_surv_rates_len; _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length); @@ -60,61 +51,80 @@ SurvRateGroup::SurvRateGroup(G1CollectorPolicy* g1p, start_adding_regions(); } + +void SurvRateGroup::reset() +{ + _all_regions_allocated = 0; + _scan_only_prefix = 0; + _setup_seq_num = 0; + _stats_arrays_length = 0; + _accum_surv_rate = 0.0; + _last_pred = 0.0; + // the following will set up the arrays with length 1 + _region_num = 1; + stop_adding_regions(); + guarantee( _stats_arrays_length == 1, "invariant" ); + guarantee( _surv_rate_pred[0] != NULL, "invariant" ); + _surv_rate_pred[0]->add(0.4); + all_surviving_words_recorded(false); + _region_num = 0; +} + + void SurvRateGroup::start_adding_regions() { - _setup_seq_num = _array_length; - _curr_length = _scan_only_prefix; + _setup_seq_num = _stats_arrays_length; + _region_num = _scan_only_prefix; _accum_surv_rate = 0.0; #if 0 - gclog_or_tty->print_cr("start adding regions, seq num %d, length %d", - _setup_seq_num, _curr_length); + gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d", + _name, _setup_seq_num, _region_num); #endif // 0 } void SurvRateGroup::stop_adding_regions() { - size_t length = _curr_length; #if 0 - gclog_or_tty->print_cr("stop adding regions, length %d", length); + gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num); #endif // 0 - if (length > _array_length) { + if (_region_num > _stats_arrays_length) { double* old_surv_rate = _surv_rate; double* old_accum_surv_rate_pred = _accum_surv_rate_pred; TruncatedSeq** old_surv_rate_pred = _surv_rate_pred; - _surv_rate = NEW_C_HEAP_ARRAY(double, length); + _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num); if (_surv_rate == NULL) { - vm_exit_out_of_memory(sizeof(double) * length, + vm_exit_out_of_memory(sizeof(double) * _region_num, "Not enough space for surv rate array."); } - _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, length); + _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num); if (_accum_surv_rate_pred == NULL) { - vm_exit_out_of_memory(sizeof(double) * length, + vm_exit_out_of_memory(sizeof(double) * _region_num, "Not enough space for accum surv rate pred array."); } - _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, length); + _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num); if (_surv_rate == NULL) { - vm_exit_out_of_memory(sizeof(TruncatedSeq*) * length, + vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num, "Not enough space for surv rate pred array."); } - for (size_t i = 0; i < _array_length; ++i) + for (size_t i = 0; i < _stats_arrays_length; ++i) _surv_rate_pred[i] = old_surv_rate_pred[i]; #if 0 - gclog_or_tty->print_cr("stop adding regions, new seqs %d to %d", - _array_length, length - 1); + gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d", + _name, _array_length, _region_num - 1); #endif // 0 - for (size_t i = _array_length; i < length; ++i) { + for (size_t i = _stats_arrays_length; i < _region_num; ++i) { _surv_rate_pred[i] = new TruncatedSeq(10); // _surv_rate_pred[i]->add(last_pred); } - _array_length = length; + _stats_arrays_length = _region_num; if (old_surv_rate != NULL) FREE_C_HEAP_ARRAY(double, old_surv_rate); @@ -124,7 +134,7 @@ SurvRateGroup::stop_adding_regions() { FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred); } - for (size_t i = 0; i < _array_length; ++i) + for (size_t i = 0; i < _stats_arrays_length; ++i) _surv_rate[i] = 0.0; } @@ -135,7 +145,7 @@ SurvRateGroup::accum_surv_rate(size_t adjustment) { double ret = _accum_surv_rate; if (adjustment > 0) { - TruncatedSeq* seq = get_seq(_curr_length+1); + TruncatedSeq* seq = get_seq(_region_num+1); double surv_rate = _g1p->get_new_prediction(seq); ret += surv_rate; } @@ -145,23 +155,23 @@ SurvRateGroup::accum_surv_rate(size_t adjustment) { int SurvRateGroup::next_age_index() { - TruncatedSeq* seq = get_seq(_curr_length); + TruncatedSeq* seq = get_seq(_region_num); double surv_rate = _g1p->get_new_prediction(seq); _accum_surv_rate += surv_rate; - ++_curr_length; + ++_region_num; return (int) ++_all_regions_allocated; } void SurvRateGroup::record_scan_only_prefix(size_t scan_only_prefix) { - guarantee( scan_only_prefix <= _curr_length, "pre-condition" ); + guarantee( scan_only_prefix <= _region_num, "pre-condition" ); _scan_only_prefix = scan_only_prefix; } void SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { - guarantee( 0 <= age_in_group && (size_t) age_in_group < _curr_length, + guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num, "pre-condition" ); guarantee( _surv_rate[age_in_group] <= 0.00001, "should only update each slot once" ); @@ -178,15 +188,15 @@ SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) { void SurvRateGroup::all_surviving_words_recorded(bool propagate) { - if (propagate && _curr_length > 0) { // conservative - double surv_rate = _surv_rate_pred[_curr_length-1]->last(); + if (propagate && _region_num > 0) { // conservative + double surv_rate = _surv_rate_pred[_region_num-1]->last(); #if 0 gclog_or_tty->print_cr("propagating %1.2lf from %d to %d", surv_rate, _curr_length, _array_length - 1); #endif // 0 - for (size_t i = _curr_length; i < _array_length; ++i) { + for (size_t i = _region_num; i < _stats_arrays_length; ++i) { guarantee( _surv_rate[i] <= 0.00001, "the slot should not have been updated" ); _surv_rate_pred[i]->add(surv_rate); @@ -195,7 +205,7 @@ SurvRateGroup::all_surviving_words_recorded(bool propagate) { double accum = 0.0; double pred = 0.0; - for (size_t i = 0; i < _array_length; ++i) { + for (size_t i = 0; i < _stats_arrays_length; ++i) { pred = _g1p->get_new_prediction(_surv_rate_pred[i]); if (pred > 1.0) pred = 1.0; accum += pred; @@ -209,8 +219,8 @@ SurvRateGroup::all_surviving_words_recorded(bool propagate) { void SurvRateGroup::print() { gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries, %d scan-only)", - _name, _curr_length, _scan_only_prefix); - for (size_t i = 0; i < _curr_length; ++i) { + _name, _region_num, _scan_only_prefix); + for (size_t i = 0; i < _region_num; ++i) { gclog_or_tty->print_cr(" age %4d surv rate %6.2lf %% pred %6.2lf %%%s", i, _surv_rate[i] * 100.0, _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0, diff --git a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp index ce69e65f08f..1f5aa2c8bee 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp @@ -29,7 +29,7 @@ private: G1CollectorPolicy* _g1p; const char* _name; - size_t _array_length; + size_t _stats_arrays_length; double* _surv_rate; double* _accum_surv_rate_pred; double _last_pred; @@ -40,7 +40,7 @@ private: size_t _summary_surv_rates_max_len; int _all_regions_allocated; - size_t _curr_length; + size_t _region_num; size_t _scan_only_prefix; size_t _setup_seq_num; @@ -48,6 +48,7 @@ public: SurvRateGroup(G1CollectorPolicy* g1p, const char* name, size_t summary_surv_rates_len); + void reset(); void start_adding_regions(); void stop_adding_regions(); void record_scan_only_prefix(size_t scan_only_prefix); @@ -55,22 +56,21 @@ public: void all_surviving_words_recorded(bool propagate); const char* name() { return _name; } - size_t region_num() { return _curr_length; } + size_t region_num() { return _region_num; } size_t scan_only_length() { return _scan_only_prefix; } double accum_surv_rate_pred(int age) { assert(age >= 0, "must be"); - if ((size_t)age < _array_length) + if ((size_t)age < _stats_arrays_length) return _accum_surv_rate_pred[age]; else { - double diff = (double) (age - _array_length + 1); - return _accum_surv_rate_pred[_array_length-1] + diff * _last_pred; + double diff = (double) (age - _stats_arrays_length + 1); + return _accum_surv_rate_pred[_stats_arrays_length-1] + diff * _last_pred; } } double accum_surv_rate(size_t adjustment); TruncatedSeq* get_seq(size_t age) { - guarantee( 0 <= age, "pre-condition" ); if (age >= _setup_seq_num) { guarantee( _setup_seq_num > 0, "invariant" ); age = _setup_seq_num-1; diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep index d751d2d1f6a..ac88dc1752b 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep @@ -28,6 +28,7 @@ binaryTreeDictionary.cpp allocationStats.hpp binaryTreeDictionary.cpp binaryTreeDictionary.hpp binaryTreeDictionary.cpp globals.hpp binaryTreeDictionary.cpp ostream.hpp +binaryTreeDictionary.cpp space.inline.hpp binaryTreeDictionary.cpp spaceDecorator.hpp binaryTreeDictionary.hpp freeBlockDictionary.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 index 536a3704fe6..84942954651 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1 @@ -31,9 +31,10 @@ bufferingOopClosure.hpp os.hpp cardTableRS.cpp concurrentMark.hpp cardTableRS.cpp g1SATBCardTableModRefBS.hpp -collectionSetChooser.cpp g1CollectedHeap.hpp +collectionSetChooser.cpp g1CollectedHeap.inline.hpp collectionSetChooser.cpp g1CollectorPolicy.hpp collectionSetChooser.cpp collectionSetChooser.hpp +collectionSetChooser.cpp space.inline.hpp collectionSetChooser.hpp heapRegion.hpp collectionSetChooser.hpp growableArray.hpp @@ -42,14 +43,16 @@ concurrentG1Refine.cpp atomic.hpp concurrentG1Refine.cpp concurrentG1Refine.hpp concurrentG1Refine.cpp concurrentG1RefineThread.hpp concurrentG1Refine.cpp copy.hpp -concurrentG1Refine.cpp g1CollectedHeap.hpp +concurrentG1Refine.cpp g1CollectedHeap.inline.hpp concurrentG1Refine.cpp g1RemSet.hpp +concurrentG1Refine.cpp space.inline.hpp concurrentG1Refine.hpp globalDefinitions.hpp +concurrentG1Refine.hpp allocation.hpp concurrentG1RefineThread.cpp concurrentG1Refine.hpp concurrentG1RefineThread.cpp concurrentG1RefineThread.hpp -concurrentG1RefineThread.cpp g1CollectedHeap.hpp +concurrentG1RefineThread.cpp g1CollectedHeap.inline.hpp concurrentG1RefineThread.cpp g1CollectorPolicy.hpp concurrentG1RefineThread.cpp handles.inline.hpp concurrentG1RefineThread.cpp mutexLocker.hpp @@ -166,10 +169,11 @@ g1CollectorPolicy.cpp concurrentMark.hpp g1CollectorPolicy.cpp concurrentMarkThread.inline.hpp g1CollectorPolicy.cpp debug.hpp g1CollectorPolicy.cpp java.hpp -g1CollectorPolicy.cpp g1CollectedHeap.hpp +g1CollectorPolicy.cpp g1CollectedHeap.inline.hpp g1CollectorPolicy.cpp g1CollectorPolicy.hpp g1CollectorPolicy.cpp heapRegionRemSet.hpp g1CollectorPolicy.cpp mutexLocker.hpp +g1CollectorPolicy.cpp gcPolicyCounters.hpp g1CollectorPolicy.hpp collectorPolicy.hpp g1CollectorPolicy.hpp collectionSetChooser.hpp @@ -187,7 +191,7 @@ g1MarkSweep.cpp biasedLocking.hpp g1MarkSweep.cpp codeCache.hpp g1MarkSweep.cpp events.hpp g1MarkSweep.cpp fprofiler.hpp -g1MarkSweep.hpp g1CollectedHeap.hpp +g1MarkSweep.hpp g1CollectedHeap.inline.hpp g1MarkSweep.cpp g1MarkSweep.hpp g1MarkSweep.cpp gcLocker.hpp g1MarkSweep.cpp genCollectedHeap.hpp @@ -226,7 +230,7 @@ g1MMUTracker.cpp ostream.hpp g1MMUTracker.cpp mutexLocker.hpp g1MMUTracker.hpp debug.hpp - +g1MMUTracker.hpp allocation.hpp g1RemSet.cpp bufferingOopClosure.hpp g1RemSet.cpp concurrentG1Refine.hpp g1RemSet.cpp concurrentG1RefineThread.hpp @@ -264,12 +268,13 @@ heapRegion.cpp heapRegionSeq.inline.hpp heapRegion.cpp iterator.hpp heapRegion.cpp oop.inline.hpp -heapRegion.hpp space.hpp +heapRegion.hpp space.inline.hpp heapRegion.hpp spaceDecorator.hpp heapRegion.hpp g1BlockOffsetTable.inline.hpp heapRegion.hpp watermark.hpp heapRegion.hpp g1_specialized_oop_closures.hpp heapRegion.hpp survRateGroup.hpp +heapRegion.hpp ageTable.hpp heapRegionRemSet.hpp sparsePRT.hpp @@ -283,7 +288,7 @@ heapRegionRemSet.cpp globalDefinitions.hpp heapRegionRemSet.cpp space.inline.hpp heapRegionSeq.cpp allocation.hpp -heapRegionSeq.cpp g1CollectedHeap.hpp +heapRegionSeq.cpp g1CollectedHeap.inline.hpp heapRegionSeq.cpp heapRegionSeq.hpp heapRegionSeq.hpp growableArray.hpp @@ -334,18 +339,18 @@ specialized_oop_closures.hpp g1_specialized_oop_closures.hpp survRateGroup.hpp numberSeq.hpp survRateGroup.cpp allocation.hpp -survRateGroup.cpp g1CollectedHeap.hpp +survRateGroup.cpp g1CollectedHeap.inline.hpp survRateGroup.cpp g1CollectorPolicy.hpp survRateGroup.cpp heapRegion.hpp survRateGroup.cpp survRateGroup.hpp thread.cpp concurrentMarkThread.inline.hpp -universe.cpp g1CollectedHeap.hpp +universe.cpp g1CollectedHeap.inline.hpp universe.cpp g1CollectorPolicy.hpp vm_operations_g1.hpp vmGCOperations.hpp vm_operations_g1.cpp vm_operations_g1.hpp -vm_operations_g1.cpp g1CollectedHeap.hpp +vm_operations_g1.cpp g1CollectedHeap.inline.hpp vm_operations_g1.cpp isGCActiveMark.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew index e5e5bc17b7c..0d8160ffa38 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew @@ -29,6 +29,8 @@ asParNewGeneration.cpp asParNewGeneration.hpp asParNewGeneration.cpp cmsAdaptiveSizePolicy.hpp asParNewGeneration.cpp cmsGCAdaptivePolicyCounters.hpp asParNewGeneration.cpp defNewGeneration.inline.hpp +asParNewGeneration.cpp markOop.inline.hpp +asParNewGeneration.cpp markSweep.inline.hpp asParNewGeneration.cpp oop.pcgc.inline.hpp asParNewGeneration.cpp parNewGeneration.hpp asParNewGeneration.cpp referencePolicy.hpp @@ -40,7 +42,7 @@ parCardTableModRefBS.cpp cardTableRS.hpp parCardTableModRefBS.cpp java.hpp parCardTableModRefBS.cpp mutexLocker.hpp parCardTableModRefBS.cpp sharedHeap.hpp -parCardTableModRefBS.cpp space.hpp +parCardTableModRefBS.cpp space.inline.hpp parCardTableModRefBS.cpp universe.hpp parCardTableModRefBS.cpp virtualspace.hpp @@ -77,6 +79,7 @@ parNewGeneration.cpp resourceArea.hpp parNewGeneration.cpp sharedHeap.hpp parNewGeneration.cpp space.hpp parNewGeneration.cpp spaceDecorator.hpp +parNewGeneration.cpp thread.hpp parNewGeneration.cpp workgroup.hpp parNewGeneration.hpp defNewGeneration.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge index 13ba87c8391..0e0ae1a1e0e 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge @@ -302,6 +302,8 @@ psOldGen.hpp safepoint.hpp psOldGen.hpp spaceCounters.hpp psPermGen.cpp gcUtil.hpp +psPermGen.cpp markOop.inline.hpp +psPermGen.cpp markSweep.inline.hpp psPermGen.cpp parallelScavengeHeap.hpp psPermGen.cpp psMarkSweepDecorator.hpp psPermGen.cpp psParallelCompact.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared b/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared index 7ea2265898d..99ce759a474 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_shared @@ -100,4 +100,4 @@ spaceCounters.hpp mutableSpace.hpp spaceCounters.hpp perfData.hpp spaceCounters.hpp generationCounters.hpp -vmGCOperations.cpp g1CollectedHeap.hpp +vmGCOperations.cpp g1CollectedHeap.inline.hpp diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index a2b7607bb79..a5010925b00 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -404,6 +404,8 @@ void ParEvacuateFollowersClosure::do_void() { if (terminator()->offer_termination()) break; par_scan_state()->end_term_time(); } + assert(par_gen()->_overflow_list == NULL && par_gen()->_num_par_pushes == 0, + "Broken overflow list?"); // Finish the last termination pause. par_scan_state()->end_term_time(); } @@ -456,6 +458,8 @@ ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level) _is_alive_closure(this), _plab_stats(YoungPLABSize, PLABWeight) { + NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) + NOT_PRODUCT(_num_par_pushes = 0;) _task_queues = new ObjToScanQueueSet(ParallelGCThreads); guarantee(_task_queues != NULL, "task_queues allocation failure."); @@ -993,12 +997,19 @@ oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo( "push forwarded object"); } // Push it on one of the queues of to-be-scanned objects. - if (!par_scan_state->work_queue()->push(obj_to_push)) { + bool simulate_overflow = false; + NOT_PRODUCT( + if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) { + // simulate a stack overflow + simulate_overflow = true; + } + ) + if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) { // Add stats for overflow pushes. if (Verbose && PrintGCDetails) { gclog_or_tty->print("queue overflow!\n"); } - push_on_overflow_list(old); + push_on_overflow_list(old, par_scan_state); par_scan_state->note_overflow_push(); } par_scan_state->note_push(); @@ -1110,9 +1121,16 @@ oop ParNewGeneration::copy_to_survivor_space_with_undo( "push forwarded object"); } // Push it on one of the queues of to-be-scanned objects. - if (!par_scan_state->work_queue()->push(obj_to_push)) { + bool simulate_overflow = false; + NOT_PRODUCT( + if (ParGCWorkQueueOverflowALot && should_simulate_overflow()) { + // simulate a stack overflow + simulate_overflow = true; + } + ) + if (simulate_overflow || !par_scan_state->work_queue()->push(obj_to_push)) { // Add stats for overflow pushes. - push_on_overflow_list(old); + push_on_overflow_list(old, par_scan_state); par_scan_state->note_overflow_push(); } par_scan_state->note_push(); @@ -1135,89 +1153,190 @@ oop ParNewGeneration::copy_to_survivor_space_with_undo( return forward_ptr; } -void ParNewGeneration::push_on_overflow_list(oop from_space_obj) { - oop cur_overflow_list = _overflow_list; +#ifndef PRODUCT +// It's OK to call this multi-threaded; the worst thing +// that can happen is that we'll get a bunch of closely +// spaced simulated oveflows, but that's OK, in fact +// probably good as it would exercise the overflow code +// under contention. +bool ParNewGeneration::should_simulate_overflow() { + if (_overflow_counter-- <= 0) { // just being defensive + _overflow_counter = ParGCWorkQueueOverflowInterval; + return true; + } else { + return false; + } +} +#endif + +#define BUSY (oop(0x1aff1aff)) +void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) { // if the object has been forwarded to itself, then we cannot // use the klass pointer for the linked list. Instead we have // to allocate an oopDesc in the C-Heap and use that for the linked list. + // XXX This is horribly inefficient when a promotion failure occurs + // and should be fixed. XXX FIX ME !!! +#ifndef PRODUCT + Atomic::inc_ptr(&_num_par_pushes); + assert(_num_par_pushes > 0, "Tautology"); +#endif if (from_space_obj->forwardee() == from_space_obj) { oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1); listhead->forward_to(from_space_obj); from_space_obj = listhead; } - while (true) { - from_space_obj->set_klass_to_list_ptr(cur_overflow_list); - oop observed_overflow_list = - (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list); - if (observed_overflow_list == cur_overflow_list) break; - // Otherwise... + oop observed_overflow_list = _overflow_list; + oop cur_overflow_list; + do { cur_overflow_list = observed_overflow_list; - } + if (cur_overflow_list != BUSY) { + from_space_obj->set_klass_to_list_ptr(cur_overflow_list); + } else { + from_space_obj->set_klass_to_list_ptr(NULL); + } + observed_overflow_list = + (oop)Atomic::cmpxchg_ptr(from_space_obj, &_overflow_list, cur_overflow_list); + } while (cur_overflow_list != observed_overflow_list); } +// *NOTE*: The overflow list manipulation code here and +// in CMSCollector:: are very similar in shape, +// except that in the CMS case we thread the objects +// directly into the list via their mark word, and do +// not need to deal with special cases below related +// to chunking of object arrays and promotion failure +// handling. +// CR 6797058 has been filed to attempt consolidation of +// the common code. +// Because of the common code, if you make any changes in +// the code below, please check the CMS version to see if +// similar changes might be needed. +// See CMSCollector::par_take_from_overflow_list() for +// more extensive documentation comments. bool ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) { ObjToScanQueue* work_q = par_scan_state->work_queue(); + assert(work_q->size() == 0, "Should first empty local work queue"); // How many to take? - int objsFromOverflow = MIN2(work_q->max_elems()/4, - (juint)ParGCDesiredObjsFromOverflowList); + size_t objsFromOverflow = MIN2((size_t)work_q->max_elems()/4, + (size_t)ParGCDesiredObjsFromOverflowList); if (_overflow_list == NULL) return false; // Otherwise, there was something there; try claiming the list. - oop prefix = (oop)Atomic::xchg_ptr(NULL, &_overflow_list); - - if (prefix == NULL) { - return false; - } + oop prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); // Trim off a prefix of at most objsFromOverflow items - int i = 1; + Thread* tid = Thread::current(); + size_t spin_count = (size_t)ParallelGCThreads; + size_t sleep_time_millis = MAX2((size_t)1, objsFromOverflow/100); + for (size_t spin = 0; prefix == BUSY && spin < spin_count; spin++) { + // someone grabbed it before we did ... + // ... we spin for a short while... + os::sleep(tid, sleep_time_millis, false); + if (_overflow_list == NULL) { + // nothing left to take + return false; + } else if (_overflow_list != BUSY) { + // try and grab the prefix + prefix = (oop)Atomic::xchg_ptr(BUSY, &_overflow_list); + } + } + if (prefix == NULL || prefix == BUSY) { + // Nothing to take or waited long enough + if (prefix == NULL) { + // Write back the NULL in case we overwrote it with BUSY above + // and it is still the same value. + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); + } + return false; + } + assert(prefix != NULL && prefix != BUSY, "Error"); + size_t i = 1; oop cur = prefix; while (i < objsFromOverflow && cur->klass_or_null() != NULL) { i++; cur = oop(cur->klass()); } // Reattach remaining (suffix) to overflow list - if (cur->klass_or_null() != NULL) { - oop suffix = oop(cur->klass()); - cur->set_klass_to_list_ptr(NULL); - - // Find last item of suffix list - oop last = suffix; - while (last->klass_or_null() != NULL) { - last = oop(last->klass()); + if (cur->klass_or_null() == NULL) { + // Write back the NULL in lieu of the BUSY we wrote + // above and it is still the same value. + if (_overflow_list == BUSY) { + (void) Atomic::cmpxchg_ptr(NULL, &_overflow_list, BUSY); } - // Atomically prepend suffix to current overflow list - oop cur_overflow_list = _overflow_list; - while (true) { - last->set_klass_to_list_ptr(cur_overflow_list); - oop observed_overflow_list = - (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); - if (observed_overflow_list == cur_overflow_list) break; - // Otherwise... - cur_overflow_list = observed_overflow_list; + } else { + assert(cur->klass_or_null() != BUSY, "Error"); + oop suffix = oop(cur->klass()); // suffix will be put back on global list + cur->set_klass_to_list_ptr(NULL); // break off suffix + // It's possible that the list is still in the empty(busy) state + // we left it in a short while ago; in that case we may be + // able to place back the suffix. + oop observed_overflow_list = _overflow_list; + oop cur_overflow_list = observed_overflow_list; + bool attached = false; + while (observed_overflow_list == BUSY || observed_overflow_list == NULL) { + observed_overflow_list = + (oop) Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); + if (cur_overflow_list == observed_overflow_list) { + attached = true; + break; + } else cur_overflow_list = observed_overflow_list; + } + if (!attached) { + // Too bad, someone else got in in between; we'll need to do a splice. + // Find the last item of suffix list + oop last = suffix; + while (last->klass_or_null() != NULL) { + last = oop(last->klass()); + } + // Atomically prepend suffix to current overflow list + observed_overflow_list = _overflow_list; + do { + cur_overflow_list = observed_overflow_list; + if (cur_overflow_list != BUSY) { + // Do the splice ... + last->set_klass_to_list_ptr(cur_overflow_list); + } else { // cur_overflow_list == BUSY + last->set_klass_to_list_ptr(NULL); + } + observed_overflow_list = + (oop)Atomic::cmpxchg_ptr(suffix, &_overflow_list, cur_overflow_list); + } while (cur_overflow_list != observed_overflow_list); } } // Push objects on prefix list onto this thread's work queue - assert(cur != NULL, "program logic"); + assert(prefix != NULL && prefix != BUSY, "program logic"); cur = prefix; - int n = 0; + ssize_t n = 0; while (cur != NULL) { oop obj_to_push = cur->forwardee(); oop next = oop(cur->klass_or_null()); cur->set_klass(obj_to_push->klass()); - if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) { - obj_to_push = cur; + // This may be an array object that is self-forwarded. In that case, the list pointer + // space, cur, is not in the Java heap, but rather in the C-heap and should be freed. + if (!is_in_reserved(cur)) { + // This can become a scaling bottleneck when there is work queue overflow coincident + // with promotion failure. + oopDesc* f = cur; + FREE_C_HEAP_ARRAY(oopDesc, f); + } else if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) { assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned"); + obj_to_push = cur; } - work_q->push(obj_to_push); + bool ok = work_q->push(obj_to_push); + assert(ok, "Should have succeeded"); cur = next; n++; } par_scan_state->note_overflow_refill(n); +#ifndef PRODUCT + assert(_num_par_pushes >= n, "Too many pops?"); + Atomic::add_ptr(-(intptr_t)n, &_num_par_pushes); +#endif return true; } +#undef BUSY void ParNewGeneration::ref_processor_init() { diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index a9e2d199f6c..b8de0b1e7ac 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -278,6 +278,7 @@ class ParNewGeneration: public DefNewGeneration { friend class ParNewRefProcTask; friend class ParNewRefProcTaskExecutor; friend class ParScanThreadStateSet; + friend class ParEvacuateFollowersClosure; private: // XXX use a global constant instead of 64! @@ -296,6 +297,7 @@ class ParNewGeneration: public DefNewGeneration { // klass-pointers (klass information already copied to the forwarded // image.) Manipulated with CAS. oop _overflow_list; + NOT_PRODUCT(ssize_t _num_par_pushes;) // If true, older generation does not support promotion undo, so avoid. static bool _avoid_promotion_undo; @@ -372,8 +374,12 @@ class ParNewGeneration: public DefNewGeneration { oop copy_to_survivor_space_with_undo(ParScanThreadState* par_scan_state, oop obj, size_t obj_sz, markOop m); + // in support of testing overflow code + NOT_PRODUCT(int _overflow_counter;) + NOT_PRODUCT(bool should_simulate_overflow();) + // Push the given (from-space) object on the global overflow list. - void push_on_overflow_list(oop from_space_obj); + void push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state); // If the global overflow list is non-empty, move some tasks from it // onto "work_q" (which must be empty). No more than 1/4 of the diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index 087cdf93c01..c268b6a2f86 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -200,6 +200,7 @@ class ParallelScavengeHeap : public CollectedHeap { void oop_iterate(OopClosure* cl); void object_iterate(ObjectClosure* cl); + void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); } void permanent_oop_iterate(OopClosure* cl); void permanent_object_iterate(ObjectClosure* cl); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index 829403f5128..608eedb8fb1 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -362,6 +362,10 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { if (PrintHeapAtGC) { Universe::print_heap_after_gc(); } + +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif } bool PSMarkSweep::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy, diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp index 2335a20e183..2d31e5d72a0 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp @@ -116,7 +116,7 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) { // ObjectSpace stuff // - _object_space = new MutableSpace(); + _object_space = new MutableSpace(virtual_space()->alignment()); if (_object_space == NULL) vm_exit_during_initialization("Could not allocate an old gen space"); @@ -385,10 +385,10 @@ void PSOldGen::post_resize() { start_array()->set_covered_region(new_memregion); Universe::heap()->barrier_set()->resize_covered_region(new_memregion); - HeapWord* const virtual_space_high = (HeapWord*) virtual_space()->high(); - // ALWAYS do this last!! - object_space()->set_end(virtual_space_high); + object_space()->initialize(new_memregion, + SpaceDecorator::DontClear, + SpaceDecorator::DontMangle); assert(new_word_size == heap_word_size(object_space()->capacity_in_bytes()), "Sanity"); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index 5d693905c98..686c65b2c53 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -2203,6 +2203,10 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { collection_exit.ticks()); gc_task_manager()->print_task_time_stamps(); } + +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif } bool PSParallelCompact::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy, diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 6357362b0f7..f0bc6a85e8b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -615,6 +615,10 @@ bool PSScavenge::invoke_no_policy() { gc_task_manager()->print_task_time_stamps(); } +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif + return !promotion_failure_occurred; } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp index 523103f6c6f..4003e19c614 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp @@ -78,7 +78,7 @@ void PSVirtualSpace::release() { _special = false; } -bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) { +bool PSVirtualSpace::expand_by(size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); @@ -92,15 +92,6 @@ bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) { _committed_high_addr += bytes; } - if (pre_touch || AlwaysPreTouch) { - for (char* curr = base_addr; - curr < _committed_high_addr; - curr += os::vm_page_size()) { - char tmp = *curr; - *curr = 0; - } - } - return result; } @@ -255,7 +246,7 @@ PSVirtualSpaceHighToLow::PSVirtualSpaceHighToLow(ReservedSpace rs) { DEBUG_ONLY(verify()); } -bool PSVirtualSpaceHighToLow::expand_by(size_t bytes, bool pre_touch) { +bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) { assert(is_aligned(bytes), "arg not aligned"); DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this)); @@ -269,15 +260,6 @@ bool PSVirtualSpaceHighToLow::expand_by(size_t bytes, bool pre_touch) { _committed_low_addr -= bytes; } - if (pre_touch || AlwaysPreTouch) { - for (char* curr = base_addr; - curr < _committed_high_addr; - curr += os::vm_page_size()) { - char tmp = *curr; - *curr = 0; - } - } - return result; } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp index 8e1e03679e6..c3c1035998a 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp @@ -80,7 +80,7 @@ class PSVirtualSpace : public CHeapObj { inline void set_reserved(char* low_addr, char* high_addr, bool special); inline void set_reserved(ReservedSpace rs); inline void set_committed(char* low_addr, char* high_addr); - virtual bool expand_by(size_t bytes, bool pre_touch = false); + virtual bool expand_by(size_t bytes); virtual bool shrink_by(size_t bytes); virtual size_t expand_into(PSVirtualSpace* space, size_t bytes); void release(); @@ -127,7 +127,7 @@ class PSVirtualSpaceHighToLow : public PSVirtualSpace { PSVirtualSpaceHighToLow(ReservedSpace rs, size_t alignment); PSVirtualSpaceHighToLow(ReservedSpace rs); - virtual bool expand_by(size_t bytes, bool pre_touch = false); + virtual bool expand_by(size_t bytes); virtual bool shrink_by(size_t bytes); virtual size_t expand_into(PSVirtualSpace* space, size_t bytes); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp index bfbffcba0dc..1b12c6bf802 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp @@ -64,12 +64,12 @@ void PSYoungGen::initialize_work() { } if (UseNUMA) { - _eden_space = new MutableNUMASpace(); + _eden_space = new MutableNUMASpace(virtual_space()->alignment()); } else { - _eden_space = new MutableSpace(); + _eden_space = new MutableSpace(virtual_space()->alignment()); } - _from_space = new MutableSpace(); - _to_space = new MutableSpace(); + _from_space = new MutableSpace(virtual_space()->alignment()); + _to_space = new MutableSpace(virtual_space()->alignment()); if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) { vm_exit_during_initialization("Could not allocate a young gen space"); diff --git a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp index 73197bbb1bf..64fe87f7ca9 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp @@ -67,6 +67,12 @@ void ageTable::merge(ageTable* subTable) { } } +void ageTable::merge_par(ageTable* subTable) { + for (int i = 0; i < table_size; i++) { + Atomic::add_ptr(subTable->sizes[i], &sizes[i]); + } +} + int ageTable::compute_tenuring_threshold(size_t survivor_capacity) { size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); size_t total = 0; diff --git a/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp b/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp index 932b792b914..fffef2af1ad 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp @@ -56,6 +56,7 @@ class ageTable VALUE_OBJ_CLASS_SPEC { // Merge another age table with the current one. Used // for parallel young generation gc. void merge(ageTable* subTable); + void merge_par(ageTable* subTable); // calculate new tenuring threshold based on age information int compute_tenuring_threshold(size_t survivor_capacity); diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index c639bbf3f96..a3787c8cd29 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -27,7 +27,7 @@ # include "incls/_mutableNUMASpace.cpp.incl" -MutableNUMASpace::MutableNUMASpace() { +MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) { _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray(0, true); _page_size = os::vm_page_size(); _adaptation_cycles = 0; @@ -221,7 +221,7 @@ bool MutableNUMASpace::update_layout(bool force) { } } if (!found) { - lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i])); + lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment())); } } @@ -443,10 +443,10 @@ void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection // Is there bottom? if (new_region.start() < intersection.start()) { // Yes // Try to coalesce small pages into a large one. - if (UseLargePages && page_size() >= os::large_page_size()) { - HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), os::large_page_size()); + if (UseLargePages && page_size() >= alignment()) { + HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), alignment()); if (new_region.contains(p) - && pointer_delta(p, new_region.start(), sizeof(char)) >= os::large_page_size()) { + && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) { if (intersection.contains(p)) { intersection = MemRegion(p, intersection.end()); } else { @@ -462,10 +462,10 @@ void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection // Is there top? if (intersection.end() < new_region.end()) { // Yes // Try to coalesce small pages into a large one. - if (UseLargePages && page_size() >= os::large_page_size()) { - HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), os::large_page_size()); + if (UseLargePages && page_size() >= alignment()) { + HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), alignment()); if (new_region.contains(p) - && pointer_delta(new_region.end(), p, sizeof(char)) >= os::large_page_size()) { + && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) { if (intersection.contains(p)) { intersection = MemRegion(intersection.start(), p); } else { @@ -504,12 +504,12 @@ void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersecti // That's the only case we have to make an additional bias_region() call. HeapWord* start = invalid_region->start(); HeapWord* end = invalid_region->end(); - if (UseLargePages && page_size() >= os::large_page_size()) { - HeapWord *p = (HeapWord*)round_down((intptr_t) start, os::large_page_size()); + if (UseLargePages && page_size() >= alignment()) { + HeapWord *p = (HeapWord*)round_down((intptr_t) start, alignment()); if (new_region.contains(p)) { start = p; } - p = (HeapWord*)round_to((intptr_t) end, os::large_page_size()); + p = (HeapWord*)round_to((intptr_t) end, alignment()); if (new_region.contains(end)) { end = p; } @@ -526,7 +526,8 @@ void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersecti void MutableNUMASpace::initialize(MemRegion mr, bool clear_space, - bool mangle_space) { + bool mangle_space, + bool setup_pages) { assert(clear_space, "Reallocation will destory data!"); assert(lgrp_spaces()->length() > 0, "There should be at least one space"); @@ -538,7 +539,7 @@ void MutableNUMASpace::initialize(MemRegion mr, // Compute chunk sizes size_t prev_page_size = page_size(); - set_page_size(UseLargePages ? os::large_page_size() : os::vm_page_size()); + set_page_size(UseLargePages ? alignment() : os::vm_page_size()); HeapWord* rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size()); HeapWord* rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size()); size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size(); @@ -666,7 +667,7 @@ void MutableNUMASpace::initialize(MemRegion mr, } // Clear space (set top = bottom) but never mangle. - s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle); + s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages); set_adaptation_cycles(samples_count()); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index f7ca2462545..128db555b58 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -82,8 +82,8 @@ class MutableNUMASpace : public MutableSpace { char* last_page_scanned() { return _last_page_scanned; } void set_last_page_scanned(char* p) { _last_page_scanned = p; } public: - LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { - _space = new MutableSpace(); + LGRPSpace(int l, size_t alignment) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { + _space = new MutableSpace(alignment); _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight); } ~LGRPSpace() { @@ -183,10 +183,10 @@ class MutableNUMASpace : public MutableSpace { public: GrowableArray* lgrp_spaces() const { return _lgrp_spaces; } - MutableNUMASpace(); + MutableNUMASpace(size_t alignment); virtual ~MutableNUMASpace(); // Space initialization. - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space, bool setup_pages = SetupPages); // Update space layout if necessary. Do all adaptive resizing job. virtual void update(); // Update allocation rate averages. diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp index 65c6d34cde8..90e1d3ca2ca 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp @@ -25,7 +25,10 @@ # include "incls/_precompiled.incl" # include "incls/_mutableSpace.cpp.incl" -MutableSpace::MutableSpace(): ImmutableSpace(), _top(NULL) { +MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { + assert(MutableSpace::alignment() >= 0 && + MutableSpace::alignment() % os::vm_page_size() == 0, + "Space should be aligned"); _mangler = new MutableSpaceMangler(this); } @@ -33,16 +36,88 @@ MutableSpace::~MutableSpace() { delete _mangler; } +void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) { + if (!mr.is_empty()) { + size_t page_size = UseLargePages ? alignment() : os::vm_page_size(); + HeapWord *start = (HeapWord*)round_to((intptr_t) mr.start(), page_size); + HeapWord *end = (HeapWord*)round_down((intptr_t) mr.end(), page_size); + if (end > start) { + size_t size = pointer_delta(end, start, sizeof(char)); + if (clear_space) { + // Prefer page reallocation to migration. + os::free_memory((char*)start, size); + } + os::numa_make_global((char*)start, size); + } + } +} + +void MutableSpace::pretouch_pages(MemRegion mr) { + for (volatile char *p = (char*)mr.start(); p < (char*)mr.end(); p += os::vm_page_size()) { + char t = *p; *p = t; + } +} + void MutableSpace::initialize(MemRegion mr, bool clear_space, - bool mangle_space) { - HeapWord* bottom = mr.start(); - HeapWord* end = mr.end(); + bool mangle_space, + bool setup_pages) { - assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), + assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()), "invalid space boundaries"); - set_bottom(bottom); - set_end(end); + + if (setup_pages && (UseNUMA || AlwaysPreTouch)) { + // The space may move left and right or expand/shrink. + // We'd like to enforce the desired page placement. + MemRegion head, tail; + if (last_setup_region().is_empty()) { + // If it's the first initialization don't limit the amount of work. + head = mr; + tail = MemRegion(mr.end(), mr.end()); + } else { + // Is there an intersection with the address space? + MemRegion intersection = last_setup_region().intersection(mr); + if (intersection.is_empty()) { + intersection = MemRegion(mr.end(), mr.end()); + } + // All the sizes below are in words. + size_t head_size = 0, tail_size = 0; + if (mr.start() <= intersection.start()) { + head_size = pointer_delta(intersection.start(), mr.start()); + } + if(intersection.end() <= mr.end()) { + tail_size = pointer_delta(mr.end(), intersection.end()); + } + // Limit the amount of page manipulation if necessary. + if (NUMASpaceResizeRate > 0 && !AlwaysPreTouch) { + const size_t change_size = head_size + tail_size; + const float setup_rate_words = NUMASpaceResizeRate >> LogBytesPerWord; + head_size = MIN2((size_t)(setup_rate_words * head_size / change_size), + head_size); + tail_size = MIN2((size_t)(setup_rate_words * tail_size / change_size), + tail_size); + } + head = MemRegion(intersection.start() - head_size, intersection.start()); + tail = MemRegion(intersection.end(), intersection.end() + tail_size); + } + assert(mr.contains(head) && mr.contains(tail), "Sanity"); + + if (UseNUMA) { + numa_setup_pages(head, clear_space); + numa_setup_pages(tail, clear_space); + } + + if (AlwaysPreTouch) { + pretouch_pages(head); + pretouch_pages(tail); + } + + // Remember where we stopped so that we can continue later. + set_last_setup_region(MemRegion(head.start(), tail.end())); + } + + set_bottom(mr.start()); + set_end(mr.end()); if (clear_space) { clear(mangle_space); diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp index b55da4c8459..98382d6c410 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.hpp @@ -25,7 +25,10 @@ // A MutableSpace is a subtype of ImmutableSpace that supports the // concept of allocation. This includes the concepts that a space may // be only partially full, and the querry methods that go with such -// an assumption. +// an assumption. MutableSpace is also responsible for minimizing the +// page allocation time by having the memory pretouched (with +// AlwaysPretouch) and for optimizing page placement on NUMA systems +// by make the underlying region interleaved (with UseNUMA). // // Invariant: (ImmutableSpace +) bottom() <= top() <= end() // top() is inclusive and end() is exclusive. @@ -37,15 +40,23 @@ class MutableSpace: public ImmutableSpace { // Helper for mangling unused space in debug builds MutableSpaceMangler* _mangler; - + // The last region which page had been setup to be interleaved. + MemRegion _last_setup_region; + size_t _alignment; protected: HeapWord* _top; MutableSpaceMangler* mangler() { return _mangler; } + void numa_setup_pages(MemRegion mr, bool clear_space); + void pretouch_pages(MemRegion mr); + + void set_last_setup_region(MemRegion mr) { _last_setup_region = mr; } + MemRegion last_setup_region() const { return _last_setup_region; } + public: virtual ~MutableSpace(); - MutableSpace(); + MutableSpace(size_t page_size); // Accessors HeapWord* top() const { return _top; } @@ -57,13 +68,20 @@ class MutableSpace: public ImmutableSpace { virtual void set_bottom(HeapWord* value) { _bottom = value; } virtual void set_end(HeapWord* value) { _end = value; } + size_t alignment() { return _alignment; } + // Returns a subregion containing all objects in this space. MemRegion used_region() { return MemRegion(bottom(), top()); } + static const bool SetupPages = true; + static const bool DontSetupPages = false; + // Initialization virtual void initialize(MemRegion mr, bool clear_space, - bool mangle_space); + bool mangle_space, + bool setup_pages = SetupPages); + virtual void clear(bool mangle_space); // Does the usual initialization but optionally resets top to bottom. #if 0 // MANGLE_SPACE diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp index 13d30c70b6d..210e6b32b90 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp @@ -42,6 +42,7 @@ class Thread; class CollectedHeap : public CHeapObj { friend class VMStructs; friend class IsGCActiveMark; // Block structured external access to _is_gc_active + friend class constantPoolCacheKlass; // allocate() method inserts is_conc_safe #ifdef ASSERT static int _fire_out_of_memory_count; @@ -82,8 +83,6 @@ class CollectedHeap : public CHeapObj { // Reinitialize tlabs before resuming mutators. virtual void resize_all_tlabs(); - debug_only(static void check_for_valid_allocation_state();) - protected: // Allocate from the current thread's TLAB, with broken-out slow path. inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size); @@ -142,6 +141,7 @@ class CollectedHeap : public CHeapObj { PRODUCT_RETURN; virtual void check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) PRODUCT_RETURN; + debug_only(static void check_for_valid_allocation_state();) public: enum Name { @@ -466,6 +466,10 @@ class CollectedHeap : public CHeapObj { // This includes objects in permanent memory. virtual void object_iterate(ObjectClosure* cl) = 0; + // Similar to object_iterate() except iterates only + // over live objects. + virtual void safe_object_iterate(ObjectClosure* cl) = 0; + // Behaves the same as oop_iterate, except only traverses // interior pointers contained in permanent memory. If there // is no permanent memory, does nothing. diff --git a/hotspot/src/share/vm/includeDB_compiler2 b/hotspot/src/share/vm/includeDB_compiler2 index ea3b88cc172..bf84589334c 100644 --- a/hotspot/src/share/vm/includeDB_compiler2 +++ b/hotspot/src/share/vm/includeDB_compiler2 @@ -140,6 +140,7 @@ c2_globals_.hpp globalDefinitions.hpp c2_globals_.hpp macros.hpp c2_init_.cpp compile.hpp +c2_init_.cpp node.hpp c2compiler.cpp ad_.hpp c2compiler.cpp c2compiler.hpp @@ -839,6 +840,7 @@ parseHelper.cpp systemDictionary.hpp phase.cpp compile.hpp phase.cpp compileBroker.hpp phase.cpp nmethod.hpp +phase.cpp node.hpp phase.cpp phase.hpp phase.hpp port.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 7ca1fcabef5..8d39f327758 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -1311,6 +1311,7 @@ cppInterpreter_.cpp bytecodeHistogram.hpp cppInterpreter_.cpp debug.hpp cppInterpreter_.cpp deoptimization.hpp cppInterpreter_.cpp frame.inline.hpp +cppInterpreter_.cpp interfaceSupport.hpp cppInterpreter_.cpp interpreterRuntime.hpp cppInterpreter_.cpp interpreter.hpp cppInterpreter_.cpp interpreterGenerator.hpp @@ -2014,7 +2015,7 @@ instanceKlass.cpp verifier.hpp instanceKlass.cpp vmSymbols.hpp instanceKlass.hpp accessFlags.hpp -instanceKlass.hpp bitMap.hpp +instanceKlass.hpp bitMap.inline.hpp instanceKlass.hpp constMethodOop.hpp instanceKlass.hpp constantPoolOop.hpp instanceKlass.hpp handles.hpp @@ -3771,6 +3772,7 @@ spaceDecorator.hpp space.hpp spaceDecorator.cpp copy.hpp spaceDecorator.cpp spaceDecorator.hpp +spaceDecorator.cpp space.inline.hpp specialized_oop_closures.cpp ostream.hpp specialized_oop_closures.cpp specialized_oop_closures.hpp diff --git a/hotspot/src/share/vm/includeDB_features b/hotspot/src/share/vm/includeDB_features index d783a04e55b..e136dfe784a 100644 --- a/hotspot/src/share/vm/includeDB_features +++ b/hotspot/src/share/vm/includeDB_features @@ -59,6 +59,8 @@ dump.cpp vm_operations.hpp dump_.cpp assembler_.inline.hpp dump_.cpp compactingPermGenGen.hpp +dump_.cpp generation.inline.hpp +dump_.cpp space.inline.hpp forte.cpp collectedHeap.inline.hpp forte.cpp debugInfoRec.hpp diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index b4204414a94..351d29cc9cc 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -163,7 +163,7 @@ #ifdef USELABELS // Have to do this dispatch this way in C++ because otherwise gcc complains about crossing an // initialization (which is is the initialization of the table pointer...) -#define DISPATCH(opcode) goto *dispatch_table[opcode] +#define DISPATCH(opcode) goto *(void*)dispatch_table[opcode] #define CONTINUE { \ opcode = *pc; \ DO_UPDATE_INSTRUCTION_COUNT(opcode); \ @@ -341,7 +341,7 @@ */ #undef CHECK_NULL #define CHECK_NULL(obj_) \ - if ((obj_) == 0) { \ + if ((obj_) == NULL) { \ VM_JAVA_ERROR(vmSymbols::java_lang_NullPointerException(), ""); \ } @@ -1362,7 +1362,7 @@ run: #define NULL_COMPARISON_NOT_OP(name) \ CASE(_if##name): { \ - int skip = (!(STACK_OBJECT(-1) == 0)) \ + int skip = (!(STACK_OBJECT(-1) == NULL)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ UPDATE_PC_AND_TOS(skip, -1); \ @@ -1372,7 +1372,7 @@ run: #define NULL_COMPARISON_OP(name) \ CASE(_if##name): { \ - int skip = ((STACK_OBJECT(-1) == 0)) \ + int skip = ((STACK_OBJECT(-1) == NULL)) \ ? (int16_t)Bytes::get_Java_u2(pc + 1) : 3; \ address branch_pc = pc; \ UPDATE_PC_AND_TOS(skip, -1); \ diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp index 715acf671a2..a1504851a38 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.hpp @@ -66,7 +66,6 @@ friend class CppInterpreterGenerator; friend class InterpreterGenerator; friend class InterpreterMacroAssembler; friend class frame; -friend class SharedRuntime; friend class VMStructs; public: diff --git a/hotspot/src/share/vm/interpreter/rewriter.cpp b/hotspot/src/share/vm/interpreter/rewriter.cpp index d000012b5cb..323ea8f9a28 100644 --- a/hotspot/src/share/vm/interpreter/rewriter.cpp +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp @@ -48,9 +48,14 @@ void Rewriter::compute_index_maps(constantPoolHandle pool, intArray*& index_map, // Creates a constant pool cache given an inverse_index_map +// This creates the constant pool cache initially in a state +// that is unsafe for concurrent GC processing but sets it to +// a safe mode before the constant pool cache is returned. constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) { const int length = inverse_index_map.length(); - constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK_(constantPoolCacheHandle())); + constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, + methodOopDesc::IsUnsafeConc, + CHECK_(constantPoolCacheHandle())); cache->initialize(inverse_index_map); return constantPoolCacheHandle(THREAD, cache); } diff --git a/hotspot/src/share/vm/libadt/dict.cpp b/hotspot/src/share/vm/libadt/dict.cpp index 3ac20d6c29e..003dd6a4f05 100644 --- a/hotspot/src/share/vm/libadt/dict.cpp +++ b/hotspot/src/share/vm/libadt/dict.cpp @@ -346,9 +346,12 @@ int32 cmpstr(const void *k1, const void *k2) { return strcmp((const char *)k1,(const char *)k2); } -// Slimey cheap key comparator. +// Cheap key comparator. int32 cmpkey(const void *key1, const void *key2) { - return (int32)((intptr_t)key1 - (intptr_t)key2); + if (key1 == key2) return 0; + intptr_t delta = (intptr_t)key1 - (intptr_t)key2; + if (delta > 0) return 1; + return -1; } //============================================================================= diff --git a/hotspot/src/share/vm/libadt/port.hpp b/hotspot/src/share/vm/libadt/port.hpp index 70034d09bbd..68a84f1a4ce 100644 --- a/hotspot/src/share/vm/libadt/port.hpp +++ b/hotspot/src/share/vm/libadt/port.hpp @@ -34,17 +34,6 @@ #include #include #include -#undef bzero -inline void bzero(void *b, int len) { memset(b,0,len); } -#undef bcopy -inline void bcopy(const void *s, void *d, size_t len) { memmove(d,s,len); } -#undef bcmp -inline int bcmp(const void *s,const void *t,int len) { return memcmp(s,t,len);} -extern "C" unsigned long strtoul(const char *s, char **end, int base); - -// Definition for sys_errlist varies from Sun 4.1 & Solaris. -// We use the new Solaris definition. -#include // Access to the C++ class virtual function pointer // Put the class in the macro diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 832a3331e19..5bb817f0280 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -610,6 +610,10 @@ void GenCollectedHeap::do_collection(bool full, Universe::print_heap_after_gc(); } +#ifdef TRACESPINNING + ParallelTaskTerminator::print_termination_counts(); +#endif + if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) { tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); vm_exit(-1); @@ -910,6 +914,13 @@ void GenCollectedHeap::object_iterate(ObjectClosure* cl) { perm_gen()->object_iterate(cl); } +void GenCollectedHeap::safe_object_iterate(ObjectClosure* cl) { + for (int i = 0; i < _n_gens; i++) { + _gens[i]->safe_object_iterate(cl); + } + perm_gen()->safe_object_iterate(cl); +} + void GenCollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { for (int i = 0; i < _n_gens; i++) { _gens[i]->object_iterate_since_last_GC(cl); diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index f9a4d508753..3ab20cfd19f 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -215,6 +215,7 @@ public: void oop_iterate(OopClosure* cl); void oop_iterate(MemRegion mr, OopClosure* cl); void object_iterate(ObjectClosure* cl); + void safe_object_iterate(ObjectClosure* cl); void object_iterate_since_last_GC(ObjectClosure* cl); Space* space_containing(const void* addr) const; diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp index 5167db243b6..d7b1d9f871d 100644 --- a/hotspot/src/share/vm/memory/generation.cpp +++ b/hotspot/src/share/vm/memory/generation.cpp @@ -319,6 +319,21 @@ void Generation::object_iterate(ObjectClosure* cl) { space_iterate(&blk); } +class GenerationSafeObjIterateClosure : public SpaceClosure { + private: + ObjectClosure* _cl; + public: + virtual void do_space(Space* s) { + s->safe_object_iterate(_cl); + } + GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {} +}; + +void Generation::safe_object_iterate(ObjectClosure* cl) { + GenerationSafeObjIterateClosure blk(cl); + space_iterate(&blk); +} + void Generation::prepare_for_compaction(CompactPoint* cp) { // Generic implementation, can be specialized CompactibleSpace* space = first_compaction_space(); diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index 0f0e74e4794..206949901e4 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -518,6 +518,11 @@ class Generation: public CHeapObj { // each. virtual void object_iterate(ObjectClosure* cl); + // Iterate over all safe objects in the generation, calling "cl.do_object" on + // each. An object is safe if its references point to other objects in + // the heap. This defaults to object_iterate() unless overridden. + virtual void safe_object_iterate(ObjectClosure* cl); + // Iterate over all objects allocated in the generation since the last // collection, calling "cl.do_object" on each. The generation must have // been initialized properly to support this function, or else this call diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp index e3d6fbd7b5a..3bc17bea600 100644 --- a/hotspot/src/share/vm/memory/heapInspection.cpp +++ b/hotspot/src/share/vm/memory/heapInspection.cpp @@ -263,6 +263,9 @@ void HeapInspection::heap_inspection(outputStream* st) { if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(&ric); // Report if certain classes are not counted because of @@ -317,5 +320,8 @@ void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray* // Iterate over objects in the heap FindInstanceClosure fic(k, result); + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(&fic); } diff --git a/hotspot/src/share/vm/memory/oopFactory.cpp b/hotspot/src/share/vm/memory/oopFactory.cpp index e9ea08d3b23..32bd1f82236 100644 --- a/hotspot/src/share/vm/memory/oopFactory.cpp +++ b/hotspot/src/share/vm/memory/oopFactory.cpp @@ -82,15 +82,19 @@ objArrayOop oopFactory::new_system_objArray(int length, TRAPS) { } -constantPoolOop oopFactory::new_constantPool(int length, TRAPS) { +constantPoolOop oopFactory::new_constantPool(int length, + bool is_conc_safe, + TRAPS) { constantPoolKlass* ck = constantPoolKlass::cast(Universe::constantPoolKlassObj()); - return ck->allocate(length, CHECK_NULL); + return ck->allocate(length, is_conc_safe, CHECK_NULL); } -constantPoolCacheOop oopFactory::new_constantPoolCache(int length, TRAPS) { +constantPoolCacheOop oopFactory::new_constantPoolCache(int length, + bool is_conc_safe, + TRAPS) { constantPoolCacheKlass* ck = constantPoolCacheKlass::cast(Universe::constantPoolCacheKlassObj()); - return ck->allocate(length, CHECK_NULL); + return ck->allocate(length, is_conc_safe, CHECK_NULL); } @@ -105,11 +109,13 @@ constMethodOop oopFactory::new_constMethod(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, int checked_exceptions_length, + bool is_conc_safe, TRAPS) { klassOop cmkObj = Universe::constMethodKlassObj(); constMethodKlass* cmk = constMethodKlass::cast(cmkObj); return cmk->allocate(byte_code_size, compressed_line_number_size, localvariable_table_length, checked_exceptions_length, + is_conc_safe, CHECK_NULL); } @@ -117,14 +123,17 @@ constMethodOop oopFactory::new_constMethod(int byte_code_size, methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags, int compressed_line_number_size, int localvariable_table_length, - int checked_exceptions_length, TRAPS) { + int checked_exceptions_length, + bool is_conc_safe, + TRAPS) { methodKlass* mk = methodKlass::cast(Universe::methodKlassObj()); assert(!access_flags.is_native() || byte_code_size == 0, "native methods should not contain byte codes"); constMethodOop cm = new_constMethod(byte_code_size, compressed_line_number_size, localvariable_table_length, - checked_exceptions_length, CHECK_NULL); + checked_exceptions_length, + is_conc_safe, CHECK_NULL); constMethodHandle rw(THREAD, cm); return mk->allocate(rw, access_flags, CHECK_NULL); } diff --git a/hotspot/src/share/vm/memory/oopFactory.hpp b/hotspot/src/share/vm/memory/oopFactory.hpp index 855e0fcf43e..a0db0f52172 100644 --- a/hotspot/src/share/vm/memory/oopFactory.hpp +++ b/hotspot/src/share/vm/memory/oopFactory.hpp @@ -81,8 +81,12 @@ class oopFactory: AllStatic { static symbolHandle new_symbol_handle(const char* name, TRAPS) { return new_symbol_handle(name, (int)strlen(name), CHECK_(symbolHandle())); } // Constant pools - static constantPoolOop new_constantPool (int length, TRAPS); - static constantPoolCacheOop new_constantPoolCache(int length, TRAPS); + static constantPoolOop new_constantPool (int length, + bool is_conc_safe, + TRAPS); + static constantPoolCacheOop new_constantPoolCache(int length, + bool is_conc_safe, + TRAPS); // Instance classes static klassOop new_instanceKlass(int vtable_len, int itable_len, int static_field_size, @@ -93,9 +97,20 @@ private: static constMethodOop new_constMethod(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, - int checked_exceptions_length, TRAPS); + int checked_exceptions_length, + bool is_conc_safe, + TRAPS); public: - static methodOop new_method(int byte_code_size, AccessFlags access_flags, int compressed_line_number_size, int localvariable_table_length, int checked_exceptions_length, TRAPS); + // Set is_conc_safe for methods which cannot safely be + // processed by concurrent GC even after the return of + // the method. + static methodOop new_method(int byte_code_size, + AccessFlags access_flags, + int compressed_line_number_size, + int localvariable_table_length, + int checked_exceptions_length, + bool is_conc_safe, + TRAPS); // Method Data containers static methodDataOop new_methodData(methodHandle method, TRAPS); diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 073886f2f93..ac6f4777e5f 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -721,12 +721,6 @@ ReferenceProcessor::process_phase3(DiscoveredList& refs_list, iter.obj(), iter.obj()->blueprint()->internal_name()); } assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); - // If discovery is concurrent, we may have objects with null referents, - // being those that were concurrently cleared after they were discovered - // (and not subsequently precleaned). - assert( (discovery_is_atomic() && iter.referent()->is_oop()) - || (!discovery_is_atomic() && iter.referent()->is_oop_or_null(UseConcMarkSweepGC)), - "Adding a bad referent"); iter.next(); } // Remember to keep sentinel pointer around diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index 652d585bb8f..00f97001384 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -569,7 +569,15 @@ void Space::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) { if (prev > mr.start()) { region_start_addr = prev; blk_start_addr = prev; - assert(blk_start_addr == block_start(region_start_addr), "invariant"); + // The previous invocation may have pushed "prev" beyond the + // last allocated block yet there may be still be blocks + // in this region due to a particular coalescing policy. + // Relax the assertion so that the case where the unallocated + // block is maintained and "prev" is beyond the unallocated + // block does not cause the assertion to fire. + assert((BlockOffsetArrayUseUnallocatedBlock && + (!is_in(prev))) || + (blk_start_addr == block_start(region_start_addr)), "invariant"); } else { region_start_addr = mr.start(); blk_start_addr = block_start(region_start_addr); @@ -705,6 +713,12 @@ void ContiguousSpace::object_iterate(ObjectClosure* blk) { object_iterate_from(bm, blk); } +// For a continguous space object_iterate() and safe_object_iterate() +// are the same. +void ContiguousSpace::safe_object_iterate(ObjectClosure* blk) { + object_iterate(blk); +} + void ContiguousSpace::object_iterate_from(WaterMark mark, ObjectClosure* blk) { assert(mark.space() == this, "Mark does not match space"); HeapWord* p = mark.point(); diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index a102c5f220c..f055638e8dd 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -193,6 +193,9 @@ class Space: public CHeapObj { // each. Objects allocated by applications of the closure are not // included in the iteration. virtual void object_iterate(ObjectClosure* blk) = 0; + // Similar to object_iterate() except only iterates over + // objects whose internal references point to objects in the space. + virtual void safe_object_iterate(ObjectClosure* blk) = 0; // Iterate over all objects that intersect with mr, calling "cl->do_object" // on each. There is an exception to this: if this closure has already @@ -843,6 +846,9 @@ class ContiguousSpace: public CompactibleSpace { void oop_iterate(OopClosure* cl); void oop_iterate(MemRegion mr, OopClosure* cl); void object_iterate(ObjectClosure* blk); + // For contiguous spaces this method will iterate safely over objects + // in the space (i.e., between bottom and top) when at a safepoint. + void safe_object_iterate(ObjectClosure* blk); void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl); // iterates on objects up to the safe limit HeapWord* object_iterate_careful(ObjectClosureCareful* cl); diff --git a/hotspot/src/share/vm/oops/constMethodKlass.cpp b/hotspot/src/share/vm/oops/constMethodKlass.cpp index 802c4430afa..f2fe1706a16 100644 --- a/hotspot/src/share/vm/oops/constMethodKlass.cpp +++ b/hotspot/src/share/vm/oops/constMethodKlass.cpp @@ -49,10 +49,16 @@ bool constMethodKlass::oop_is_parsable(oop obj) const { return constMethodOop(obj)->object_is_parsable(); } +bool constMethodKlass::oop_is_conc_safe(oop obj) const { + assert(obj->is_constMethod(), "must be constMethod oop"); + return constMethodOop(obj)->is_conc_safe(); +} + constMethodOop constMethodKlass::allocate(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, int checked_exceptions_length, + bool is_conc_safe, TRAPS) { int size = constMethodOopDesc::object_size(byte_code_size, @@ -75,6 +81,7 @@ constMethodOop constMethodKlass::allocate(int byte_code_size, compressed_line_number_size, localvariable_table_length); assert(cm->size() == size, "wrong size for object"); + cm->set_is_conc_safe(is_conc_safe); cm->set_partially_loaded(); assert(cm->is_parsable(), "Is safely parsable by gc"); return cm; diff --git a/hotspot/src/share/vm/oops/constMethodKlass.hpp b/hotspot/src/share/vm/oops/constMethodKlass.hpp index 87fc9c3156d..a3f7d9710f7 100644 --- a/hotspot/src/share/vm/oops/constMethodKlass.hpp +++ b/hotspot/src/share/vm/oops/constMethodKlass.hpp @@ -32,12 +32,16 @@ public: // Testing bool oop_is_constMethod() const { return true; } virtual bool oop_is_parsable(oop obj) const; + virtual bool oop_is_conc_safe(oop obj) const; + // Allocation DEFINE_ALLOCATE_PERMANENT(constMethodKlass); constMethodOop allocate(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, - int checked_exceptions_length, TRAPS); + int checked_exceptions_length, + bool is_conc_safe, + TRAPS); static klassOop create_klass(TRAPS); // Sizing diff --git a/hotspot/src/share/vm/oops/constMethodOop.hpp b/hotspot/src/share/vm/oops/constMethodOop.hpp index e9ffa4b66bc..4669e6a852f 100644 --- a/hotspot/src/share/vm/oops/constMethodOop.hpp +++ b/hotspot/src/share/vm/oops/constMethodOop.hpp @@ -104,6 +104,7 @@ private: // loads and stores. This value may updated and read without a lock by // multiple threads, so is volatile. volatile uint64_t _fingerprint; + volatile bool _is_conc_safe; // if true, safe for concurrent GC processing public: oop* oop_block_beg() const { return adr_method(); } @@ -273,6 +274,8 @@ public: oop* adr_method() const { return (oop*)&_method; } oop* adr_stackmap_data() const { return (oop*)&_stackmap_data; } oop* adr_exception_table() const { return (oop*)&_exception_table; } + bool is_conc_safe() { return _is_conc_safe; } + void set_is_conc_safe(bool v) { _is_conc_safe = v; } // Unique id for the method static const u2 MAX_IDNUM; diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.cpp b/hotspot/src/share/vm/oops/constantPoolKlass.cpp index 593b74668ff..2a17c00e1ce 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp @@ -25,7 +25,7 @@ # include "incls/_precompiled.incl" # include "incls/_constantPoolKlass.cpp.incl" -constantPoolOop constantPoolKlass::allocate(int length, TRAPS) { +constantPoolOop constantPoolKlass::allocate(int length, bool is_conc_safe, TRAPS) { int size = constantPoolOopDesc::object_size(length); KlassHandle klass (THREAD, as_klassOop()); constantPoolOop c = @@ -38,6 +38,9 @@ constantPoolOop constantPoolKlass::allocate(int length, TRAPS) { c->set_flags(0); // only set to non-zero if constant pool is merged by RedefineClasses c->set_orig_length(0); + // if constant pool may change during RedefineClasses, it is created + // unsafe for GC concurrent processing. + c->set_is_conc_safe(is_conc_safe); // all fields are initialized; needed for GC // initialize tag array @@ -207,6 +210,11 @@ int constantPoolKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) return size; } +bool constantPoolKlass::oop_is_conc_safe(oop obj) const { + assert(obj->is_constantPool(), "must be constantPool"); + return constantPoolOop(obj)->is_conc_safe(); +} + #ifndef SERIALGC int constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert (obj->is_constantPool(), "obj must be constant pool"); diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.hpp b/hotspot/src/share/vm/oops/constantPoolKlass.hpp index 324efbec023..2f9efc285ef 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.hpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.hpp @@ -34,7 +34,7 @@ class constantPoolKlass : public Klass { // Allocation DEFINE_ALLOCATE_PERMANENT(constantPoolKlass); - constantPoolOop allocate(int length, TRAPS); + constantPoolOop allocate(int length, bool is_conc_safe, TRAPS); static klassOop create_klass(TRAPS); // Casting from klassOop @@ -48,6 +48,8 @@ class constantPoolKlass : public Klass { int object_size() const { return align_object_size(header_size()); } // Garbage collection + // Returns true is the object is safe for GC concurrent processing. + virtual bool oop_is_conc_safe(oop obj) const; void oop_follow_contents(oop obj); int oop_adjust_pointers(oop obj); diff --git a/hotspot/src/share/vm/oops/constantPoolOop.cpp b/hotspot/src/share/vm/oops/constantPoolOop.cpp index 842f8067934..e90bda568e9 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.cpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp @@ -962,7 +962,7 @@ static void print_cpool_bytes(jint cnt, u1 *bytes) { } case JVM_CONSTANT_Long: { u8 val = Bytes::get_Java_u8(bytes); - printf("long %lldl", *(jlong *) &val); + printf("long "INT64_FORMAT, *(jlong *) &val); ent_size = 8; idx++; // Long takes two cpool slots break; diff --git a/hotspot/src/share/vm/oops/constantPoolOop.hpp b/hotspot/src/share/vm/oops/constantPoolOop.hpp index 5627059091f..fd2264c1eab 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.hpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp @@ -43,6 +43,8 @@ class constantPoolOopDesc : public oopDesc { klassOop _pool_holder; // the corresponding class int _flags; // a few header bits to describe contents for GC int _length; // number of elements in the array + volatile bool _is_conc_safe; // if true, safe for concurrent + // GC processing // only set to non-zero if constant pool is merged by RedefineClasses int _orig_length; @@ -379,6 +381,9 @@ class constantPoolOopDesc : public oopDesc { static int object_size(int length) { return align_object_size(header_size() + length); } int object_size() { return object_size(length()); } + bool is_conc_safe() { return _is_conc_safe; } + void set_is_conc_safe(bool v) { _is_conc_safe = v; } + friend class constantPoolKlass; friend class ClassFileParser; friend class SystemDictionary; diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.cpp b/hotspot/src/share/vm/oops/cpCacheKlass.cpp index 241914dca65..95fd11ded28 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp @@ -32,13 +32,43 @@ int constantPoolCacheKlass::oop_size(oop obj) const { } -constantPoolCacheOop constantPoolCacheKlass::allocate(int length, TRAPS) { +constantPoolCacheOop constantPoolCacheKlass::allocate(int length, + bool is_conc_safe, + TRAPS) { // allocate memory int size = constantPoolCacheOopDesc::object_size(length); + KlassHandle klass (THREAD, as_klassOop()); - constantPoolCacheOop cache = (constantPoolCacheOop) - CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + + // This is the original code. The code from permanent_obj_allocate() + // was in-lined to allow the setting of is_conc_safe before the klass + // is installed. + // constantPoolCacheOop cache = (constantPoolCacheOop) + // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + + oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); + constantPoolCacheOop cache = (constantPoolCacheOop) obj; + cache->set_is_conc_safe(is_conc_safe); + // The store to is_conc_safe must be visible before the klass + // is set. This should be done safely because _is_conc_safe has + // been declared volatile. If there are any problems, consider adding + // OrderAccess::storestore(); + CollectedHeap::post_allocation_install_obj_klass(klass, obj, size); + NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, + size)); + + // The length field affects the size of the object. The allocation + // above allocates the correct size (see calculation of "size") but + // the size() method of the constant pool cache oop will not reflect + // that size until the correct length is set. cache->set_length(length); + + // The store of the length must be visible before is_conc_safe is + // set to a safe state. + // This should be done safely because _is_conc_safe has + // been declared volatile. If there are any problems, consider adding + // OrderAccess::storestore(); + cache->set_is_conc_safe(methodOopDesc::IsSafeConc); cache->set_constant_pool(NULL); return cache; } @@ -114,7 +144,6 @@ int constantPoolCacheKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegio return size; } - int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); constantPoolCacheOop cache = (constantPoolCacheOop)obj; @@ -131,6 +160,11 @@ int constantPoolCacheKlass::oop_adjust_pointers(oop obj) { return size; } +bool constantPoolCacheKlass::oop_is_conc_safe(oop obj) const { + assert(obj->is_constantPoolCache(), "should be constant pool"); + return constantPoolCacheOop(obj)->is_conc_safe(); +} + #ifndef SERIALGC void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.hpp b/hotspot/src/share/vm/oops/cpCacheKlass.hpp index ea826671dbc..299910052ae 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.hpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.hpp @@ -32,7 +32,7 @@ class constantPoolCacheKlass: public Klass { // Allocation DEFINE_ALLOCATE_PERMANENT(constantPoolCacheKlass); - constantPoolCacheOop allocate(int length, TRAPS); + constantPoolCacheOop allocate(int length, bool is_conc_safe, TRAPS); static klassOop create_klass(TRAPS); // Casting from klassOop @@ -48,6 +48,7 @@ class constantPoolCacheKlass: public Klass { // Garbage collection void oop_follow_contents(oop obj); int oop_adjust_pointers(oop obj); + virtual bool oop_is_conc_safe(oop obj) const; // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS diff --git a/hotspot/src/share/vm/oops/cpCacheOop.hpp b/hotspot/src/share/vm/oops/cpCacheOop.hpp index ccdb4472e2c..c5ba6052191 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp @@ -291,6 +291,9 @@ class constantPoolCacheOopDesc: public oopDesc { private: int _length; constantPoolOop _constant_pool; // the corresponding constant pool + // If true, safe for concurrent GC processing, + // Set unconditionally in constantPoolCacheKlass::allocate() + volatile bool _is_conc_safe; // Sizing debug_only(friend class ClassVerifier;) @@ -316,6 +319,12 @@ class constantPoolCacheOopDesc: public oopDesc { constantPoolOop constant_pool() const { return _constant_pool; } ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; } + // GC support + // If the _length field has not been set, the size of the + // constantPoolCache cannot be correctly calculated. + bool is_conc_safe() { return _is_conc_safe; } + void set_is_conc_safe(bool v) { _is_conc_safe = v; } + // Code generation static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 46852c02ee1..881da970d03 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -606,8 +606,19 @@ class Klass : public Klass_vtbl { #undef assert_same_query // Unless overridden, oop is parsable if it has a klass pointer. + // Parsability of an object is object specific. virtual bool oop_is_parsable(oop obj) const { return true; } + // Unless overridden, oop is safe for concurrent GC processing + // after its allocation is complete. The exception to + // this is the case where objects are changed after allocation. + // Class redefinition is one of the known exceptions. During + // class redefinition, an allocated class can changed in order + // order to create a merged class (the combiniation of the + // old class definition that has to be perserved and the new class + // definition which is being created. + virtual bool oop_is_conc_safe(oop obj) const { return true; } + // Access flags AccessFlags access_flags() const { return _access_flags; } void set_access_flags(AccessFlags flags) { _access_flags = flags; } diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index 8a5507cbac8..c239ccf1a2c 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -792,15 +792,34 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod AccessFlags flags = m->access_flags(); int checked_exceptions_len = m->checked_exceptions_length(); int localvariable_len = m->localvariable_table_length(); - methodOop newm_oop = oopFactory::new_method(new_code_length, flags, new_compressed_linenumber_size, localvariable_len, checked_exceptions_len, CHECK_(methodHandle())); + // Allocate newm_oop with the is_conc_safe parameter set + // to IsUnsafeConc to indicate that newm_oop is not yet + // safe for concurrent processing by a GC. + methodOop newm_oop = oopFactory::new_method(new_code_length, + flags, + new_compressed_linenumber_size, + localvariable_len, + checked_exceptions_len, + IsUnsafeConc, + CHECK_(methodHandle())); methodHandle newm (THREAD, newm_oop); int new_method_size = newm->method_size(); // Create a shallow copy of methodOopDesc part, but be careful to preserve the new constMethodOop constMethodOop newcm = newm->constMethod(); int new_const_method_size = newm->constMethod()->object_size(); + memcpy(newm(), m(), sizeof(methodOopDesc)); // Create shallow copy of constMethodOopDesc, but be careful to preserve the methodOop + // is_conc_safe is set to false because that is the value of + // is_conc_safe initialzied into newcm and the copy should + // not overwrite that value. During the window during which it is + // tagged as unsafe, some extra work could be needed during precleaning + // or concurrent marking but those phases will be correct. Setting and + // resetting is done in preference to a careful copying into newcm to + // avoid having to know the precise layout of a constMethodOop. + m->constMethod()->set_is_conc_safe(false); memcpy(newcm, m->constMethod(), sizeof(constMethodOopDesc)); + m->constMethod()->set_is_conc_safe(true); // Reset correct method/const method, method size, and parameter info newcm->set_method(newm()); newm->set_constMethod(newcm); @@ -831,6 +850,10 @@ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_cod m->localvariable_table_start(), localvariable_len * sizeof(LocalVariableTableElement)); } + + // Only set is_conc_safe to true when changes to newcm are + // complete. + newcm->set_is_conc_safe(true); return newm; } diff --git a/hotspot/src/share/vm/oops/methodOop.hpp b/hotspot/src/share/vm/oops/methodOop.hpp index 965181c664d..8b03a68380a 100644 --- a/hotspot/src/share/vm/oops/methodOop.hpp +++ b/hotspot/src/share/vm/oops/methodOop.hpp @@ -129,6 +129,10 @@ class methodOopDesc : public oopDesc { volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry public: + + static const bool IsUnsafeConc = false; + static const bool IsSafeConc = true; + // accessors for instance variables constMethodOop constMethod() const { return _constMethod; } void set_constMethod(constMethodOop xconst) { oop_store_without_check((oop*)&_constMethod, (oop)xconst); } diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 07c2ba5ac52..ba13ca63c44 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -108,6 +108,13 @@ class oopDesc { // installation of their klass pointer. bool is_parsable(); + // Some perm gen objects that have been allocated and initialized + // can be changed by the VM when not at a safe point (class rededfinition + // is an example). Such objects should not be examined by the + // concurrent processing of a garbage collector if is_conc_safe() + // returns false. + bool is_conc_safe(); + // type test operations (inlined in oop.inline.h) bool is_instance() const; bool is_instanceRef() const; diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 0c7a3967f48..9161310de60 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -435,6 +435,10 @@ inline bool oopDesc::is_parsable() { return blueprint()->oop_is_parsable(this); } +inline bool oopDesc::is_conc_safe() { + return blueprint()->oop_is_conc_safe(this); +} + inline void update_barrier_set(void* p, oop v) { assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); oopDesc::bs()->write_ref_field(p, v); diff --git a/hotspot/src/share/vm/oops/oopsHierarchy.hpp b/hotspot/src/share/vm/oops/oopsHierarchy.hpp index 597dafe3de8..06c64d0e46f 100644 --- a/hotspot/src/share/vm/oops/oopsHierarchy.hpp +++ b/hotspot/src/share/vm/oops/oopsHierarchy.hpp @@ -126,8 +126,11 @@ public: operator jobject () const { return (jobject)obj(); } // from javaClasses.cpp operator JavaThread* () const { return (JavaThread*)obj(); } + +#ifndef _LP64 // from jvm.cpp operator jlong* () const { return (jlong*)obj(); } +#endif // from parNewGeneration and other things that want to get to the end of // an oop for stuff (like constMethodKlass.cpp, objArrayKlass.cpp) diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 1de186518d9..cf15fa7c4fb 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -880,6 +880,7 @@ void PhaseCFG::dump_headers() { } void PhaseCFG::verify( ) const { +#ifdef ASSERT // Verify sane CFG for( uint i = 0; i < _num_blocks; i++ ) { Block *b = _blocks[i]; @@ -894,10 +895,20 @@ void PhaseCFG::verify( ) const { "CreateEx must be first instruction in block" ); } for( uint k = 0; k < n->req(); k++ ) { - Node *use = n->in(k); - if( use && use != n ) { - assert( _bbs[use->_idx] || use->is_Con(), + Node *def = n->in(k); + if( def && def != n ) { + assert( _bbs[def->_idx] || def->is_Con(), "must have block; constants for debug info ok" ); + // Verify that instructions in the block is in correct order. + // Uses must follow their definition if they are at the same block. + // Mostly done to check that MachSpillCopy nodes are placed correctly + // when CreateEx node is moved in build_ifg_physical(). + if( _bbs[def->_idx] == b && + !(b->head()->is_Loop() && n->is_Phi()) && + // See (+++) comment in reg_split.cpp + !(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) { + assert( b->find_node(def) < j, "uses must follow definitions" ); + } } } } @@ -914,6 +925,7 @@ void PhaseCFG::verify( ) const { assert( b->_num_succs == 2, "Conditional branch must have two targets"); } } +#endif } #endif diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 844d637e519..3a516ab98bd 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -191,6 +191,9 @@ notproduct(bool, VerifyHashTableKeys, true, \ "Verify the immutability of keys in the VN hash tables") \ \ + notproduct(bool, VerifyRegisterAllocator , false, \ + "Verify Register Allocator") \ + \ develop_pd(intx, FLOATPRESSURE, \ "Number of float LRG's that constitute high register pressure") \ \ diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index fdee151f1e9..e29cc0d58e3 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -858,12 +858,18 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // convert the one to the other. const TypePtr* ttp = _type->make_ptr(); const TypeInstPtr* ttip = (ttp != NULL) ? ttp->isa_instptr() : NULL; + const TypeKlassPtr* ttkp = (ttp != NULL) ? ttp->isa_klassptr() : NULL; bool is_intf = false; if (ttip != NULL) { ciKlass* k = ttip->klass(); if (k->is_loaded() && k->is_interface()) is_intf = true; } + if (ttkp != NULL) { + ciKlass* k = ttkp->klass(); + if (k->is_loaded() && k->is_interface()) + is_intf = true; + } // Default case: merge all inputs const Type *t = Type::TOP; // Merged type starting value @@ -921,6 +927,8 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // uplift the type. if( !t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface() ) { assert(ft == _type, ""); } // Uplift to interface + else if( !t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface() ) + { assert(ft == _type, ""); } // Uplift to interface // Otherwise it's something stupid like non-overlapping int ranges // found on dying counted loops. else @@ -936,6 +944,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // because the type system doesn't interact well with interfaces. const TypePtr *jtp = jt->make_ptr(); const TypeInstPtr *jtip = (jtp != NULL) ? jtp->isa_instptr() : NULL; + const TypeKlassPtr *jtkp = (jtp != NULL) ? jtp->isa_klassptr() : NULL; if( jtip && ttip ) { if( jtip->is_loaded() && jtip->klass()->is_interface() && ttip->is_loaded() && !ttip->klass()->is_interface() ) { @@ -945,6 +954,14 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { jt = ft; } } + if( jtkp && ttkp ) { + if( jtkp->is_loaded() && jtkp->klass()->is_interface() && + ttkp->is_loaded() && !ttkp->klass()->is_interface() ) { + assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) || + ft->isa_narrowoop() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), ""); + jt = ft; + } + } if (jt != ft && jt->base() == ft->base()) { if (jt->isa_int() && jt->is_int()->_lo == ft->is_int()->_lo && diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 0456db5dc11..82558d8f577 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -228,6 +228,11 @@ void PhaseChaitin::Register_Allocate() { // them for real. de_ssa(); +#ifdef ASSERT + // Veify the graph before RA. + verify(&live_arena); +#endif + { NOT_PRODUCT( Compile::TracePhase t3("computeLive", &_t_computeLive, TimeCompiler); ) _live = NULL; // Mark live as being not available @@ -306,12 +311,6 @@ void PhaseChaitin::Register_Allocate() { C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after physical split"); if (C->failing()) return; -#ifdef ASSERT - if( VerifyOpto ) { - _cfg.verify(); - verify_base_ptrs(&live_arena); - } -#endif NOT_PRODUCT( C->verify_graph_edges(); ) compact(); // Compact LRGs; return new lower max lrg @@ -340,7 +339,7 @@ void PhaseChaitin::Register_Allocate() { compress_uf_map_for_nodes(); #ifdef ASSERT - if( VerifyOpto ) _ifg->verify(this); + verify(&live_arena, true); #endif } else { ifg.SquareUp(); @@ -376,12 +375,6 @@ void PhaseChaitin::Register_Allocate() { // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after split"); if (C->failing()) return; -#ifdef ASSERT - if( VerifyOpto ) { - _cfg.verify(); - verify_base_ptrs(&live_arena); - } -#endif compact(); // Compact LRGs; return new lower max lrg @@ -412,7 +405,7 @@ void PhaseChaitin::Register_Allocate() { } compress_uf_map_for_nodes(); #ifdef ASSERT - if( VerifyOpto ) _ifg->verify(this); + verify(&live_arena, true); #endif cache_lrg_info(); // Count degree of LRGs @@ -432,6 +425,11 @@ void PhaseChaitin::Register_Allocate() { // Peephole remove copies post_allocate_copy_removal(); +#ifdef ASSERT + // Veify the graph after RA. + verify(&live_arena); +#endif + // max_reg is past the largest *register* used. // Convert that to a frame_slot number. if( _max_reg <= _matcher._new_SP ) @@ -956,7 +954,7 @@ void PhaseChaitin::Simplify( ) { while ((neighbor = elements.next()) != 0) { LRG *n = &lrgs(neighbor); #ifdef ASSERT - if( VerifyOpto ) { + if( VerifyOpto || VerifyRegisterAllocator ) { assert( _ifg->effective_degree(neighbor) == n->degree(), "" ); } #endif diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index 9c7cc593e40..307d6110c04 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -491,6 +491,8 @@ private: // Verify that base pointers and derived pointers are still sane void verify_base_ptrs( ResourceArea *a ) const; + void verify( ResourceArea *a, bool verify_ifg = false ) const; + void dump_for_spill_split_recycle() const; public: diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 14b43120059..bbb3e79990e 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -129,7 +129,7 @@ macro(JumpProj) macro(LShiftI) macro(LShiftL) macro(LoadB) -macro(LoadC) +macro(LoadUS) macro(LoadD) macro(LoadD_unaligned) macro(LoadF) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index de05e5fb84a..7c6f751f8ff 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -2005,7 +2005,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { case Op_StoreP: case Op_StoreN: case Op_LoadB: - case Op_LoadC: + case Op_LoadUS: case Op_LoadI: case Op_LoadKlass: case Op_LoadNKlass: diff --git a/hotspot/src/share/vm/opto/divnode.cpp b/hotspot/src/share/vm/opto/divnode.cpp index 94240873ef5..67cad067960 100644 --- a/hotspot/src/share/vm/opto/divnode.cpp +++ b/hotspot/src/share/vm/opto/divnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -244,42 +244,73 @@ static bool magic_long_divide_constants(jlong d, jlong &M, jint &s) { //---------------------long_by_long_mulhi-------------------------------------- // Generate ideal node graph for upper half of a 64 bit x 64 bit multiplication -static Node *long_by_long_mulhi( PhaseGVN *phase, Node *dividend, jlong magic_const) { +static Node* long_by_long_mulhi(PhaseGVN* phase, Node* dividend, jlong magic_const) { // If the architecture supports a 64x64 mulhi, there is // no need to synthesize it in ideal nodes. if (Matcher::has_match_rule(Op_MulHiL)) { - Node *v = phase->longcon(magic_const); + Node* v = phase->longcon(magic_const); return new (phase->C, 3) MulHiLNode(dividend, v); } + // Taken from Hacker's Delight, Fig. 8-2. Multiply high signed. + // (http://www.hackersdelight.org/HDcode/mulhs.c) + // + // int mulhs(int u, int v) { + // unsigned u0, v0, w0; + // int u1, v1, w1, w2, t; + // + // u0 = u & 0xFFFF; u1 = u >> 16; + // v0 = v & 0xFFFF; v1 = v >> 16; + // w0 = u0*v0; + // t = u1*v0 + (w0 >> 16); + // w1 = t & 0xFFFF; + // w2 = t >> 16; + // w1 = u0*v1 + w1; + // return u1*v1 + w2 + (w1 >> 16); + // } + // + // Note: The version above is for 32x32 multiplications, while the + // following inline comments are adapted to 64x64. + const int N = 64; - Node *u_hi = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); - Node *u_lo = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); + // u0 = u & 0xFFFFFFFF; u1 = u >> 32; + Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); + Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); - Node *v_hi = phase->longcon(magic_const >> N/2); - Node *v_lo = phase->longcon(magic_const & 0XFFFFFFFF); + // v0 = v & 0xFFFFFFFF; v1 = v >> 32; + Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF); + Node* v1 = phase->longcon(magic_const >> (N / 2)); - Node *hihi_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_hi)); - Node *hilo_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_lo)); - Node *lohi_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_hi)); - Node *lolo_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_lo)); + // w0 = u0*v0; + Node* w0 = phase->transform(new (phase->C, 3) MulLNode(u0, v0)); - Node *t1 = phase->transform(new (phase->C, 3) URShiftLNode(lolo_product, phase->intcon(N / 2))); - Node *t2 = phase->transform(new (phase->C, 3) AddLNode(hilo_product, t1)); + // t = u1*v0 + (w0 >> 32); + Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0)); + Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2))); + Node* t = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp)); - // Construct both t3 and t4 before transforming so t2 doesn't go dead - // prematurely. - Node *t3 = new (phase->C, 3) RShiftLNode(t2, phase->intcon(N / 2)); - Node *t4 = new (phase->C, 3) AndLNode(t2, phase->longcon(0xFFFFFFFF)); - t3 = phase->transform(t3); - t4 = phase->transform(t4); + // w1 = t & 0xFFFFFFFF; + Node* w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF)); - Node *t5 = phase->transform(new (phase->C, 3) AddLNode(t4, lohi_product)); - Node *t6 = phase->transform(new (phase->C, 3) RShiftLNode(t5, phase->intcon(N / 2))); - Node *t7 = phase->transform(new (phase->C, 3) AddLNode(t3, hihi_product)); + // w2 = t >> 32; + Node* w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2)); - return new (phase->C, 3) AddLNode(t7, t6); + // 6732154: Construct both w1 and w2 before transforming, so t + // doesn't go dead prematurely. + w1 = phase->transform(w1); + w2 = phase->transform(w2); + + // w1 = u0*v1 + w1; + Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1)); + w1 = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1)); + + // return u1*v1 + w2 + (w1 >> 32); + Node* u1v1 = phase->transform(new (phase->C, 3) MulLNode(u1, v1)); + Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2)); + Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2))); + + return new (phase->C, 3) AddLNode(temp1, temp2); } @@ -976,7 +1007,7 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Expand mod if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) { - uint k = log2_long(con); // Extract k + uint k = exact_log2_long(con+1); // Extract k // Basic algorithm by David Detlefs. See fastmod_long.java for gory details. // Used to help a popular random number generator which does a long-mod diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index c3d9db916bc..b56fb157119 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -29,6 +29,9 @@ #include "incls/_precompiled.incl" #include "incls/_gcm.cpp.incl" +// To avoid float value underflow +#define MIN_BLOCK_FREQUENCY 1.e-35f + //----------------------------schedule_node_into_block------------------------- // Insert node n into block b. Look for projections of n and make sure they // are in b also. @@ -1380,6 +1383,13 @@ void PhaseCFG::Estimate_Block_Frequency() { } } +#ifdef ASSERT + for (uint i = 0; i < _num_blocks; i++ ) { + Block *b = _blocks[i]; + assert(b->_freq >= MIN_BLOCK_FREQUENCY, "Register Allocator requiers meaningful block frequency"); + } +#endif + #ifndef PRODUCT if (PrintCFGBlockFreq) { tty->print_cr("CFG Block Frequencies"); @@ -1877,7 +1887,9 @@ void CFGLoop::scale_freq() { float loop_freq = _freq * trip_count(); for (int i = 0; i < _members.length(); i++) { CFGElement* s = _members.at(i); - s->_freq *= loop_freq; + float block_freq = s->_freq * loop_freq; + if (block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY; + s->_freq = block_freq; } CFGLoop* ch = _child; while (ch != NULL) { diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 36a6eafde59..c0cb4ba0132 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1836,10 +1836,7 @@ void GraphKit::write_barrier_post(Node* oop_store, Node* obj, Node* adr, (CardTableModRefBS*)(Universe::heap()->barrier_set()); Node *b = _gvn.transform(new (C, 3) URShiftXNode( cast, _gvn.intcon(CardTableModRefBS::card_shift) )); // We store into a byte array, so do not bother to left-shift by zero - // Get base of card map - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), - "adjust this code"); - Node *c = makecon(TypeRawPtr::make((address)ct->byte_map_base)); + Node *c = byte_map_base_node(); // Combine Node *sb_ctl = control(); Node *sb_adr = _gvn.transform(new (C, 4) AddPNode( top()/*no base ptr*/, c, b )); @@ -2945,16 +2942,10 @@ Node* GraphKit::new_instance(Node* klass_node, // Now generate allocation code - // With escape analysis, the entire memory state is needed to be able to - // eliminate the allocation. If the allocations cannot be eliminated, this - // will be optimized to the raw slice when the allocation is expanded. - Node *mem; - if (C->do_escape_analysis()) { - mem = reset_memory(); - set_all_memory(mem); - } else { - mem = memory(Compile::AliasIdxRaw); - } + // The entire memory state is needed for slow path of the allocation + // since GC and deoptimization can happened. + Node *mem = reset_memory(); + set_all_memory(mem); // Create new memory state AllocateNode* alloc = new (C, AllocateNode::ParmLimit) @@ -3091,16 +3082,10 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) // Now generate allocation code - // With escape analysis, the entire memory state is needed to be able to - // eliminate the allocation. If the allocations cannot be eliminated, this - // will be optimized to the raw slice when the allocation is expanded. - Node *mem; - if (C->do_escape_analysis()) { - mem = reset_memory(); - set_all_memory(mem); - } else { - mem = memory(Compile::AliasIdxRaw); - } + // The entire memory state is needed for slow path of the allocation + // since GC and deoptimization can happened. + Node *mem = reset_memory(); + set_all_memory(mem); // Create new memory state // Create the AllocateArrayNode and its result projections AllocateArrayNode* alloc @@ -3233,12 +3218,11 @@ void GraphKit::g1_write_barrier_pre(Node* obj, // Now some of the values - Node* marking = __ load(no_ctrl, marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw); - Node* index = __ load(no_ctrl, index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw); - Node* buffer = __ load(no_ctrl, buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); + Node* marking = __ load(__ ctrl(), marking_adr, TypeInt::INT, active_type, Compile::AliasIdxRaw); // if (!marking) __ if_then(marking, BoolTest::ne, zero); { + Node* index = __ load(__ ctrl(), index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw); const Type* t1 = adr->bottom_type(); const Type* t2 = val->bottom_type(); @@ -3246,6 +3230,7 @@ void GraphKit::g1_write_barrier_pre(Node* obj, Node* orig = __ load(no_ctrl, adr, val_type, bt, alias_idx); // if (orig != NULL) __ if_then(orig, BoolTest::ne, null()); { + Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw); // load original value // alias_idx correct?? @@ -3365,14 +3350,6 @@ void GraphKit::g1_write_barrier_post(Node* store, const TypeFunc *tf = OptoRuntime::g1_wb_post_Type(); - // Get the address of the card table - CardTableModRefBS* ct = - (CardTableModRefBS*)(Universe::heap()->barrier_set()); - Node *card_table = __ makecon(TypeRawPtr::make((address)ct->byte_map_base)); - // Get base of card map - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - - // Offsets into the thread const int index_offset = in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()); @@ -3402,7 +3379,7 @@ void GraphKit::g1_write_barrier_post(Node* store, Node* card_offset = __ URShiftX( cast, __ ConI(CardTableModRefBS::card_shift) ); // Combine card table base and card offset - Node *card_adr = __ AddP(no_base, card_table, card_offset ); + Node *card_adr = __ AddP(no_base, byte_map_base_node(), card_offset ); // If we know the value being stored does it cross regions? diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index 0817ed3bfcb..160e3376c95 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -83,6 +83,18 @@ class GraphKit : public Phase { Node* zerocon(BasicType bt) const { return _gvn.zerocon(bt); } // (See also macro MakeConX in type.hpp, which uses intcon or longcon.) + // Helper for byte_map_base + Node* byte_map_base_node() { + // Get base of card map + CardTableModRefBS* ct = (CardTableModRefBS*)(Universe::heap()->barrier_set()); + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust users of this code"); + if (ct->byte_map_base != NULL) { + return makecon(TypeRawPtr::make((address)ct->byte_map_base)); + } else { + return null(); + } + } + jint find_int_con(Node* n, jint value_if_unknown) { return _gvn.find_int_con(n, value_if_unknown); } diff --git a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 6dfc5fc9c8a..ad45b566eda 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -557,7 +557,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { // max. 2 chars allowed if (value >= -9 && value <= 99) { - sprintf(buffer, "%d", value); + sprintf(buffer, INT64_FORMAT, value); print_prop(short_name, buffer); } else { print_prop(short_name, "L"); diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 1a352de722b..b3250513d7a 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -471,12 +471,28 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // for the "collect_gc_info" phase later. IndexSet liveout(_live->live(b)); uint last_inst = b->end_idx(); - // Compute last phi index - uint last_phi; - for( last_phi = 1; last_phi < last_inst; last_phi++ ) - if( !b->_nodes[last_phi]->is_Phi() ) + // Compute first nonphi node index + uint first_inst; + for( first_inst = 1; first_inst < last_inst; first_inst++ ) + if( !b->_nodes[first_inst]->is_Phi() ) break; + // Spills could be inserted before CreateEx node which should be + // first instruction in block after Phis. Move CreateEx up. + for( uint insidx = first_inst; insidx < last_inst; insidx++ ) { + Node *ex = b->_nodes[insidx]; + if( ex->is_SpillCopy() ) continue; + if( insidx > first_inst && ex->is_Mach() && + ex->as_Mach()->ideal_Opcode() == Op_CreateEx ) { + // If the CreateEx isn't above all the MachSpillCopies + // then move it to the top. + b->_nodes.remove(insidx); + b->_nodes.insert(first_inst, ex); + } + // Stop once a CreateEx or any other node is found + break; + } + // Reset block's register pressure values for each ifg construction uint pressure[2], hrp_index[2]; pressure[0] = pressure[1] = 0; @@ -485,7 +501,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // Liveout things are presumed live for the whole block. We accumulate // 'area' accordingly. If they get killed in the block, we'll subtract // the unused part of the block from the area. - int inst_count = last_inst - last_phi; + int inst_count = last_inst - first_inst; double cost = (inst_count <= 0) ? 0.0 : b->_freq * double(inst_count); assert(!(cost < 0.0), "negative spill cost" ); IndexSetIterator elements(&liveout); diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 341ddb08c14..dcedbd61f83 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -107,7 +107,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe was_store = false; switch( mach->ideal_Opcode() ) { case Op_LoadB: - case Op_LoadC: + case Op_LoadUS: case Op_LoadD: case Op_LoadF: case Op_LoadI: diff --git a/hotspot/src/share/vm/opto/live.cpp b/hotspot/src/share/vm/opto/live.cpp index 4127f67e1dd..d2ff515058c 100644 --- a/hotspot/src/share/vm/opto/live.cpp +++ b/hotspot/src/share/vm/opto/live.cpp @@ -271,9 +271,9 @@ void PhaseLive::dump( const Block *b ) const { //------------------------------verify_base_ptrs------------------------------- // Verify that base pointers and derived pointers are still sane. -// Basically, if a derived pointer is live at a safepoint, then its -// base pointer must be live also. void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const { +#ifdef ASSERT + Unique_Node_List worklist(a); for( uint i = 0; i < _cfg._num_blocks; i++ ) { Block *b = _cfg._blocks[i]; for( uint j = b->end_idx() + 1; j > 1; j-- ) { @@ -287,28 +287,81 @@ void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const { // Now scan for a live derived pointer if (jvms->oopoff() < sfpt->req()) { // Check each derived/base pair - for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx += 2) { + for (uint idx = jvms->oopoff(); idx < sfpt->req(); idx++) { Node *check = sfpt->in(idx); - uint j = 0; + bool is_derived = ((idx - jvms->oopoff()) & 1) == 0; // search upwards through spills and spill phis for AddP - while(true) { - if( !check ) break; - int idx = check->is_Copy(); - if( idx ) { - check = check->in(idx); - } else if( check->is_Phi() && check->_idx >= _oldphi ) { - check = check->in(1); - } else - break; - j++; - assert(j < 100000,"Derived pointer checking in infinite loop"); + worklist.clear(); + worklist.push(check); + uint k = 0; + while( k < worklist.size() ) { + check = worklist.at(k); + assert(check,"Bad base or derived pointer"); + // See PhaseChaitin::find_base_for_derived() for all cases. + int isc = check->is_Copy(); + if( isc ) { + worklist.push(check->in(isc)); + } else if( check->is_Phi() ) { + for (uint m = 1; m < check->req(); m++) + worklist.push(check->in(m)); + } else if( check->is_Con() ) { + if (is_derived) { + // Derived is NULL+offset + assert(!is_derived || check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad derived pointer"); + } else { + assert(check->bottom_type()->is_ptr()->_offset == 0,"Bad base pointer"); + // Base either ConP(NULL) or loadConP + if (check->is_Mach()) { + assert(check->as_Mach()->ideal_Opcode() == Op_ConP,"Bad base pointer"); + } else { + assert(check->Opcode() == Op_ConP && + check->bottom_type()->is_ptr()->ptr() == TypePtr::Null,"Bad base pointer"); + } + } + } else if( check->bottom_type()->is_ptr()->_offset == 0 ) { + if(check->is_Proj() || check->is_Mach() && + (check->as_Mach()->ideal_Opcode() == Op_CreateEx || + check->as_Mach()->ideal_Opcode() == Op_ThreadLocal || + check->as_Mach()->ideal_Opcode() == Op_CMoveP || + check->as_Mach()->ideal_Opcode() == Op_CheckCastPP || +#ifdef _LP64 + UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP || + UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN || +#endif + check->as_Mach()->ideal_Opcode() == Op_LoadP || + check->as_Mach()->ideal_Opcode() == Op_LoadKlass)) { + // Valid nodes + } else { + check->dump(); + assert(false,"Bad base or derived pointer"); + } + } else { + assert(is_derived,"Bad base pointer"); + assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer"); + } + k++; + assert(k < 100000,"Derived pointer checking in infinite loop"); } // End while - assert(check->is_Mach() && check->as_Mach()->ideal_Opcode() == Op_AddP,"Bad derived pointer") } } // End of check for derived pointers } // End of Kcheck for debug info } // End of if found a safepoint } // End of forall instructions in block } // End of forall blocks -} +#endif +} + +//------------------------------verify------------------------------------- +// Verify that graphs and base pointers are still sane. +void PhaseChaitin::verify( ResourceArea *a, bool verify_ifg ) const { +#ifdef ASSERT + if( VerifyOpto || VerifyRegisterAllocator ) { + _cfg.verify(); + verify_base_ptrs(a); + if(verify_ifg) + _ifg->verify(this); + } +#endif +} + #endif diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index 7e375992f1d..fba4a350bbb 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -2654,7 +2654,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify case Op_ModF: case Op_ModD: case Op_LoadB: // Same with Loads; they can sink - case Op_LoadC: // during loop optimizations. + case Op_LoadUS: // during loop optimizations. case Op_LoadD: case Op_LoadF: case Op_LoadI: diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 4d74a434fec..f77b14ada56 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -952,13 +952,6 @@ void PhaseMacroExpand::expand_allocate_common( Node* klass_node = alloc->in(AllocateNode::KlassNode); Node* initial_slow_test = alloc->in(AllocateNode::InitialTest); - // With escape analysis, the entire memory state was needed to be able to - // eliminate the allocation. Since the allocations cannot be eliminated, - // optimize it to the raw slice. - if (mem->is_MergeMem()) { - mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw); - } - assert(ctrl != NULL, "must have control"); // We need a Region and corresponding Phi's to merge the slow-path and fast-path results. // they will not be used if "always_slow" is set @@ -1016,6 +1009,11 @@ void PhaseMacroExpand::expand_allocate_common( Node *slow_mem = mem; // save the current memory state for slow path // generate the fast allocation code unless we know that the initial test will always go slow if (!always_slow) { + // Fast path modifies only raw memory. + if (mem->is_MergeMem()) { + mem = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw); + } + Node* eden_top_adr; Node* eden_end_adr; @@ -1239,8 +1237,6 @@ void PhaseMacroExpand::expand_allocate_common( } } - mem = result_phi_rawmem; - // An allocate node has separate i_o projections for the uses on the control and i_o paths // Replace uses of the control i_o projection with result_phi_i_o (unless we are only generating a slow call) if (_ioproj_fallthrough == NULL) { diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 582cf2740b9..e911c065ccd 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -1824,7 +1824,7 @@ void Matcher::find_shared( Node *n ) { mem_op = true; break; case Op_LoadB: - case Op_LoadC: + case Op_LoadUS: case Op_LoadD: case Op_LoadF: case Op_LoadI: diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 4cfc0d233f3..9c79f2ec936 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -779,14 +779,14 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type "use LoadRangeNode instead"); switch (bt) { case T_BOOLEAN: - case T_BYTE: return new (C, 3) LoadBNode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_INT: return new (C, 3) LoadINode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_CHAR: return new (C, 3) LoadCNode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_SHORT: return new (C, 3) LoadSNode(ctl, mem, adr, adr_type, rt->is_int() ); - case T_LONG: return new (C, 3) LoadLNode(ctl, mem, adr, adr_type, rt->is_long() ); - case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt ); - case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt ); - case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() ); + case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() ); + case T_INT: return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int() ); + case T_CHAR: return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int() ); + case T_SHORT: return new (C, 3) LoadSNode (ctl, mem, adr, adr_type, rt->is_int() ); + case T_LONG: return new (C, 3) LoadLNode (ctl, mem, adr, adr_type, rt->is_long() ); + case T_FLOAT: return new (C, 3) LoadFNode (ctl, mem, adr, adr_type, rt ); + case T_DOUBLE: return new (C, 3) LoadDNode (ctl, mem, adr, adr_type, rt ); + case T_ADDRESS: return new (C, 3) LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr() ); case T_OBJECT: #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { @@ -1076,13 +1076,14 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { // of the original value. Node* mem_phi = in(Memory); Node* offset = in(Address)->in(AddPNode::Offset); + Node* region = base->in(0); Node* in1 = clone(); Node* in1_addr = in1->in(Address)->clone(); in1_addr->set_req(AddPNode::Base, base->in(allocation_index)); in1_addr->set_req(AddPNode::Address, base->in(allocation_index)); in1_addr->set_req(AddPNode::Offset, offset); - in1->set_req(0, base->in(allocation_index)); + in1->set_req(0, region->in(allocation_index)); in1->set_req(Address, in1_addr); in1->set_req(Memory, mem_phi->in(allocation_index)); @@ -1091,7 +1092,7 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { in2_addr->set_req(AddPNode::Base, base->in(load_index)); in2_addr->set_req(AddPNode::Address, base->in(load_index)); in2_addr->set_req(AddPNode::Offset, offset); - in2->set_req(0, base->in(load_index)); + in2->set_req(0, region->in(load_index)); in2->set_req(Address, in2_addr); in2->set_req(Memory, mem_phi->in(load_index)); @@ -1100,7 +1101,7 @@ Node* LoadNode::eliminate_autobox(PhaseGVN* phase) { in2_addr = phase->transform(in2_addr); in2 = phase->transform(in2); - PhiNode* result = PhiNode::make_blank(base->in(0), this); + PhiNode* result = PhiNode::make_blank(region, this); result->set_req(allocation_index, in1); result->set_req(load_index, in2); return result; @@ -1303,6 +1304,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); if (base != NULL && phase->type(base)->higher_equal(TypePtr::NOTNULL) + && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw && all_controls_dominate(base, phase->C->start())) { // A method-invariant, non-null address (constant or 'this' argument). set_req(MemNode::Control, NULL); @@ -1356,7 +1358,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Steps (a), (b): Walk past independent stores to find an exact match. if (prev_mem != NULL && prev_mem != in(MemNode::Memory)) { // (c) See if we can fold up on the spot, but don't fold up here. - // Fold-up might require truncation (for LoadB/LoadS/LoadC) or + // Fold-up might require truncation (for LoadB/LoadS/LoadUS) or // just return a prior value, which is done by Identity calls. if (can_see_stored_value(prev_mem, phase)) { // Make ready for step (d): @@ -1605,14 +1607,14 @@ Node *LoadBNode::Ideal(PhaseGVN *phase, bool can_reshape) { return LoadNode::Ideal(phase, can_reshape); } -//--------------------------LoadCNode::Ideal-------------------------------------- +//--------------------------LoadUSNode::Ideal------------------------------------- // // If the previous store is to the same address as this load, // and the value stored was larger than a char, replace this load // with the value stored truncated to a char. If no truncation is // needed, the replacement is done in LoadNode::Identity(). // -Node *LoadCNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node *LoadUSNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* mem = in(MemNode::Memory); Node* value = can_see_stored_value(mem,phase); if( value && !phase->type(value)->higher_equal( _type ) ) diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index e1a84febc44..63cb0d653f7 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -207,11 +207,11 @@ public: virtual BasicType memory_type() const { return T_BYTE; } }; -//------------------------------LoadCNode-------------------------------------- -// Load a char (16bits unsigned) from memory -class LoadCNode : public LoadNode { +//------------------------------LoadUSNode------------------------------------- +// Load an unsigned short/char (16bits unsigned) from memory +class LoadUSNode : public LoadNode { public: - LoadCNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) + LoadUSNode( Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti = TypeInt::CHAR ) : LoadNode(c,mem,adr,at,ti) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 5cdcbafbc4b..081dce647bb 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -442,16 +442,17 @@ Node *AndINode::Identity( PhaseTransform *phase ) { return load; } uint lop = load->Opcode(); - if( lop == Op_LoadC && + if( lop == Op_LoadUS && con == 0x0000FFFF ) // Already zero-extended return load; // Masking off the high bits of a unsigned-shift-right is not // needed either. if( lop == Op_URShiftI ) { const TypeInt *t12 = phase->type( load->in(2) )->isa_int(); - if( t12 && t12->is_con() ) { - int shift_con = t12->get_con(); - int mask = max_juint >> shift_con; + if( t12 && t12->is_con() ) { // Shift is by a constant + int shift = t12->get_con(); + shift &= BitsPerJavaInteger - 1; // semantics of Java shifts + int mask = max_juint >> shift; if( (mask&con) == mask ) // If AND is useless, skip it return load; } @@ -470,19 +471,19 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { uint lop = load->Opcode(); // Masking bits off of a Character? Hi bits are already zero. - if( lop == Op_LoadC && + if( lop == Op_LoadUS && (mask & 0xFFFF0000) ) // Can we make a smaller mask? return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF)); // Masking bits off of a Short? Loading a Character does some masking if( lop == Op_LoadS && (mask & 0xFFFF0000) == 0 ) { - Node *ldc = new (phase->C, 3) LoadCNode(load->in(MemNode::Control), + Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control), load->in(MemNode::Memory), load->in(MemNode::Address), load->adr_type()); - ldc = phase->transform(ldc); - return new (phase->C, 3) AndINode(ldc,phase->intcon(mask&0xFFFF)); + ldus = phase->transform(ldus); + return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF)); } // Masking sign bits off of a Byte? Let the matcher use an unsigned load @@ -579,9 +580,10 @@ Node *AndLNode::Identity( PhaseTransform *phase ) { // needed either. if( lop == Op_URShiftL ) { const TypeInt *t12 = phase->type( usr->in(2) )->isa_int(); - if( t12 && t12->is_con() ) { - int shift_con = t12->get_con(); - jlong mask = max_julong >> shift_con; + if( t12 && t12->is_con() ) { // Shift is by a constant + int shift = t12->get_con(); + shift &= BitsPerJavaLong - 1; // semantics of Java shifts + jlong mask = max_julong >> shift; if( (mask&con) == mask ) // If AND is useless, skip it return usr; } @@ -605,8 +607,8 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { const TypeInt *t12 = phase->type(rsh->in(2))->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); - shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts - const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - shift)) -1); + shift &= BitsPerJavaLong - 1; // semantics of Java shifts + const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - shift)) -1); // If the AND'ing of the 2 masks has no bits, then only original shifted // bits survive. NO sign-extension bits survive the maskings. if( (sign_bits_mask & mask) == 0 ) { @@ -786,7 +788,7 @@ Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits // before shifting them away. - const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) - CONST64(1); + const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) - CONST64(1); if( add1_op == Op_AndL && phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) return new (phase->C, 3) LShiftLNode( add1->in(1), in(2) ); @@ -820,7 +822,7 @@ const Type *LShiftLNode::Value( PhaseTransform *phase ) const { return TypeLong::LONG; uint shift = r2->get_con(); - shift &= (BitsPerJavaInteger*2)-1; // semantics of Java shifts + shift &= BitsPerJavaLong - 1; // semantics of Java shifts // Shift by a multiple of 64 does nothing: if (shift == 0) return t1; @@ -913,7 +915,7 @@ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { set_req(2, phase->intcon(0)); return this; } - else if( ld->Opcode() == Op_LoadC ) + else if( ld->Opcode() == Op_LoadUS ) // Replace zero-extension-load with sign-extension-load return new (phase->C, 3) LoadSNode( ld->in(MemNode::Control), ld->in(MemNode::Memory), @@ -1235,7 +1237,7 @@ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count // note: mask computation below does not work for 0 shift count // We'll be wanting the right-shift amount as a mask of that many bits - const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaInteger*2 - con)) -1); + const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) -1); // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". @@ -1302,7 +1304,7 @@ const Type *URShiftLNode::Value( PhaseTransform *phase ) const { if (r2->is_con()) { uint shift = r2->get_con(); - shift &= (2*BitsPerJavaInteger)-1; // semantics of Java shifts + shift &= BitsPerJavaLong - 1; // semantics of Java shifts // Shift by a multiple of 64 does nothing: if (shift == 0) return t1; // Calculate reasonably aggressive bounds for the result. @@ -1325,7 +1327,7 @@ const Type *URShiftLNode::Value( PhaseTransform *phase ) const { const TypeLong* tl = TypeLong::make(lo, hi, MAX2(r1->_widen,r2->_widen)); #ifdef ASSERT // Make sure we get the sign-capture idiom correct. - if (shift == (2*BitsPerJavaInteger)-1) { + if (shift == BitsPerJavaLong - 1) { if (r1->_lo >= 0) assert(tl == TypeLong::ZERO, ">>>63 of + is 0"); if (r1->_hi < 0) assert(tl == TypeLong::ONE, ">>>63 of - is +1"); } diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp index acc8248500d..4551162bff3 100644 --- a/hotspot/src/share/vm/opto/superword.cpp +++ b/hotspot/src/share/vm/opto/superword.cpp @@ -1444,7 +1444,7 @@ const Type* SuperWord::container_type(const Type* t) { // (Start, end] half-open range defining which operands are vector void SuperWord::vector_opd_range(Node* n, uint* start, uint* end) { switch (n->Opcode()) { - case Op_LoadB: case Op_LoadC: + case Op_LoadB: case Op_LoadUS: case Op_LoadI: case Op_LoadL: case Op_LoadF: case Op_LoadD: case Op_LoadP: diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index f433a125535..6830277ea3f 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -2471,6 +2471,8 @@ const Type *TypeOopPtr::filter( const Type *kills ) const { const Type* ft = join(kills); const TypeInstPtr* ftip = ft->isa_instptr(); const TypeInstPtr* ktip = kills->isa_instptr(); + const TypeKlassPtr* ftkp = ft->isa_klassptr(); + const TypeKlassPtr* ktkp = kills->isa_klassptr(); if (ft->empty()) { // Check for evil case of 'this' being a class and 'kills' expecting an @@ -2484,6 +2486,8 @@ const Type *TypeOopPtr::filter( const Type *kills ) const { // uplift the type. if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) return kills; // Uplift to interface + if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface()) + return kills; // Uplift to interface return Type::TOP; // Canonical empty value } @@ -2499,6 +2503,12 @@ const Type *TypeOopPtr::filter( const Type *kills ) const { // Happens in a CTW of rt.jar, 320-341, no extra flags return ktip->cast_to_ptr_type(ftip->ptr()); } + if (ftkp != NULL && ktkp != NULL && + ftkp->is_loaded() && ftkp->klass()->is_interface() && + ktkp->is_loaded() && !ktkp->klass()->is_interface()) { + // Happens in a CTW of rt.jar, 320-341, no extra flags + return ktkp->cast_to_ptr_type(ftkp->ptr()); + } return ft; } @@ -3657,7 +3667,7 @@ const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const { //------------------------------cast_to_ptr_type------------------------------- const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const { - assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); + assert(_base == KlassPtr, "subclass must override cast_to_ptr_type"); if( ptr == _ptr ) return this; return make(ptr, _klass, _offset); } diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 3d3f3ddd883..493b622a28e 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -882,6 +882,8 @@ class TypeKlassPtr : public TypeOopPtr { public: ciSymbol* name() const { return _klass->name(); } + bool is_loaded() const { return _klass->is_loaded(); } + // ptr to klass 'k' static const TypeKlassPtr *make( ciKlass* k ) { return make( TypePtr::Constant, k, 0); } // ptr to klass 'k' with offset diff --git a/hotspot/src/share/vm/opto/vectornode.cpp b/hotspot/src/share/vm/opto/vectornode.cpp index bf2cdc81ac8..7b6fef64bdf 100644 --- a/hotspot/src/share/vm/opto/vectornode.cpp +++ b/hotspot/src/share/vm/opto/vectornode.cpp @@ -239,7 +239,7 @@ int VectorNode::opcode(int sopc, uint vlen, const Type* opd_t) { return Op_XorV; case Op_LoadB: - case Op_LoadC: + case Op_LoadUS: case Op_LoadS: case Op_LoadI: case Op_LoadL: @@ -269,7 +269,7 @@ int VectorLoadNode::opcode(int sopc, uint vlen) { case 16: return Op_Load16B; } break; - case Op_LoadC: + case Op_LoadUS: switch (vlen) { case 2: return Op_Load2C; case 4: return Op_Load4C; diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index b4a82b9e547..e3f715dd23e 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -2691,8 +2691,13 @@ static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) { directBufferSupportInitializeEnded = 1; } else { - ThreadInVMfromNative tivn(thread); // set state as yield_all can call os:sleep while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) { + // Set state as yield_all can call os:sleep. On Solaris, yield_all calls + // os::sleep which requires the VM state transition. On other platforms, it + // is not necessary. The following call to change the VM state is purposely + // put inside the loop to avoid potential deadlock when multiple threads + // try to call this method. See 6791815 for more details. + ThreadInVMfromNative tivn(thread); os::yield_all(); } } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7f832341c6e..1835594ba0b 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -2475,7 +2475,8 @@ void jio_print(const char* s) { if (Arguments::vfprintf_hook() != NULL) { jio_fprintf(defaultStream::output_stream(), "%s", s); } else { - ::write(defaultStream::output_fd(), s, (int)strlen(s)); + // Make an unused local variable to avoid warning from gcc 4.x compiler. + size_t count = ::write(defaultStream::output_fd(), s, (int)strlen(s)); } } diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index bd8fe2b356b..4cc6b577b47 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1230,8 +1230,14 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // Constant pools are not easily reused so we allocate a new one // each time. + // merge_cp is created unsafe for concurrent GC processing. It + // should be marked safe before discarding it because, even if + // garbage. If it crosses a card boundary, it may be scanned + // in order to find the start of the first complete object on the card. constantPoolHandle merge_cp(THREAD, - oopFactory::new_constantPool(merge_cp_length, THREAD)); + oopFactory::new_constantPool(merge_cp_length, + methodOopDesc::IsUnsafeConc, + THREAD)); int orig_length = old_cp->orig_length(); if (orig_length == 0) { // This old_cp is an actual original constant pool. We save @@ -1274,6 +1280,7 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // rewriting so we can't use the old constant pool with the new // class. + merge_cp()->set_is_conc_safe(true); merge_cp = constantPoolHandle(); // toss the merged constant pool } else if (old_cp->length() < scratch_cp->length()) { // The old constant pool has fewer entries than the new constant @@ -1283,6 +1290,7 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // rewriting so we can't use the new constant pool with the old // class. + merge_cp()->set_is_conc_safe(true); merge_cp = constantPoolHandle(); // toss the merged constant pool } else { // The old constant pool has more entries than the new constant @@ -1296,6 +1304,7 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true, THREAD); // drop local ref to the merged constant pool + merge_cp()->set_is_conc_safe(true); merge_cp = constantPoolHandle(); } } else { @@ -1325,7 +1334,10 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // GCed. set_new_constant_pool(scratch_class, merge_cp, merge_cp_length, true, THREAD); + merge_cp()->set_is_conc_safe(true); } + assert(old_cp()->is_conc_safe(), "Just checking"); + assert(scratch_cp()->is_conc_safe(), "Just checking"); return JVMTI_ERROR_NONE; } // end merge_cp_and_rewrite() @@ -2314,13 +2326,16 @@ void VM_RedefineClasses::set_new_constant_pool( // worst case merge situation. We want to associate the minimum // sized constant pool with the klass to save space. constantPoolHandle smaller_cp(THREAD, - oopFactory::new_constantPool(scratch_cp_length, THREAD)); + oopFactory::new_constantPool(scratch_cp_length, + methodOopDesc::IsUnsafeConc, + THREAD)); // preserve orig_length() value in the smaller copy int orig_length = scratch_cp->orig_length(); assert(orig_length != 0, "sanity check"); smaller_cp->set_orig_length(orig_length); scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); scratch_cp = smaller_cp; + smaller_cp()->set_is_conc_safe(true); } // attach new constant pool to klass @@ -2516,6 +2531,7 @@ void VM_RedefineClasses::set_new_constant_pool( rewrite_cp_refs_in_stack_map_table(method, THREAD); } // end for each method + assert(scratch_cp()->is_conc_safe(), "Just checking"); } // end set_new_constant_pool() diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 152789815af..dcf83bb22d4 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -1320,6 +1320,9 @@ class VM_HeapIterateOperation: public VM_Operation { } // do the iteration + // If this operation encounters a bad object when using CMS, + // consider using safe_object_iterate() which avoids perm gen + // objects that may contain bad references. Universe::heap()->object_iterate(_blk); // when sharing is enabled we must iterate over the shared spaces diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index b9c943d10b2..417522943ad 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -229,6 +229,7 @@ public: inline void set_base(const char* base); inline void add_prefix(const char* prefix); + inline void add_suffix_to_prefix(const char* suffix); inline void add_suffix(const char* suffix); inline void reset_path(const char* base); @@ -290,6 +291,10 @@ inline void SysClassPath::add_prefix(const char* prefix) { _items[_scp_prefix] = add_to_path(_items[_scp_prefix], prefix, true); } +inline void SysClassPath::add_suffix_to_prefix(const char* suffix) { + _items[_scp_prefix] = add_to_path(_items[_scp_prefix], suffix, false); +} + inline void SysClassPath::add_suffix(const char* suffix) { _items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false); } @@ -512,7 +517,6 @@ static bool set_bool_flag(char* name, bool value, FlagValueOrigin origin) { return CommandLineFlags::boolAtPut(name, &value, origin); } - static bool set_fp_numeric_flag(char* name, char* value, FlagValueOrigin origin) { double v; if (sscanf(value, "%lf", &v) != 1) { @@ -525,7 +529,6 @@ static bool set_fp_numeric_flag(char* name, char* value, FlagValueOrigin origin) return false; } - static bool set_numeric_flag(char* name, char* value, FlagValueOrigin origin) { julong v; intx intx_v; @@ -555,7 +558,6 @@ static bool set_numeric_flag(char* name, char* value, FlagValueOrigin origin) { return false; } - static bool set_string_flag(char* name, const char* value, FlagValueOrigin origin) { if (!CommandLineFlags::ccstrAtPut(name, &value, origin)) return false; // Contract: CommandLineFlags always returns a pointer that needs freeing. @@ -591,7 +593,6 @@ static bool append_to_string_flag(char* name, const char* new_value, FlagValueOr return true; } - bool Arguments::parse_argument(const char* arg, FlagValueOrigin origin) { // range of acceptable characters spelled out for portability reasons @@ -652,7 +653,6 @@ bool Arguments::parse_argument(const char* arg, FlagValueOrigin origin) { return false; } - void Arguments::add_string(char*** bldarray, int* count, const char* arg) { assert(bldarray != NULL, "illegal argument"); @@ -756,7 +756,6 @@ bool Arguments::process_argument(const char* arg, return true; } - bool Arguments::process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized) { FILE* stream = fopen(file_name, "rb"); if (stream == NULL) { @@ -932,7 +931,6 @@ void Arguments::set_mode_flags(Mode mode) { } } - // Conflict: required to use shared spaces (-Xshare:on), but // incompatible command line options were chosen. @@ -946,7 +944,6 @@ static void no_shared_spaces() { } } - // If the user has chosen ParallelGCThreads > 0, we set UseParNewGC // if it's not explictly set or unset. If the user has chosen // UseParNewGC and not explicitly set ParallelGCThreads we @@ -1361,7 +1358,7 @@ void Arguments::set_aggressive_opts_flags() { // Feed the cache size setting into the JDK char buffer[1024]; - sprintf(buffer, "java.lang.Integer.IntegerCache.high=%d", AutoBoxCacheMax); + sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax); add_property(buffer); } if (AggressiveOpts && FLAG_IS_DEFAULT(DoEscapeAnalysis)) { @@ -1714,6 +1711,21 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) { return result; } + if (AggressiveOpts) { + // Insert alt-rt.jar between user-specified bootclasspath + // prefix and the default bootclasspath. os::set_boot_path() + // uses meta_index_dir as the default bootclasspath directory. + const char* altclasses_jar = "alt-rt.jar"; + size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 + + strlen(altclasses_jar); + char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len); + strcpy(altclasses_path, get_meta_index_dir()); + strcat(altclasses_path, altclasses_jar); + scp.add_suffix_to_prefix(altclasses_path); + scp_assembly_required = true; + FREE_C_HEAP_ARRAY(char, altclasses_path); + } + // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) result = parse_java_options_environment_variable(&scp, &scp_assembly_required); if (result != JNI_OK) { @@ -1729,7 +1741,6 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) { return JNI_OK; } - jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, @@ -1795,7 +1806,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, *scp_assembly_required_p = true; // -Xrun } else if (match_option(option, "-Xrun", &tail)) { - if(tail != NULL) { + if (tail != NULL) { const char* pos = strchr(tail, ':'); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1), tail, len); @@ -2478,7 +2489,7 @@ jint Arguments::parse_options_environment_variable(const char* name, SysClassPat vm_args.version = JNI_VERSION_1_2; vm_args.options = options; vm_args.nOptions = i; - vm_args.ignoreUnrecognized = false; + vm_args.ignoreUnrecognized = IgnoreUnrecognizedVMOptions; if (PrintVMOptions) { const char* tail; @@ -2525,13 +2536,12 @@ jint Arguments::parse(const JavaVMInitArgs* args) { // If flag "-XX:Flags=flags-file" is used it will be the first option to be processed. bool settings_file_specified = false; + const char* flags_file; int index; for (index = 0; index < args->nOptions; index++) { const JavaVMOption *option = args->options + index; if (match_option(option, "-XX:Flags=", &tail)) { - if (!process_settings_file(tail, true, args->ignoreUnrecognized)) { - return JNI_EINVAL; - } + flags_file = tail; settings_file_specified = true; } if (match_option(option, "-XX:+PrintVMOptions", &tail)) { @@ -2540,6 +2550,24 @@ jint Arguments::parse(const JavaVMInitArgs* args) { if (match_option(option, "-XX:-PrintVMOptions", &tail)) { PrintVMOptions = false; } + if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) { + IgnoreUnrecognizedVMOptions = true; + } + if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { + IgnoreUnrecognizedVMOptions = false; + } + } + + if (IgnoreUnrecognizedVMOptions) { + // uncast const to modify the flag args->ignoreUnrecognized + *(jboolean*)(&args->ignoreUnrecognized) = true; + } + + // Parse specified settings file + if (settings_file_specified) { + if (!process_settings_file(flags_file, true, args->ignoreUnrecognized)) { + return JNI_EINVAL; + } } // Parse default .hotspotrc settings file @@ -2558,7 +2586,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } } - // Parse JavaVMInitArgs structure passed in, as well as JAVA_TOOL_OPTIONS and _JAVA_OPTIONS jint result = parse_vm_init_args(args); if (result != JNI_OK) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7d9e1a614ae..c16ae09ec32 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -835,8 +835,21 @@ class CommandLineFlags { "Prints the system dictionary at exit") \ \ diagnostic(bool, UnsyncloadClass, false, \ - "Unstable: VM calls loadClass unsynchronized. Custom classloader "\ - "must call VM synchronized for findClass & defineClass") \ + "Unstable: VM calls loadClass unsynchronized. Custom " \ + "class loader must call VM synchronized for findClass " \ + "and defineClass.") \ + \ + product(bool, AlwaysLockClassLoader, false, \ + "Require the VM to acquire the class loader lock before calling " \ + "loadClass() even for class loaders registering " \ + "as parallel capable. Default false. ") \ + \ + product(bool, AllowParallelDefineClass, false, \ + "Allow parallel defineClass requests for class loaders " \ + "registering as parallel capable. Default false") \ + \ + product(bool, MustCallLoadClassInternal, false, \ + "Call loadClassInternal() rather than loadClass().Default false") \ \ product_pd(bool, DontYieldALot, \ "Throw away obvious excess yield calls (for SOLARIS only)") \ @@ -1294,7 +1307,14 @@ class CommandLineFlags { product(intx, ParGCArrayScanChunk, 50, \ "Scan a subset and push remainder, if array is bigger than this") \ \ - product(intx, ParGCDesiredObjsFromOverflowList, 20, \ + notproduct(bool, ParGCWorkQueueOverflowALot, false, \ + "Whether we should simulate work queue overflow in ParNew") \ + \ + notproduct(uintx, ParGCWorkQueueOverflowInterval, 1000, \ + "An `interval' counter that determines how frequently" \ + " we simulate overflow; a smaller number increases frequency") \ + \ + product(uintx, ParGCDesiredObjsFromOverflowList, 20, \ "The desired number of objects to claim from the overflow list") \ \ product(uintx, CMSParPromoteBlocksToClaim, 50, \ @@ -1406,18 +1426,18 @@ class CommandLineFlags { develop(bool, CMSOverflowEarlyRestoration, false, \ "Whether preserved marks should be restored early") \ \ - product(uintx, CMSMarkStackSize, 32*K, \ + product(uintx, CMSMarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \ "Size of CMS marking stack") \ \ - product(uintx, CMSMarkStackSizeMax, 4*M, \ + product(uintx, CMSMarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \ "Max size of CMS marking stack") \ \ notproduct(bool, CMSMarkStackOverflowALot, false, \ "Whether we should simulate frequent marking stack / work queue" \ " overflow") \ \ - notproduct(intx, CMSMarkStackOverflowInterval, 1000, \ - "A per-thread `interval' counter that determines how frequently" \ + notproduct(uintx, CMSMarkStackOverflowInterval, 1000, \ + "An `interval' counter that determines how frequently" \ " we simulate overflow; a smaller number increases frequency") \ \ product(uintx, CMSMaxAbortablePrecleanLoops, 0, \ @@ -1635,7 +1655,14 @@ class CommandLineFlags { develop(uintx, WorkStealingYieldsBeforeSleep, 1000, \ "Number of yields before a sleep is done during workstealing") \ \ - product(uintx, PreserveMarkStackSize, 40, \ + develop(uintx, WorkStealingHardSpins, 4096, \ + "Number of iterations in a spin loop between checks on " \ + "time out of hard spin") \ + \ + develop(uintx, WorkStealingSpinToYieldRatio, 10, \ + "Ratio of hard spins to calls to yield") \ + \ + product(uintx, PreserveMarkStackSize, 1024, \ "Size for stack used in promotion failure handling") \ \ product_pd(bool, UseTLAB, "Use thread-local object allocation") \ @@ -2167,6 +2194,9 @@ class CommandLineFlags { product(bool, PrintVMOptions, trueInDebug, \ "print VM flag settings") \ \ + product(bool, IgnoreUnrecognizedVMOptions, false, \ + "Ignore unrecognized VM options") \ + \ diagnostic(bool, SerializeVMOutput, true, \ "Use a mutex to serialize output to tty and hotspot.log") \ \ diff --git a/hotspot/src/share/vm/runtime/memprofiler.cpp b/hotspot/src/share/vm/runtime/memprofiler.cpp index 4d5ad533d83..f8a259f9be2 100644 --- a/hotspot/src/share/vm/runtime/memprofiler.cpp +++ b/hotspot/src/share/vm/runtime/memprofiler.cpp @@ -104,21 +104,22 @@ void MemProfiler::do_trace() { } // Print trace line in log - fprintf(_log_fp, "%6.1f,%5d,%5d,%6ld,%6ld,%6ld,%6ld,", - os::elapsedTime(), - Threads::number_of_threads(), - SystemDictionary::number_of_classes(), - Universe::heap()->used() / K, - Universe::heap()->capacity() / K, - Universe::heap()->permanent_used() / HWperKB, - Universe::heap()->permanent_capacity() / HWperKB); + fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) "," + UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",", + os::elapsedTime(), + Threads::number_of_threads(), + SystemDictionary::number_of_classes(), + Universe::heap()->used() / K, + Universe::heap()->capacity() / K, + Universe::heap()->permanent_used() / HWperKB, + Universe::heap()->permanent_capacity() / HWperKB); - fprintf(_log_fp, "%6ld,", CodeCache::capacity() / K); + fprintf(_log_fp, UINTX_FORMAT_W(6) ",", CodeCache::capacity() / K); - fprintf(_log_fp, "%6ld,%6ld,%6ld\n", - handles_memory_usage / K, - resource_memory_usage / K, - OopMapCache::memory_usage() / K); + fprintf(_log_fp, UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",%6ld\n", + handles_memory_usage / K, + resource_memory_usage / K, + OopMapCache::memory_usage() / K); fflush(_log_fp); } diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index da6d719edc0..8c81d42734a 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -74,13 +74,11 @@ char* os::iso8601_time(char* buffer, size_t buffer_length) { const int milliseconds_after_second = milliseconds_since_19700101 % milliseconds_per_microsecond; // Convert the time value to a tm and timezone variable - const struct tm *time_struct_temp = localtime(&seconds_since_19700101); - if (time_struct_temp == NULL) { - assert(false, "Failed localtime"); + struct tm time_struct; + if (localtime_pd(&seconds_since_19700101, &time_struct) == NULL) { + assert(false, "Failed localtime_pd"); return NULL; } - // Save the results of localtime - const struct tm time_struct = *time_struct_temp; const time_t zone = timezone; // If daylight savings time is in effect, @@ -93,10 +91,10 @@ char* os::iso8601_time(char* buffer, size_t buffer_length) { UTC_to_local = UTC_to_local - seconds_per_hour; } // Compute the time zone offset. - // localtime(3C) sets timezone to the difference (in seconds) + // localtime_pd() sets timezone to the difference (in seconds) // between UTC and and local time. // ISO 8601 says we need the difference between local time and UTC, - // we change the sign of the localtime(3C) result. + // we change the sign of the localtime_pd() result. const time_t local_to_UTC = -(UTC_to_local); // Then we have to figure out if if we are ahead (+) or behind (-) UTC. char sign_local_to_UTC = '+'; diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 0856d23a03b..ce653c5f6f2 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -120,7 +120,8 @@ class os: AllStatic { // Return current local time in a string (YYYY-MM-DD HH:MM:SS). // It is MT safe, but not async-safe, as reading time zone // information may require a lock on some platforms. - static char* local_time_string(char *buf, size_t buflen); + static char* local_time_string(char *buf, size_t buflen); + static struct tm* localtime_pd (const time_t* clock, struct tm* res); // Fill in buffer with current local time as an ISO-8601 string. // E.g., YYYY-MM-DDThh:mm:ss.mmm+zzzz. // Returns buffer, or NULL if it failed. diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp index 2a3b838f6e5..c13af643a85 100644 --- a/hotspot/src/share/vm/runtime/safepoint.cpp +++ b/hotspot/src/share/vm/runtime/safepoint.cpp @@ -730,7 +730,7 @@ void SafepointSynchronize::print_safepoint_timeout(SafepointTimeoutReason reason if (DieOnSafepointTimeout) { char msg[1024]; VM_Operation *op = VMThread::vm_operation(); - sprintf(msg, "Safepoint sync time longer than %d ms detected when executing %s.", + sprintf(msg, "Safepoint sync time longer than " INTX_FORMAT "ms detected when executing %s.", SafepointTimeoutDelay, op != NULL ? op->name() : "no vm operation"); fatal(msg); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 76067dc8ee1..cf69631c0bb 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -192,64 +192,46 @@ JRT_END JRT_LEAF(jint, SharedRuntime::f2i(jfloat x)) - if (g_isnan(x)) {return 0;} - jlong lltmp = (jlong)x; - jint ltmp = (jint)lltmp; - if (ltmp == lltmp) { - return ltmp; - } else { - if (x < 0) { - return min_jint; - } else { - return max_jint; - } - } + if (g_isnan(x)) + return 0; + if (x >= (jfloat) max_jint) + return max_jint; + if (x <= (jfloat) min_jint) + return min_jint; + return (jint) x; JRT_END JRT_LEAF(jlong, SharedRuntime::f2l(jfloat x)) - if (g_isnan(x)) {return 0;} - jlong lltmp = (jlong)x; - if (lltmp != min_jlong) { - return lltmp; - } else { - if (x < 0) { - return min_jlong; - } else { - return max_jlong; - } - } + if (g_isnan(x)) + return 0; + if (x >= (jfloat) max_jlong) + return max_jlong; + if (x <= (jfloat) min_jlong) + return min_jlong; + return (jlong) x; JRT_END JRT_LEAF(jint, SharedRuntime::d2i(jdouble x)) - if (g_isnan(x)) {return 0;} - jlong lltmp = (jlong)x; - jint ltmp = (jint)lltmp; - if (ltmp == lltmp) { - return ltmp; - } else { - if (x < 0) { - return min_jint; - } else { - return max_jint; - } - } + if (g_isnan(x)) + return 0; + if (x >= (jdouble) max_jint) + return max_jint; + if (x <= (jdouble) min_jint) + return min_jint; + return (jint) x; JRT_END JRT_LEAF(jlong, SharedRuntime::d2l(jdouble x)) - if (g_isnan(x)) {return 0;} - jlong lltmp = (jlong)x; - if (lltmp != min_jlong) { - return lltmp; - } else { - if (x < 0) { - return min_jlong; - } else { - return max_jlong; - } - } + if (g_isnan(x)) + return 0; + if (x >= (jdouble) max_jlong) + return max_jlong; + if (x <= (jdouble) min_jlong) + return min_jlong; + return (jlong) x; JRT_END diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp index aeb66980add..e0f3cfe04bb 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.cpp +++ b/hotspot/src/share/vm/runtime/synchronizer.cpp @@ -424,7 +424,7 @@ void ObjectSynchronizer::Initialize () { // asserts is that error message -- often something about negative array // indices -- is opaque. -#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @%X\n", tag); } +#define CTASSERT(x) { int tag[1-(2*!(x))]; printf ("Tag @" INTPTR_FORMAT "\n", (intptr_t)tag); } void ObjectMonitor::ctAsserts() { CTASSERT(offset_of (ObjectMonitor, _header) == 0); diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index bf7aaf1a914..18bd9f477d7 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1700,7 +1700,7 @@ void VM_HeapDumper::doit() { // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk // of the heap dump. HeapObjectDumper obj_dumper(this, writer()); - Universe::heap()->object_iterate(&obj_dumper); + Universe::heap()->safe_object_iterate(&obj_dumper); // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals do_threads(); diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index f87bfad69ac..0a9b8f2a2f3 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,7 @@ extern int BytesPerHeapOop; extern int BitsPerHeapOop; const int BitsPerJavaInteger = 32; +const int BitsPerJavaLong = 64; const int BitsPerSize_t = size_tSize * BitsPerByte; // Size of a char[] needed to represent a jint as a string in decimal. @@ -906,6 +907,14 @@ inline int exact_log2(intptr_t x) { return log2_intptr(x); } +//* the argument must be exactly a power of 2 +inline int exact_log2_long(jlong x) { + #ifdef ASSERT + if (!is_power_of_2_long(x)) basic_fatal("x must be a power of 2"); + #endif + return log2_long(x); +} + // returns integer round-up to the nearest multiple of s (s must be a power of two) inline intptr_t round_to(intptr_t x, uintx s) { @@ -1087,15 +1096,24 @@ inline int build_int_from_shorts( jushort low, jushort high ) { // Format macros that allow the field width to be specified. The width must be // a string literal (e.g., "8") or a macro that evaluates to one. #ifdef _LP64 +#define UINTX_FORMAT_W(width) UINT64_FORMAT_W(width) #define SSIZE_FORMAT_W(width) INT64_FORMAT_W(width) #define SIZE_FORMAT_W(width) UINT64_FORMAT_W(width) #else +#define UINTX_FORMAT_W(width) UINT32_FORMAT_W(width) #define SSIZE_FORMAT_W(width) INT32_FORMAT_W(width) #define SIZE_FORMAT_W(width) UINT32_FORMAT_W(width) #endif // _LP64 // Format pointers and size_t (or size_t-like integer types) which change size -// between 32- and 64-bit. +// between 32- and 64-bit. The pointer format theoretically should be "%p", +// however, it has different output on different platforms. On Windows, the data +// will be padded with zeros automatically. On Solaris, we can use "%016p" & +// "%08p" on 64 bit & 32 bit platforms to make the data padded with extra zeros. +// On Linux, "%016p" or "%08p" is not be allowed, at least on the latest GCC +// 4.3.2. So we have to use "%016x" or "%08x" to simulate the printing format. +// GCC 4.3.2, however requires the data to be converted to "intptr_t" when +// using "%x". #ifdef _LP64 #define PTR_FORMAT PTR64_FORMAT #define UINTX_FORMAT UINT64_FORMAT diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp index 417978f0891..48f2c7e886a 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp @@ -116,7 +116,9 @@ #ifdef _LP64 #define NULL_WORD 0L #else - #define NULL_WORD 0 + // Cast 0 to intptr_t rather than int32_t since they are not the same type + // on platforms such as Mac OS X. + #define NULL_WORD ((intptr_t)0) #endif #else #define NULL_WORD NULL diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp index f25364b72bf..62c8b92e255 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp @@ -115,7 +115,9 @@ #ifdef _LP64 #define NULL_WORD 0L #else - #define NULL_WORD 0 + // Cast 0 to intptr_t rather than int32_t since they are not the same type + // on some platforms. + #define NULL_WORD ((intptr_t)0) #endif #else #define NULL_WORD NULL diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 8770bed52ca..65d18802ba2 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -300,7 +300,10 @@ fileStream::fileStream(const char* file_name) { } void fileStream::write(const char* s, size_t len) { - if (_file != NULL) fwrite(s, 1, len, _file); + if (_file != NULL) { + // Make an unused local variable to avoid warning from gcc 4.x compiler. + size_t count = fwrite(s, 1, len, _file); + } update_position(s, len); } @@ -328,7 +331,10 @@ fdStream::~fdStream() { } void fdStream::write(const char* s, size_t len) { - if (_fd != -1) ::write(_fd, s, (int)len); + if (_fd != -1) { + // Make an unused local variable to avoid warning from gcc 4.x compiler. + size_t count = ::write(_fd, s, (int)len); + } update_position(s, len); } diff --git a/hotspot/src/share/vm/utilities/taskqueue.cpp b/hotspot/src/share/vm/utilities/taskqueue.cpp index 779ec4e7f3a..2b3145813fd 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.cpp +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp @@ -25,6 +25,12 @@ # include "incls/_precompiled.incl" # include "incls/_taskqueue.cpp.incl" +#ifdef TRACESPINNING +uint ParallelTaskTerminator::_total_yields = 0; +uint ParallelTaskTerminator::_total_spins = 0; +uint ParallelTaskTerminator::_total_peeks = 0; +#endif + bool TaskQueueSuper::peek() { return _bottom != _age.top(); } @@ -69,15 +75,62 @@ bool ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { Atomic::inc(&_offered_termination); - juint yield_count = 0; + uint yield_count = 0; + // Number of hard spin loops done since last yield + uint hard_spin_count = 0; + // Number of iterations in the hard spin loop. + uint hard_spin_limit = WorkStealingHardSpins; + + // If WorkStealingSpinToYieldRatio is 0, no hard spinning is done. + // If it is greater than 0, then start with a small number + // of spins and increase number with each turn at spinning until + // the count of hard spins exceeds WorkStealingSpinToYieldRatio. + // Then do a yield() call and start spinning afresh. + if (WorkStealingSpinToYieldRatio > 0) { + hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio; + hard_spin_limit = MAX2(hard_spin_limit, 1U); + } + // Remember the initial spin limit. + uint hard_spin_start = hard_spin_limit; + + // Loop waiting for all threads to offer termination or + // more work. while (true) { + // Are all threads offering termination? if (_offered_termination == _n_threads) { - //inner_termination_loop(); return true; } else { + // Look for more work. + // Periodically sleep() instead of yield() to give threads + // waiting on the cores the chance to grab this code if (yield_count <= WorkStealingYieldsBeforeSleep) { + // Do a yield or hardspin. For purposes of deciding whether + // to sleep, count this as a yield. yield_count++; - yield(); + + // Periodically call yield() instead spinning + // After WorkStealingSpinToYieldRatio spins, do a yield() call + // and reset the counts and starting limit. + if (hard_spin_count > WorkStealingSpinToYieldRatio) { + yield(); + hard_spin_count = 0; + hard_spin_limit = hard_spin_start; +#ifdef TRACESPINNING + _total_yields++; +#endif + } else { + // Hard spin this time + // Increase the hard spinning period but only up to a limit. + hard_spin_limit = MIN2(2*hard_spin_limit, + (uint) WorkStealingHardSpins); + for (uint j = 0; j < hard_spin_limit; j++) { + SpinPause(); + } + hard_spin_count++; +#ifdef TRACESPINNING + _total_spins++; +#endif + } } else { if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("ParallelTaskTerminator::offer_termination() " @@ -92,6 +145,9 @@ ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { sleep(WorkStealingSleepMillis); } +#ifdef TRACESPINNING + _total_peeks++; +#endif if (peek_in_queue_set() || (terminator != NULL && terminator->should_exit_termination())) { Atomic::dec(&_offered_termination); @@ -101,6 +157,16 @@ ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) { } } +#ifdef TRACESPINNING +void ParallelTaskTerminator::print_termination_counts() { + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " + "Total spins: %lld Total peeks: %lld", + total_yields(), + total_spins(), + total_peeks()); +} +#endif + void ParallelTaskTerminator::reset_for_reuse() { if (_offered_termination != 0) { assert(_offered_termination == _n_threads, diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index 2323fb61c76..3a80a814238 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -22,67 +22,76 @@ * */ +#ifdef LP64 +typedef juint TAG_TYPE; +// for a taskqueue size of 4M +#define LOG_TASKQ_SIZE 22 +#else +typedef jushort TAG_TYPE; +// for a taskqueue size of 16K +#define LOG_TASKQ_SIZE 14 +#endif + class TaskQueueSuper: public CHeapObj { protected: // The first free element after the last one pushed (mod _n). - // (For now we'll assume only 32-bit CAS). - volatile juint _bottom; + volatile uint _bottom; // log2 of the size of the queue. enum SomeProtectedConstants { - Log_n = 14 + Log_n = LOG_TASKQ_SIZE }; +#undef LOG_TASKQ_SIZE // Size of the queue. - juint n() { return (1 << Log_n); } + uint n() { return (1 << Log_n); } // For computing "x mod n" efficiently. - juint n_mod_mask() { return n() - 1; } + uint n_mod_mask() { return n() - 1; } struct Age { - jushort _top; - jushort _tag; + TAG_TYPE _top; + TAG_TYPE _tag; - jushort tag() const { return _tag; } - jushort top() const { return _top; } + TAG_TYPE tag() const { return _tag; } + TAG_TYPE top() const { return _top; } Age() { _tag = 0; _top = 0; } friend bool operator ==(const Age& a1, const Age& a2) { return a1.tag() == a2.tag() && a1.top() == a2.top(); } - }; Age _age; // These make sure we do single atomic reads and writes. Age get_age() { - jint res = *(volatile jint*)(&_age); + uint res = *(volatile uint*)(&_age); return *(Age*)(&res); } void set_age(Age a) { - *(volatile jint*)(&_age) = *(int*)(&a); + *(volatile uint*)(&_age) = *(uint*)(&a); } - jushort get_top() { + TAG_TYPE get_top() { return get_age().top(); } // These both operate mod _n. - juint increment_index(juint ind) { + uint increment_index(uint ind) { return (ind + 1) & n_mod_mask(); } - juint decrement_index(juint ind) { + uint decrement_index(uint ind) { return (ind - 1) & n_mod_mask(); } // Returns a number in the range [0.._n). If the result is "n-1", it // should be interpreted as 0. - juint dirty_size(juint bot, juint top) { - return ((jint)bot - (jint)top) & n_mod_mask(); + uint dirty_size(uint bot, uint top) { + return ((int)bot - (int)top) & n_mod_mask(); } // Returns the size corresponding to the given "bot" and "top". - juint size(juint bot, juint top) { - juint sz = dirty_size(bot, top); + uint size(uint bot, uint top) { + uint sz = dirty_size(bot, top); // Has the queue "wrapped", so that bottom is less than top? // There's a complicated special case here. A pair of threads could // perform pop_local and pop_global operations concurrently, starting @@ -94,7 +103,7 @@ protected: // owner performs pop_local's, and several concurrent threads // attempting to perform the pop_global will all perform the same CAS, // and only one can succeed. Any stealing thread that reads after - // either the increment or decrement will seen an empty queue, and will + // either the increment or decrement will see an empty queue, and will // not join the competitors. The "sz == -1 || sz == _n-1" state will // not be modified by concurrent queues, so the owner thread can reset // the state to _bottom == top so subsequent pushes will be performed @@ -112,11 +121,11 @@ public: // Return an estimate of the number of elements in the queue. // The "careful" version admits the possibility of pop_local/pop_global // races. - juint size() { + uint size() { return size(_bottom, get_top()); } - juint dirty_size() { + uint dirty_size() { return dirty_size(_bottom, get_top()); } @@ -127,15 +136,15 @@ public: // Maximum number of elements allowed in the queue. This is two less // than the actual queue size, for somewhat complicated reasons. - juint max_elems() { return n() - 2; } + uint max_elems() { return n() - 2; } }; template class GenericTaskQueue: public TaskQueueSuper { private: // Slow paths for push, pop_local. (pop_global has no fast path.) - bool push_slow(E t, juint dirty_n_elems); - bool pop_local_slow(juint localBot, Age oldAge); + bool push_slow(E t, uint dirty_n_elems); + bool pop_local_slow(uint localBot, Age oldAge); public: // Initializes the queue to empty. @@ -170,7 +179,7 @@ private: template GenericTaskQueue::GenericTaskQueue():TaskQueueSuper() { - assert(sizeof(Age) == sizeof(jint), "Depends on this."); + assert(sizeof(Age) == sizeof(int), "Depends on this."); } template @@ -182,9 +191,9 @@ void GenericTaskQueue::initialize() { template void GenericTaskQueue::oops_do(OopClosure* f) { // tty->print_cr("START OopTaskQueue::oops_do"); - int iters = size(); - juint index = _bottom; - for (int i = 0; i < iters; ++i) { + uint iters = size(); + uint index = _bottom; + for (uint i = 0; i < iters; ++i) { index = decrement_index(index); // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T, // index, &_elems[index], _elems[index]); @@ -198,10 +207,10 @@ void GenericTaskQueue::oops_do(OopClosure* f) { template -bool GenericTaskQueue::push_slow(E t, juint dirty_n_elems) { +bool GenericTaskQueue::push_slow(E t, uint dirty_n_elems) { if (dirty_n_elems == n() - 1) { // Actually means 0, so do the push. - juint localBot = _bottom; + uint localBot = _bottom; _elems[localBot] = t; _bottom = increment_index(localBot); return true; @@ -211,7 +220,7 @@ bool GenericTaskQueue::push_slow(E t, juint dirty_n_elems) { template bool GenericTaskQueue:: -pop_local_slow(juint localBot, Age oldAge) { +pop_local_slow(uint localBot, Age oldAge) { // This queue was observed to contain exactly one element; either this // thread will claim it, or a competing "pop_global". In either case, // the queue will be logically empty afterwards. Create a new Age value @@ -230,9 +239,8 @@ pop_local_slow(juint localBot, Age oldAge) { Age tempAge; // No competing pop_global has yet incremented "top"; we'll try to // install new_age, thus claiming the element. - assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), - "Assumption about CAS unit."); - *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); + assert(sizeof(Age) == sizeof(int), "Assumption about CAS unit."); + *(uint*)&tempAge = Atomic::cmpxchg(*(uint*)&newAge, (volatile uint*)&_age, *(uint*)&oldAge); if (tempAge == oldAge) { // We win. assert(dirty_size(localBot, get_top()) != n() - 1, @@ -253,8 +261,8 @@ template bool GenericTaskQueue::pop_global(E& t) { Age newAge; Age oldAge = get_age(); - juint localBot = _bottom; - juint n_elems = size(localBot, oldAge.top()); + uint localBot = _bottom; + uint n_elems = size(localBot, oldAge.top()); if (n_elems == 0) { return false; } @@ -263,7 +271,7 @@ bool GenericTaskQueue::pop_global(E& t) { newAge._top = increment_index(newAge.top()); if ( newAge._top == 0 ) newAge._tag++; Age resAge; - *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); + *(uint*)&resAge = Atomic::cmpxchg(*(uint*)&newAge, (volatile uint*)&_age, *(uint*)&oldAge); // Note that using "_bottom" here might fail, since a pop_local might // have decremented it. assert(dirty_size(localBot, newAge._top) != n() - 1, @@ -287,7 +295,7 @@ public: template class GenericTaskQueueSet: public TaskQueueSetSuper { private: - int _n; + uint _n; GenericTaskQueue** _queues; public: @@ -300,51 +308,51 @@ public: } } - bool steal_1_random(int queue_num, int* seed, E& t); - bool steal_best_of_2(int queue_num, int* seed, E& t); - bool steal_best_of_all(int queue_num, int* seed, E& t); + bool steal_1_random(uint queue_num, int* seed, E& t); + bool steal_best_of_2(uint queue_num, int* seed, E& t); + bool steal_best_of_all(uint queue_num, int* seed, E& t); - void register_queue(int i, GenericTaskQueue* q); + void register_queue(uint i, GenericTaskQueue* q); - GenericTaskQueue* queue(int n); + GenericTaskQueue* queue(uint n); // The thread with queue number "queue_num" (and whose random number seed // is at "seed") is trying to steal a task from some other queue. (It // may try several queues, according to some configuration parameter.) // If some steal succeeds, returns "true" and sets "t" the stolen task, // otherwise returns false. - bool steal(int queue_num, int* seed, E& t); + bool steal(uint queue_num, int* seed, E& t); bool peek(); }; template -void GenericTaskQueueSet::register_queue(int i, GenericTaskQueue* q) { - assert(0 <= i && i < _n, "index out of range."); +void GenericTaskQueueSet::register_queue(uint i, GenericTaskQueue* q) { + assert(i < _n, "index out of range."); _queues[i] = q; } template -GenericTaskQueue* GenericTaskQueueSet::queue(int i) { +GenericTaskQueue* GenericTaskQueueSet::queue(uint i) { return _queues[i]; } template -bool GenericTaskQueueSet::steal(int queue_num, int* seed, E& t) { - for (int i = 0; i < 2 * _n; i++) +bool GenericTaskQueueSet::steal(uint queue_num, int* seed, E& t) { + for (uint i = 0; i < 2 * _n; i++) if (steal_best_of_2(queue_num, seed, t)) return true; return false; } template -bool GenericTaskQueueSet::steal_best_of_all(int queue_num, int* seed, E& t) { +bool GenericTaskQueueSet::steal_best_of_all(uint queue_num, int* seed, E& t) { if (_n > 2) { int best_k; - jint best_sz = 0; - for (int k = 0; k < _n; k++) { + uint best_sz = 0; + for (uint k = 0; k < _n; k++) { if (k == queue_num) continue; - jint sz = _queues[k]->size(); + uint sz = _queues[k]->size(); if (sz > best_sz) { best_sz = sz; best_k = k; @@ -362,9 +370,9 @@ bool GenericTaskQueueSet::steal_best_of_all(int queue_num, int* seed, E& t) { } template -bool GenericTaskQueueSet::steal_1_random(int queue_num, int* seed, E& t) { +bool GenericTaskQueueSet::steal_1_random(uint queue_num, int* seed, E& t) { if (_n > 2) { - int k = queue_num; + uint k = queue_num; while (k == queue_num) k = randomParkAndMiller(seed) % _n; return _queues[2]->pop_global(t); } else if (_n == 2) { @@ -378,20 +386,20 @@ bool GenericTaskQueueSet::steal_1_random(int queue_num, int* seed, E& t) { } template -bool GenericTaskQueueSet::steal_best_of_2(int queue_num, int* seed, E& t) { +bool GenericTaskQueueSet::steal_best_of_2(uint queue_num, int* seed, E& t) { if (_n > 2) { - int k1 = queue_num; + uint k1 = queue_num; while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; - int k2 = queue_num; + uint k2 = queue_num; while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; // Sample both and try the larger. - juint sz1 = _queues[k1]->size(); - juint sz2 = _queues[k2]->size(); + uint sz1 = _queues[k1]->size(); + uint sz2 = _queues[k2]->size(); if (sz2 > sz1) return _queues[k2]->pop_global(t); else return _queues[k1]->pop_global(t); } else if (_n == 2) { // Just try the other one. - int k = (queue_num + 1) % 2; + uint k = (queue_num + 1) % 2; return _queues[k]->pop_global(t); } else { assert(_n == 1, "can't be zero."); @@ -402,7 +410,7 @@ bool GenericTaskQueueSet::steal_best_of_2(int queue_num, int* seed, E& t) { template bool GenericTaskQueueSet::peek() { // Try all the queues. - for (int j = 0; j < _n; j++) { + for (uint j = 0; j < _n; j++) { if (_queues[j]->peek()) return true; } @@ -418,11 +426,19 @@ public: // A class to aid in the termination of a set of parallel tasks using // TaskQueueSet's for work stealing. +#undef TRACESPINNING + class ParallelTaskTerminator: public StackObj { private: int _n_threads; TaskQueueSetSuper* _queue_set; - jint _offered_termination; + int _offered_termination; + +#ifdef TRACESPINNING + static uint _total_yields; + static uint _total_spins; + static uint _total_peeks; +#endif bool peek_in_queue_set(); protected: @@ -454,13 +470,19 @@ public: // the terminator is finished. void reset_for_reuse(); +#ifdef TRACESPINNING + static uint total_yields() { return _total_yields; } + static uint total_spins() { return _total_spins; } + static uint total_peeks() { return _total_peeks; } + static void print_termination_counts(); +#endif }; #define SIMPLE_STACK 0 template inline bool GenericTaskQueue::push(E t) { #if SIMPLE_STACK - juint localBot = _bottom; + uint localBot = _bottom; if (_bottom < max_elems()) { _elems[localBot] = t; _bottom = localBot + 1; @@ -469,10 +491,10 @@ template inline bool GenericTaskQueue::push(E t) { return false; } #else - juint localBot = _bottom; + uint localBot = _bottom; assert((localBot >= 0) && (localBot < n()), "_bottom out of range."); - jushort top = get_top(); - juint dirty_n_elems = dirty_size(localBot, top); + TAG_TYPE top = get_top(); + uint dirty_n_elems = dirty_size(localBot, top); assert((dirty_n_elems >= 0) && (dirty_n_elems < n()), "n_elems out of range."); if (dirty_n_elems < max_elems()) { @@ -487,19 +509,19 @@ template inline bool GenericTaskQueue::push(E t) { template inline bool GenericTaskQueue::pop_local(E& t) { #if SIMPLE_STACK - juint localBot = _bottom; + uint localBot = _bottom; assert(localBot > 0, "precondition."); localBot--; t = _elems[localBot]; _bottom = localBot; return true; #else - juint localBot = _bottom; + uint localBot = _bottom; // This value cannot be n-1. That can only occur as a result of // the assignment to bottom in this method. If it does, this method // resets the size( to 0 before the next call (which is sequential, // since this is pop_local.) - juint dirty_n_elems = dirty_size(localBot, get_top()); + uint dirty_n_elems = dirty_size(localBot, get_top()); assert(dirty_n_elems != n() - 1, "Shouldn't be possible..."); if (dirty_n_elems == 0) return false; localBot = decrement_index(localBot); @@ -512,7 +534,7 @@ template inline bool GenericTaskQueue::pop_local(E& t) { // If there's still at least one element in the queue, based on the // "_bottom" and "age" we've read, then there can be no interference with // a "pop_global" operation, and we're done. - juint tp = get_top(); + TAG_TYPE tp = get_top(); // XXX if (size(localBot, tp) > 0) { assert(dirty_size(localBot, tp) != n() - 1, "Shouldn't be possible..."); @@ -581,7 +603,7 @@ class RegionTaskQueueWithOverflow: public CHeapObj { bool is_empty(); bool stealable_is_empty(); bool overflow_is_empty(); - juint stealable_size() { return _region_queue.size(); } + uint stealable_size() { return _region_queue.size(); } RegionTaskQueue* task_queue() { return &_region_queue; } }; diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index d2a0161a7cc..a4d0cb0baf0 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -674,6 +674,11 @@ void VMError::report_and_die() { reset_signal_handlers(); } else { + // If UseOsErrorReporting we call this for each level of the call stack + // while searching for the exception handler. Only the first level needs + // to be reported. + if (UseOSErrorReporting && log_done) return; + // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp index 414bc7f21eb..8e618d91462 100644 --- a/hotspot/src/share/vm/utilities/vmError.hpp +++ b/hotspot/src/share/vm/utilities/vmError.hpp @@ -50,7 +50,7 @@ class VMError : public StackObj { // additional info for VM internal errors const char * _filename; - int _lineno; + size_t _lineno; // used by fatal error handler int _current_step; diff --git a/hotspot/src/share/vm/utilities/workgroup.hpp b/hotspot/src/share/vm/utilities/workgroup.hpp index fb2ec0603fd..45ddc9cbfc2 100644 --- a/hotspot/src/share/vm/utilities/workgroup.hpp +++ b/hotspot/src/share/vm/utilities/workgroup.hpp @@ -32,7 +32,7 @@ class WorkData; // An abstract task to be worked on by a gang. // You subclass this to supply your own work() method -class AbstractGangTask: public CHeapObj { +class AbstractGangTask VALUE_OBJ_CLASS_SPEC { public: // The abstract work method. // The argument tells you which member of the gang you are. diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index 2596d851229..f78c2d971c6 100644 --- a/hotspot/test/Makefile +++ b/hotspot/test/Makefile @@ -28,9 +28,9 @@ # Get OS/ARCH specifics OSNAME = $(shell uname -s) -SLASH_JAVA = /java ifeq ($(OSNAME), SunOS) PLATFORM = solaris + SLASH_JAVA = /java ARCH = $(shell uname -p) ifeq ($(ARCH), i386) ARCH=i586 @@ -38,6 +38,7 @@ ifeq ($(OSNAME), SunOS) endif ifeq ($(OSNAME), Linux) PLATFORM = linux + SLASH_JAVA = /java ARCH = $(shell uname -m) ifeq ($(ARCH), i386) ARCH = i586 @@ -62,6 +63,10 @@ ifeq ($(OSNAME), Windows_NT) EXESUFFIX = .exe endif +ifdef ALT_SLASH_JAVA + SLASH_JAVA = $(ALT_SLASH_JAVA) +endif + # Utilities used CD = cd CP = cp diff --git a/hotspot/test/compiler/6603011/Test.java b/hotspot/test/compiler/6603011/Test.java new file mode 100644 index 00000000000..1192d258afe --- /dev/null +++ b/hotspot/test/compiler/6603011/Test.java @@ -0,0 +1,220 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6603011 + * @summary long/int division by constant + * + * @run main/othervm -Xcomp -Xbatch -XX:-Inline Test + */ + +// +// -XX:-Inline is essential to this test so that verification functions +// divi, modi, divl and modl generate "plain" divides. +// -Xcomp -Xbatch are also useful to ensure the full range of +// dividend and divisor combinations are tested +// + +import java.net.*; + +class s { + static int divi(int dividend, int divisor) { return dividend / divisor; } + static int modi(int dividend, int divisor) { return dividend % divisor; } + static long divl(long dividend, long divisor) { return dividend / divisor; } + static long modl(long dividend, long divisor) { return dividend % divisor; } +} + +public class Test implements Runnable { + // Report verbose messages on failure; turn off to suppress + // too much output with gross numbers of failures. + static final boolean VERBOSE = true; + + // Initailize DIVISOR so that it is final in this class. + static final int DIVISOR; + static { + int value = 0; + try { + value = Integer.decode(System.getProperty("divisor")); + } catch (Throwable e) { + } + DIVISOR = value; + } + + // The methods of interest. We want the JIT to compile these + // and convert the divide into a multiply. + public int divbyI (int dividend) { return dividend / DIVISOR; } + public int modbyI (int dividend) { return dividend % DIVISOR; } + public long divbyL (long dividend) { return dividend / DIVISOR; } + public long modbyL (long dividend) { return dividend % DIVISOR; } + + public int divisor() { return DIVISOR; } + + public boolean checkI (int dividend) { + int quo = divbyI(dividend); + int rem = modbyI(dividend); + int quo0 = s.divi(dividend, divisor()); + int rem0 = s.modi(dividend, divisor()); + + if (quo != quo0 || rem != rem0) { + if (VERBOSE) { + System.out.println("Computed: " + dividend + " / " + divisor() + " = " + + quo + ", " + dividend + " % " + divisor() + " = " + rem ); + System.out.println("expected: " + dividend + " / " + divisor() + " = " + + quo0 + ", " + dividend + " % " + divisor() + " = " + rem0); + // Report sign of rem failure + if (rem != 0 && (rem ^ dividend) < 0) { + System.out.println(" rem & dividend have different signs"); + } + // Report range of rem failure + if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) { + System.out.println(" remainder out of range"); + } + // Report quo/rem identity relationship failure + if ((quo * divisor()) + rem != dividend) { + System.out.println(" quotien/remainder invariant broken"); + } + } + return false; + } + return true; + } + + public boolean checkL (long dividend) { + long quo = divbyL(dividend); + long rem = modbyL(dividend); + long quo0 = s.divl(dividend, divisor()); + long rem0 = s.modl(dividend, divisor()); + + if (quo != quo0 || rem != rem0) { + if (VERBOSE) { + System.out.println(" " + dividend + " / " + divisor() + " = " + + quo + ", " + dividend + " % " + divisor() + " = " + rem); + // Report sign of rem failure + if (rem != 0 && (rem ^ dividend) < 0) { + System.out.println(" rem & dividend have different signs"); + } + // Report range of rem failure + if (java.lang.Math.abs(rem) >= java.lang.Math.abs(divisor())) { + System.out.println(" remainder out of range"); + } + // Report quo/rem identity relationship failure + if ((quo * divisor()) + rem != dividend) { + System.out.println(" (" + quo + " * " + divisor() + ") + " + rem + " != " + + dividend); + } + } + return false; + } + return true; + } + + public void run() { + // Don't try to divide by zero + if (divisor() == 0) return; + + // Range of dividends to check. Try dividends from start to end + // inclusive, as well as variations on those values as shifted + // left. + int start = -1024; + int end = 1024; + + // Test int division using a variety of dividends. + int wrong = 0; + int total = 0; + + outerloop: + for (int i = start; i <= end; i++) { + for (int s = 0; s < 32; s += 4) { + total++; + int dividend = i << s; + if (!checkI(dividend)) { + wrong++; + // Stop on the first failure + // break outerloop; + } + } + } + if (wrong > 0) { + System.out.println("divisor " + divisor() + ": " + + wrong + "/" + total + " wrong int divisions"); + } + + // Test long division using a variety of dividends. + wrong = 0; + total = 0; + + outerloop: + for (int i = start; i <= end; i++) { + for (int s = 0; s < 64; s += 4) { + total++; + long dividend = i << s; + if (!checkL(dividend)) { + wrong++; + // Stop on the first failure + // break outerloop; + } + } + } + if (wrong > 0) { + System.out.println("divisor " + divisor() + ": " + + wrong + "/" + total + " wrong long divisions"); + } + + } + + // Reload this class with the "divisor" property set to the input parameter. + // This allows the JIT to see q.DIVISOR as a final constant, and change + // any divisions or mod operations into multiplies. + public static void test_divisor(int divisor, + URLClassLoader apploader) throws Exception { + System.setProperty("divisor", "" + divisor); + ClassLoader loader = new URLClassLoader(apploader.getURLs(), + apploader.getParent()); + Class c = loader.loadClass("Test"); + Runnable r = (Runnable)c.newInstance(); + r.run(); + } + + public static void main(String[] args) throws Exception { + Class cl = Class.forName("Test"); + URLClassLoader apploader = (URLClassLoader)cl.getClassLoader(); + + + // Test every divisor between -100 and 100. + for (int i = -100; i <= 100; i++) { + test_divisor(i, apploader); + } + + // Try a few divisors outside the typical range. + // The values below have been observed in rt.jar. + test_divisor(101, apploader); + test_divisor(400, apploader); + test_divisor(1000, apploader); + test_divisor(3600, apploader); + test_divisor(9973, apploader); + test_divisor(86400, apploader); + test_divisor(1000000, apploader); + } + +} diff --git a/hotspot/test/compiler/6775880/Test.java b/hotspot/test/compiler/6775880/Test.java index 7c952ec4530..a938f9e73c4 100644 --- a/hotspot/test/compiler/6775880/Test.java +++ b/hotspot/test/compiler/6775880/Test.java @@ -27,7 +27,7 @@ * @bug 6775880 * @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now") * @compile -source 1.4 -target 1.4 Test.java - * @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test */ public class Test { diff --git a/hotspot/test/compiler/6778657/Test.java b/hotspot/test/compiler/6778657/Test.java new file mode 100644 index 00000000000..4fdd33e9386 --- /dev/null +++ b/hotspot/test/compiler/6778657/Test.java @@ -0,0 +1,75 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* + * @test + * @bug 6778657 + * @summary Casts in SharedRuntime::f2i, f2l, d2i and d2l rely on undefined C++ behaviour + */ + +public class Test { + public static void check_f2i(int expect) { + float check = expect; + check *= 2; + int actual = (int) check; + if (actual != expect) + throw new RuntimeException("expecting " + expect + ", got " + actual); + } + + public static void check_f2l(long expect) { + float check = expect; + check *= 2; + long actual = (long) check; + if (actual != expect) + throw new RuntimeException("expecting " + expect + ", got " + actual); + } + + public static void check_d2i(int expect) { + double check = expect; + check *= 2; + int actual = (int) check; + if (actual != expect) + throw new RuntimeException("expecting " + expect + ", got " + actual); + } + + public static void check_d2l(long expect) { + double check = expect; + check *= 2; + long actual = (long) check; + if (actual != expect) + throw new RuntimeException("expecting " + expect + ", got " + actual); + } + + public static void main(String[] args) { + check_f2i(Integer.MAX_VALUE); + check_f2i(Integer.MIN_VALUE); + check_f2l(Long.MAX_VALUE); + check_f2l(Long.MIN_VALUE); + check_d2i(Integer.MAX_VALUE); + check_d2i(Integer.MIN_VALUE); + check_d2l(Long.MAX_VALUE); + check_d2l(Long.MIN_VALUE); + } +} + diff --git a/hotspot/test/compiler/6795161/Test.java b/hotspot/test/compiler/6795161/Test.java new file mode 100644 index 00000000000..62dbd0dc5cc --- /dev/null +++ b/hotspot/test/compiler/6795161/Test.java @@ -0,0 +1,60 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* + * @test + * @bug 6795161 + * @summary Escape analysis leads to data corruption + * @run main/othervm -server -Xcomp -XX:CompileOnly=Test -XX:+DoEscapeAnalysis Test + */ + +class Test_Class_1 { + static String var_1; + + static void badFunc(int size) + { + try { + for (int i = 0; i < 1; (new byte[size-i])[0] = 0, i++) {} + } catch (Exception e) { + // don't comment it out, it will lead to correct results ;) + //System.out.println("Got exception: " + e); + } + } +} + +public class Test { + static String var_1_copy = Test_Class_1.var_1; + + static byte var_check; + + public static void main(String[] args) + { + var_check = 1; + + Test_Class_1.badFunc(-1); + + System.out.println("EATester.var_check = " + Test.var_check + " (expected 1)\n"); + } +} + diff --git a/hotspot/test/compiler/6795362/Test6795362.java b/hotspot/test/compiler/6795362/Test6795362.java new file mode 100644 index 00000000000..2b37618ac76 --- /dev/null +++ b/hotspot/test/compiler/6795362/Test6795362.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6795362 + * @summary 32bit server compiler leads to wrong results on solaris-x86 + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6795362.sub Test6795362 + */ + +public class Test6795362 { + public static void main(String[] args) + { + sub(); + + if (var_bad != 0) + throw new InternalError(var_bad + " != 0"); + } + + static long var_bad = -1L; + + static void sub() + { + var_bad >>= 65; + var_bad /= 65; + } +} diff --git a/hotspot/test/compiler/6799693/Test.java b/hotspot/test/compiler/6799693/Test.java new file mode 100644 index 00000000000..dbb691e0384 --- /dev/null +++ b/hotspot/test/compiler/6799693/Test.java @@ -0,0 +1,47 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* + * @test + * @bug 6799693 + * @summary Server compiler leads to data corruption when expression throws an Exception + * @run main/othervm -Xcomp -XX:CompileOnly=Test Test + */ + +public class Test { + static int var_bad = 1; + + public static void main(String[] args) + { + var_bad++; + + try { + for (int i = 0; i < 10; i++) (new byte[((byte)-1 << i)])[0] = 0; + } + catch (Exception e) { System.out.println("Got " + e); } + + System.out.println("Test.var_bad = " + var_bad + " (expected 2)\n"); + } +} + diff --git a/hotspot/test/compiler/6800154/Test6800154.java b/hotspot/test/compiler/6800154/Test6800154.java new file mode 100644 index 00000000000..41b95bb0f50 --- /dev/null +++ b/hotspot/test/compiler/6800154/Test6800154.java @@ -0,0 +1,109 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6800154 + * @summary Add comments to long_by_long_mulhi() for better understandability + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6800154.divcomp Test6800154 + */ + +import java.net.URLClassLoader; + +public class Test6800154 implements Runnable { + static final long[] DIVIDENDS = { + 0, + 1, + 2, + 1423487, + 4444441, + 4918923241323L, + -1, + -24351, + 0x3333, + 0x0000000080000000L, + 0x7fffffffffffffffL, + 0x8000000000000000L + }; + + static final long[] DIVISORS = { + 1, + 2, + 17, + 12342, + 24123, + 143444, + 123444442344L, + -1, + -2, + -4423423234231423L, + 0x0000000080000000L, + 0x7fffffffffffffffL, + 0x8000000000000000L + }; + + // Initialize DIVISOR so that it is final in this class. + static final long DIVISOR; + + static { + long value = 0; + try { + value = Long.decode(System.getProperty("divisor")); + } catch (Throwable e) { + } + DIVISOR = value; + } + + public static void main(String[] args) throws Exception + { + Class cl = Class.forName("Test6800154"); + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); + + // Iterate over all divisors. + for (int i = 0; i < DIVISORS.length; i++) { + System.setProperty("divisor", "" + DIVISORS[i]); + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); + Class c = loader.loadClass("Test6800154"); + Runnable r = (Runnable) c.newInstance(); + r.run(); + } + } + + public void run() + { + // Iterate over all dividends. + for (int i = 0; i < DIVIDENDS.length; i++) { + long dividend = DIVIDENDS[i]; + + long expected = divint(dividend); + long result = divcomp(dividend); + + if (result != expected) + throw new InternalError(dividend + " / " + DIVISOR + " failed: " + result + " != " + expected); + } + } + + static long divint(long a) { return a / DIVISOR; } + static long divcomp(long a) { return a / DIVISOR; } +} diff --git a/hotspot/test/compiler/6805724/Test6805724.java b/hotspot/test/compiler/6805724/Test6805724.java new file mode 100644 index 00000000000..f05d8e6bf6e --- /dev/null +++ b/hotspot/test/compiler/6805724/Test6805724.java @@ -0,0 +1,80 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6805724 + * @summary ModLNode::Ideal() generates functionally incorrect graph when divisor is any (2^k-1) constant. + * + * @run main/othervm -Xcomp -XX:CompileOnly=Test6805724.fcomp Test6805724 + */ + +import java.net.URLClassLoader; + +public class Test6805724 implements Runnable { + // Initialize DIVISOR so that it is final in this class. + static final long DIVISOR; // 2^k-1 constant + + static { + long value = 0; + try { + value = Long.decode(System.getProperty("divisor")); + } catch (Throwable t) { + // This one is required for the Class.forName() in main. + } + DIVISOR = value; + } + + static long fint(long x) { + return x % DIVISOR; + } + + static long fcomp(long x) { + return x % DIVISOR; + } + + public void run() { + long a = 0x617981E1L; + + long expected = fint(a); + long result = fcomp(a); + + if (result != expected) + throw new InternalError(result + " != " + expected); + } + + public static void main(String args[]) throws Exception { + Class cl = Class.forName("Test6805724"); + URLClassLoader apploader = (URLClassLoader) cl.getClassLoader(); + + // Iterate over all 2^k-1 divisors. + for (int k = 1; k < Long.SIZE; k++) { + long divisor = (1L << k) - 1; + System.setProperty("divisor", "" + divisor); + ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent()); + Class c = loader.loadClass("Test6805724"); + Runnable r = (Runnable) c.newInstance(); + r.run(); + } + } +} diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a195c0946ac..d760b86ea59 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -19,3 +19,8 @@ e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38 036e0dca841a5a17f784d15c86a9da88d2a6f1e6 jdk7-b42 96fe28d4a9131e1a97bfe00f779e5626cd09c4d0 jdk7-b43 b203df0741af3eb08687bc5eb798bac87363758d jdk7-b44 +0f113667880d335cfa2c35721b1b45144fb757f5 jdk7-b45 +b2271877894af809b7703767fe8d4e38591a02a2 jdk7-b46 +d711ad1954b294957737ea386cfd4d3c05028a36 jdk7-b47 +39de90eb4822cafaacc69edd67ab5547e55ae920 jdk7-b48 +5c1f24531903573c1830775432276da567243f9c jdk7-b49 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 541312fa826..0912b5f8ec4 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -19,3 +19,8 @@ a8379d24aa03386610169cb0f4e4b8ed266a2e8d jdk7-b41 621c02d83abc850c170fb6726d57b19f1eaf5033 jdk7-b42 1ad2f51564db6ca4c6d95760cf13fb083d3dec94 jdk7-b43 344485a03674b6950a7a23d01a6efb8055afb6ec jdk7-b44 +dea7753d713936c5b6fd942a91811b0676537fd0 jdk7-b45 +af4a3eeb7812a5d09a241c50b51b3c648a9d45c1 jdk7-b46 +223011570edbd49bb0fe51cdeb2089f95d305267 jdk7-b47 +01e5dd31d0c10a2db3d50db346905d2d3db45e88 jdk7-b48 +18ca864890f3d4ed942ecbffb78c936a57759921 jdk7-b49 diff --git a/jdk/.hgtags b/jdk/.hgtags index 4ab2cd9e5c0..6a5bcb2becb 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -19,3 +19,8 @@ cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38 3ef0bdfa7609f79d4f2ea621f30cf593a2e432ce jdk7-b42 50c67678b0d180063ade199d398b67a54063fa7f jdk7-b43 d8eb2738db6b148911177d9bcfe888109b7f2f71 jdk7-b44 +527b426497a259d0605d069e3930e838948531a6 jdk7-b45 +4b03e27a44090d1f646af28dc58f9ead827e24c7 jdk7-b46 +b4ac413b1f129eeef0acab3f31081c1b7dfe3b27 jdk7-b47 +5fbd9ea7def17186693b6f7099b5d0dc73903eee jdk7-b48 +8311105ea7a3db7bcbcb2b696459127c7f2297a4 jdk7-b49 diff --git a/jdk/make/com/sun/org/apache/xml/Makefile b/jdk/make/com/sun/org/apache/xml/Makefile index 140a381c45e..36a15bac490 100644 --- a/jdk/make/com/sun/org/apache/xml/Makefile +++ b/jdk/make/com/sun/org/apache/xml/Makefile @@ -41,7 +41,7 @@ AUTO_FILES_JAVA_DIRS = com/sun/org/apache/xml # Resources # LOCALE_SET_DEFINITION = jre -NEW_RESOURCE_BUNDLES_PROPERTIES = \ +NEW_RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = \ $(PKGDIR)/internal/security/resource/config.dtd \ $(PKGDIR)/internal/security/resource/config.xml \ $(PKGDIR)/internal/security/resource/xmlsecurity_de.properties \ diff --git a/jdk/make/com/sun/rowset/Makefile b/jdk/make/com/sun/rowset/Makefile index 919ef46fd99..ff7641a128e 100644 --- a/jdk/make/com/sun/rowset/Makefile +++ b/jdk/make/com/sun/rowset/Makefile @@ -41,7 +41,7 @@ AUTO_FILES_JAVA_DIRS = com/sun/rowset # Resources # LOCALE_SET_DEFINITION = jre -RESOURCE_BUNDLES_PROPERTIES = $(PKGDIR)/RowSetResourceBundle.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = $(PKGDIR)/RowSetResourceBundle.properties # # Rules diff --git a/jdk/make/common/Defs-windows.gmk b/jdk/make/common/Defs-windows.gmk index 7b178497e12..75da038ffee 100644 --- a/jdk/make/common/Defs-windows.gmk +++ b/jdk/make/common/Defs-windows.gmk @@ -398,16 +398,7 @@ ifeq ($(ARCH), ia64) # SA will never be supported here. INCLUDE_SA = false else - # Hopefully, SA will be supported here one of these days, - # and these will be changed to true. Until then, - # to build SA on windows, do a control build with - # BUILD_WIN_SA=1 - # on the make command. - ifdef BUILD_WIN_SA - INCLUDE_SA = true - else - INCLUDE_SA = false - endif + INCLUDE_SA = true endif # Settings for the VERSIONINFO tap on windows. diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 76a1bc466f2..4bee467967d 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -911,14 +911,6 @@ initial-image-jdk:: initial-image-jdk-setup \ fi; \ done ifeq ($(PLATFORM), windows) - @# - @# Audio soundbank - Bug# 4236400 - @# Windows only: adding audio files to JDK's jre/lib directory. - @# - ($(CD) $(LIBDIR) && $(TAR) cf - \ - `$(FIND) audio -depth -print`) | \ - ($(CD) $(JDK_IMAGE_DIR)/jre/lib && $(TAR) xf -) - @# @# @# lib/ @# diff --git a/jdk/make/common/internal/BinaryPlugs.gmk b/jdk/make/common/internal/BinaryPlugs.gmk index bb2d64262ed..a77044af43c 100644 --- a/jdk/make/common/internal/BinaryPlugs.gmk +++ b/jdk/make/common/internal/BinaryPlugs.gmk @@ -29,9 +29,7 @@ # Names of native shared libraries -PLUG_JSOUND_LIBRARY=$(LIB_PREFIX)jsoundhs.$(LIBRARY_SUFFIX) -PLUG_LIBRARY_NAMES = \ - $(PLUG_JSOUND_LIBRARY) +PLUG_LIBRARY_NAMES= # Sub-directory where native shared libraries are located (e.g. jre/bin or...) @@ -74,62 +72,10 @@ com/sun/jmx/snmp/daemon/SnmpSocket.class \ com/sun/jmx/snmp/daemon/SnmpTimerServer.class \ com/sun/jmx/snmp/daemon/WaitQ.class -PLUG_SOUND_CLASS_NAMES = \ -com/sun/media/sound/AbstractPlayer.class \ -com/sun/media/sound/CircularBuffer.class \ -com/sun/media/sound/HeadspaceInstrument.class \ -com/sun/media/sound/HeadspaceMixer\$$1.class \ -com/sun/media/sound/HeadspaceMixer\$$MidiLine.class \ -com/sun/media/sound/HeadspaceMixer\$$MidiLineInfo.class \ -com/sun/media/sound/HeadspaceMixer\$$MixerInfo.class \ -com/sun/media/sound/HeadspaceMixer\$$MixerReverbControl\$$MixerReverbType.class \ -com/sun/media/sound/HeadspaceMixer\$$MixerReverbControl.class \ -com/sun/media/sound/HeadspaceMixer.class \ -com/sun/media/sound/HeadspaceMixerProvider.class \ -com/sun/media/sound/HeadspaceSample.class \ -com/sun/media/sound/HeadspaceSoundbank.class \ -com/sun/media/sound/HsbParser.class \ -com/sun/media/sound/MixerClip\$$1.class \ -com/sun/media/sound/MixerClip\$$MixerClipApplyReverbControl.class \ -com/sun/media/sound/MixerClip\$$MixerClipGainControl.class \ -com/sun/media/sound/MixerClip\$$MixerClipMuteControl.class \ -com/sun/media/sound/MixerClip\$$MixerClipPanControl.class \ -com/sun/media/sound/MixerClip\$$MixerClipSampleRateControl.class \ -com/sun/media/sound/MixerClip.class \ -com/sun/media/sound/MixerMidiChannel.class \ -com/sun/media/sound/MixerSequencer\$$1.class \ -com/sun/media/sound/MixerSequencer\$$ControllerVectorElement.class \ -com/sun/media/sound/MixerSequencer\$$MixerSequencerInfo.class \ -com/sun/media/sound/MixerSequencer\$$RecordingTrack.class \ -com/sun/media/sound/MixerSequencer.class \ -com/sun/media/sound/MixerSequencerProvider.class \ -com/sun/media/sound/MixerSourceLine\$$1.class \ -com/sun/media/sound/MixerSourceLine\$$MixerSourceLineApplyReverbControl.class \ -com/sun/media/sound/MixerSourceLine\$$MixerSourceLineGainControl.class \ -com/sun/media/sound/MixerSourceLine\$$MixerSourceLineMuteControl.class \ -com/sun/media/sound/MixerSourceLine\$$MixerSourceLinePanControl.class \ -com/sun/media/sound/MixerSourceLine\$$MixerSourceLineSampleRateControl.class \ -com/sun/media/sound/MixerSourceLine.class \ -com/sun/media/sound/MixerSynth\$$1.class \ -com/sun/media/sound/MixerSynth\$$MixerSynthInfo.class \ -com/sun/media/sound/MixerSynth\$$SynthReceiver.class \ -com/sun/media/sound/MixerSynth.class \ -com/sun/media/sound/MixerSynthProvider.class \ -com/sun/media/sound/MixerThread.class \ -com/sun/media/sound/RmfFileReader.class \ -com/sun/media/sound/SimpleInputDevice\$$1.class \ -com/sun/media/sound/SimpleInputDevice\$$InputDeviceDataLine.class \ -com/sun/media/sound/SimpleInputDevice\$$InputDevicePort.class \ -com/sun/media/sound/SimpleInputDevice\$$InputDevicePortInfo.class \ -com/sun/media/sound/SimpleInputDevice.class \ -com/sun/media/sound/SimpleInputDeviceProvider\$$1.class \ -com/sun/media/sound/SimpleInputDeviceProvider\$$InputDeviceInfo.class \ -com/sun/media/sound/SimpleInputDeviceProvider.class - # Class list temp files (used by both import and export of plugs) PLUG_TEMPDIR=$(ABS_TEMPDIR)/plugs -PLUG_CLASS_AREAS = jmf sound +PLUG_CLASS_AREAS = jmf PLUG_CLISTS = $(PLUG_CLASS_AREAS:%=$(PLUG_TEMPDIR)/%.clist) # Create jargs file command @@ -147,18 +93,11 @@ $(PLUG_TEMPDIR)/jmf.clist: @for i in $(PLUG_JMF_CLASS_NAMES) ; do \ $(ECHO) "$$i" >> $@; \ done -$(PLUG_TEMPDIR)/sound.clist: - @$(prep-target) - @for i in $(PLUG_SOUND_CLASS_NAMES) ; do \ - $(ECHO) "$$i" >> $@ ; \ - done $(PLUG_TEMPDIR)/all.clist: $(PLUG_CLISTS) @$(prep-target) $(CAT) $(PLUG_CLISTS) > $@ $(PLUG_TEMPDIR)/jmf.jargs: $(PLUG_TEMPDIR)/jmf.clist $(plug-create-jargs) -$(PLUG_TEMPDIR)/sound.jargs: $(PLUG_TEMPDIR)/sound.clist - $(plug-create-jargs) $(PLUG_TEMPDIR)/all.jargs: $(PLUG_TEMPDIR)/all.clist $(plug-create-jargs) @@ -193,25 +132,11 @@ endef # import-binary-plug-classes import-binary-plug-jmf-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/jmf.clist $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/jmf.clist) -import-binary-plug-sound-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/sound.clist - $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/sound.clist) # Import all classes from the jar file import-binary-plug-jar: \ - import-binary-plug-jmf-classes \ - import-binary-plug-sound-classes - -# Import native libraries - -$(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY): \ - $(PLUG_IMPORT_DIR)/$(PLUG_LOCATION_SUBDIR)/$(PLUG_JSOUND_LIBRARY) - $(import-binary-plug-file) - -# Rules only used by lower level makefiles - -import-binary-plug-jsound-library: \ - $(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY) + import-binary-plug-jmf-classes # Binary plug start/complete messages @@ -241,9 +166,7 @@ import-binary-plugs: \ import-binary-plugs-libs \ import-binary-plugs \ import-binary-plug-jar \ - import-binary-plug-jmf-classes \ - import-binary-plug-sound-classes \ - import-binary-plug-jsound-library + import-binary-plug-jmf-classes else # !OPENJDK @@ -280,12 +203,6 @@ $(PLUG_EXPORT_JARFILE): $(PLUG_TEMPDIR)/all.clist $(PLUG_TEMPDIR)/all.jargs @$(java-vm-cleanup) export-binary-plugs-jar: $(PLUG_EXPORT_JARFILE) -# Export native libraries - -$(PLUG_EXPORT_DIR)/$(PLUG_LOCATION_SUBDIR)/$(PLUG_JSOUND_LIBRARY): \ - $(LIB_LOCATION)/$(PLUG_JSOUND_LIBRARY) - $(export-binary-plug-file) - # Export binary plug start/complete messages export-binary-plugs-started: diff --git a/jdk/make/common/internal/Resources.gmk b/jdk/make/common/internal/Resources.gmk index dbc11ef832f..a772194b471 100644 --- a/jdk/make/common/internal/Resources.gmk +++ b/jdk/make/common/internal/Resources.gmk @@ -44,12 +44,8 @@ # # NEW_RESOURCE_BUNDLES_JAVA - new resource bundles implemented in # Java, not localized -# NEW_RESOURCE_BUNDLES_PROPERTIES - new resource bundles implemented as -# properties files, not localized # RESOURCE_BUNDLES_JAVA - resource bundles implemented in # Java, localized -# RESOURCE_BUNDLES_PROPERTIES - new resource bundles implemented as -# properties files, localized # # The following variable is now used for most .properties files in the JDK. # These properties files are converted into java and compiled with javac. @@ -61,6 +57,13 @@ # properties files, localized # NEW_RESOURCE_BUNDLES_COMPILED_PROPERTIES - same as above, not localized # +# For non-compiled properties files, use the following variables: +# +# NEW_RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES - new resource bundles implemented as +# properties files, not localized +# RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES - resource bundles implemented as +# properties files, localized +# # Other properties files to be installed are identified using the variable: # # OTHER_PROPERTIES @@ -109,11 +112,12 @@ COMPILED_PROPERTIES += $(RESOURCE_BUNDLES_COMPILED_PROPERTIES) \ FILES_java += $(COMPILED_PROPERTIES:%.properties=%.java) # Non-compiled files -PROPERTIES_FILES += $(NEW_RESOURCE_BUNDLES_PROPERTIES) -PROPERTIES_FILES += $(RESOURCE_BUNDLES_PROPERTIES) \ - $(foreach file,$(RESOURCE_BUNDLES_PROPERTIES), \ +PROPERTIES_FILES += $(NEW_RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES) +PROPERTIES_FILES += $(RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES) \ + $(foreach file,$(RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES), \ $(foreach locale,$(LOCALE_SUFFIXES), \ $(basename $(file))_$(locale)$(suffix $(file)))) +# other properties PROPERTIES_FILES += $(OTHER_PROPERTIES) # diff --git a/jdk/make/docs/CORE_PKGS.gmk b/jdk/make/docs/CORE_PKGS.gmk index 4a41a2005bf..f9b9ee59cc1 100644 --- a/jdk/make/docs/CORE_PKGS.gmk +++ b/jdk/make/docs/CORE_PKGS.gmk @@ -1,5 +1,5 @@ # -# Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -110,6 +110,9 @@ CORE_PKGS = \ java.nio.channels.spi \ java.nio.charset \ java.nio.charset.spi \ + java.nio.file \ + java.nio.file.attribute \ + java.nio.file.spi \ java.rmi \ java.rmi.activation \ java.rmi.dgc \ diff --git a/jdk/make/docs/NON_CORE_PKGS.gmk b/jdk/make/docs/NON_CORE_PKGS.gmk index ccf7a0f79a8..6028a85da34 100644 --- a/jdk/make/docs/NON_CORE_PKGS.gmk +++ b/jdk/make/docs/NON_CORE_PKGS.gmk @@ -1,5 +1,5 @@ # -# Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,8 @@ OLD_JSSE_PKGS = com.sun.net.ssl HTTPSERVER_PKGS = com.sun.net.httpserver \ com.sun.net.httpserver.spi +NIO_PKGS = com.sun.nio.file + DOCLETAPI_PKGS = com.sun.javadoc TAGLETAPI_FILE = com/sun/tools/doclets/Taglet.java @@ -92,6 +94,7 @@ NON_CORE_PKGS = $(DOMAPI_PKGS) \ $(MGMT_PKGS) \ $(JAAS_PKGS) \ $(JGSS_PKGS) \ + $(NIO_PKGS) \ $(OLD_JSSE_PKGS) \ $(HTTPSERVER_PKGS) \ $(SMARTCARDIO_PKGS) \ diff --git a/jdk/make/java/nio/Exportedfiles.gmk b/jdk/make/java/nio/Exportedfiles.gmk index 49c4e24ac3f..fd8b73f64b9 100644 --- a/jdk/make/java/nio/Exportedfiles.gmk +++ b/jdk/make/java/nio/Exportedfiles.gmk @@ -1,5 +1,5 @@ # -# Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ FILES_export = \ sun/nio/ch/DatagramChannelImpl.java \ sun/nio/ch/DatagramDispatcher.java \ sun/nio/ch/FileChannelImpl.java \ - sun/nio/ch/FileDispatcher.java \ + sun/nio/ch/FileDispatcherImpl.java \ sun/nio/ch/FileKey.java \ sun/nio/ch/FileLockImpl.java \ sun/nio/ch/IOStatus.java \ diff --git a/jdk/make/java/nio/FILES_c.gmk b/jdk/make/java/nio/FILES_c.gmk index 6f7c3ff3f74..b1670c20dfe 100644 --- a/jdk/make/java/nio/FILES_c.gmk +++ b/jdk/make/java/nio/FILES_c.gmk @@ -1,5 +1,5 @@ # -# Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ FILES_c = \ DatagramChannelImpl.c \ DatagramDispatcher.c \ FileChannelImpl.c \ - FileDispatcher.c \ + FileDispatcherImpl.c \ FileKey.c \ IOUtil.c \ MappedByteBuffer.c \ diff --git a/jdk/make/java/nio/FILES_java.gmk b/jdk/make/java/nio/FILES_java.gmk index 29f1f8f42c4..5027274f209 100644 --- a/jdk/make/java/nio/FILES_java.gmk +++ b/jdk/make/java/nio/FILES_java.gmk @@ -1,5 +1,5 @@ # -# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,19 +31,29 @@ FILES_src = \ java/nio/MappedByteBuffer.java \ java/nio/StringCharBuffer.java \ \ + java/nio/channels/AsynchronousByteChannel.java \ + java/nio/channels/AsynchronousChannel.java \ + java/nio/channels/AsynchronousChannelGroup.java \ + java/nio/channels/AsynchronousDatagramChannel.java \ + java/nio/channels/AsynchronousFileChannel.java \ + java/nio/channels/AsynchronousServerSocketChannel.java \ + java/nio/channels/AsynchronousSocketChannel.java \ java/nio/channels/ByteChannel.java \ java/nio/channels/Channel.java \ java/nio/channels/Channels.java \ + java/nio/channels/CompletionHandler.java \ java/nio/channels/DatagramChannel.java \ java/nio/channels/FileChannel.java \ java/nio/channels/FileLock.java \ java/nio/channels/GatheringByteChannel.java \ java/nio/channels/InterruptibleChannel.java \ + java/nio/channels/Pipe.java \ java/nio/channels/MembershipKey.java \ java/nio/channels/MulticastChannel.java \ java/nio/channels/NetworkChannel.java \ java/nio/channels/ReadableByteChannel.java \ java/nio/channels/ScatteringByteChannel.java \ + java/nio/channels/SeekableByteChannel.java \ java/nio/channels/SelectableChannel.java \ java/nio/channels/Selector.java \ java/nio/channels/SelectionKey.java \ @@ -55,6 +65,7 @@ FILES_src = \ java/nio/channels/spi/AbstractSelectableChannel.java \ java/nio/channels/spi/AbstractSelectionKey.java \ java/nio/channels/spi/AbstractSelector.java \ + java/nio/channels/spi/AsynchronousChannelProvider.java \ java/nio/channels/spi/SelectorProvider.java \ \ java/nio/charset/Charset.java \ @@ -66,21 +77,117 @@ FILES_src = \ \ java/nio/charset/spi/CharsetProvider.java \ \ + java/nio/file/AccessDeniedException.java \ + java/nio/file/AccessMode.java \ + java/nio/file/AtomicMoveNotSupportedException.java \ + java/nio/file/ClosedDirectoryStreamException.java \ + java/nio/file/ClosedFileSystemException.java \ + java/nio/file/ClosedWatchServiceException.java \ + java/nio/file/CopyOption.java \ + java/nio/file/DirectoryNotEmptyException.java \ + java/nio/file/DirectoryStream.java \ + java/nio/file/DirectoryStreamFilters.java \ + java/nio/file/FileAction.java \ + java/nio/file/FileAlreadyExistsException.java \ + java/nio/file/FileRef.java \ + java/nio/file/FileStore.java \ + java/nio/file/FileSystem.java \ + java/nio/file/FileSystemAlreadyExistsException.java \ + java/nio/file/FileSystemException.java \ + java/nio/file/FileSystemNotFoundException.java \ + java/nio/file/FileSystems.java \ + java/nio/file/FileTreeWalker.java \ + java/nio/file/FileVisitOption.java \ + java/nio/file/FileVisitResult.java \ + java/nio/file/FileVisitor.java \ + java/nio/file/Files.java \ + java/nio/file/InvalidPathException.java \ + java/nio/file/LinkOption.java \ + java/nio/file/LinkPermission.java \ + java/nio/file/NoSuchFileException.java \ + java/nio/file/NotDirectoryException.java \ + java/nio/file/NotLinkException.java \ + java/nio/file/OpenOption.java \ + java/nio/file/Path.java \ + java/nio/file/PathMatcher.java \ + java/nio/file/Paths.java \ + java/nio/file/ProviderMismatchException.java \ + java/nio/file/ProviderNotFoundException.java \ + java/nio/file/ReadOnlyFileSystemException.java \ + java/nio/file/SecureDirectoryStream.java \ + java/nio/file/SimpleFileVisitor.java \ + java/nio/file/StandardCopyOption.java \ + java/nio/file/StandardOpenOption.java \ + java/nio/file/StandardWatchEventKind.java \ + java/nio/file/WatchEvent.java \ + java/nio/file/WatchKey.java \ + java/nio/file/WatchService.java \ + java/nio/file/Watchable.java \ + \ + java/nio/file/attribute/AclEntry.java \ + java/nio/file/attribute/AclEntryFlag.java \ + java/nio/file/attribute/AclEntryPermission.java \ + java/nio/file/attribute/AclEntryType.java \ + java/nio/file/attribute/AclFileAttributeView.java \ + java/nio/file/attribute/AttributeView.java \ + java/nio/file/attribute/Attributes.java \ + java/nio/file/attribute/BasicFileAttributeView.java \ + java/nio/file/attribute/BasicFileAttributes.java \ + java/nio/file/attribute/DosFileAttributeView.java \ + java/nio/file/attribute/DosFileAttributes.java \ + java/nio/file/attribute/FileAttribute.java \ + java/nio/file/attribute/FileAttributeView.java \ + java/nio/file/attribute/FileOwnerAttributeView.java \ + java/nio/file/attribute/FileStoreAttributeView.java \ + java/nio/file/attribute/FileStoreSpaceAttributeView.java \ + java/nio/file/attribute/FileStoreSpaceAttributes.java \ + java/nio/file/attribute/GroupPrincipal.java \ + java/nio/file/attribute/UserDefinedFileAttributeView.java \ + java/nio/file/attribute/PosixFileAttributeView.java \ + java/nio/file/attribute/PosixFileAttributes.java \ + java/nio/file/attribute/PosixFilePermission.java \ + java/nio/file/attribute/PosixFilePermissions.java \ + java/nio/file/attribute/UserPrincipal.java \ + java/nio/file/attribute/UserPrincipalLookupService.java \ + java/nio/file/attribute/UserPrincipalNotFoundException.java \ + \ + java/nio/file/spi/AbstractPath.java \ + java/nio/file/spi/FileSystemProvider.java \ + java/nio/file/spi/FileTypeDetector.java \ + \ + com/sun/nio/file/ExtendedCopyOption.java \ + com/sun/nio/file/ExtendedOpenOption.java \ + com/sun/nio/file/ExtendedWatchEventModifier.java \ + com/sun/nio/file/SensitivityWatchEventModifier.java \ + \ sun/nio/ByteBuffered.java \ \ + sun/nio/ch/AbstractFuture.java \ sun/nio/ch/AbstractPollArrayWrapper.java \ sun/nio/ch/AllocatedNativeObject.java \ + sun/nio/ch/AsynchronousChannelGroupImpl.java \ + sun/nio/ch/AsynchronousFileChannelImpl.java \ + sun/nio/ch/AsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/AsynchronousSocketChannelImpl.java \ + sun/nio/ch/Cancellable.java \ sun/nio/ch/ChannelInputStream.java \ + sun/nio/ch/CompletedFuture.java \ sun/nio/ch/DatagramChannelImpl.java \ sun/nio/ch/DatagramDispatcher.java \ sun/nio/ch/DatagramSocketAdaptor.java \ + sun/nio/ch/DefaultAsynchronousChannelProvider.java \ sun/nio/ch/DefaultSelectorProvider.java \ sun/nio/ch/DirectBuffer.java \ sun/nio/ch/ExtendedSocketOption.java \ sun/nio/ch/FileChannelImpl.java \ sun/nio/ch/FileDispatcher.java \ + sun/nio/ch/FileDispatcherImpl.java \ sun/nio/ch/FileKey.java \ + sun/nio/ch/FileLockImpl.java \ + sun/nio/ch/FileLockTable.java \ + sun/nio/ch/Groupable.java \ sun/nio/ch/Interruptible.java \ + sun/nio/ch/Invoker.java \ sun/nio/ch/IOUtil.java \ sun/nio/ch/IOStatus.java \ sun/nio/ch/IOVecWrapper.java \ @@ -92,6 +199,7 @@ FILES_src = \ sun/nio/ch/NativeThreadSet.java \ sun/nio/ch/Net.java \ sun/nio/ch/OptionKey.java \ + sun/nio/ch/PendingFuture.java \ sun/nio/ch/PipeImpl.java \ sun/nio/ch/PollArrayWrapper.java \ sun/nio/ch/Reflect.java \ @@ -101,12 +209,14 @@ FILES_src = \ sun/nio/ch/SelChImpl.java \ sun/nio/ch/ServerSocketAdaptor.java \ sun/nio/ch/ServerSocketChannelImpl.java \ + sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \ sun/nio/ch/SinkChannelImpl.java \ sun/nio/ch/SocketAdaptor.java \ sun/nio/ch/SocketChannelImpl.java \ sun/nio/ch/SocketDispatcher.java \ sun/nio/ch/SocketOptionRegistry.java \ sun/nio/ch/SourceChannelImpl.java \ + sun/nio/ch/ThreadPool.java \ sun/nio/ch/Util.java \ \ sun/nio/cs/AbstractCharsetProvider.java \ @@ -134,6 +244,25 @@ FILES_src = \ sun/nio/cs/UTF_32LE_BOM.java \ sun/nio/cs/UTF_32Coder.java \ \ + sun/nio/fs/AbstractAclFileAttributeView.java \ + sun/nio/fs/AbstractBasicFileAttributeView.java \ + sun/nio/fs/AbstractFileStoreSpaceAttributeView.java \ + sun/nio/fs/AbstractFileTypeDetector.java \ + sun/nio/fs/AbstractPoller.java \ + sun/nio/fs/AbstractUserDefinedFileAttributeView.java \ + sun/nio/fs/AbstractWatchKey.java \ + sun/nio/fs/AbstractWatchService.java \ + sun/nio/fs/BasicFileAttributesHolder.java \ + sun/nio/fs/Cancellable.java \ + sun/nio/fs/DefaultFileSystemProvider.java \ + sun/nio/fs/DefaultFileTypeDetector.java \ + sun/nio/fs/FileOwnerAttributeViewImpl.java \ + sun/nio/fs/Globs.java \ + sun/nio/fs/MimeType.java \ + sun/nio/fs/NativeBuffer.java \ + sun/nio/fs/NativeBuffers.java \ + sun/nio/fs/Reflect.java \ + \ java/net/DatagramSocket.java \ java/net/DatagramSocketImpl.java \ java/net/PlainSocketImpl.java \ @@ -244,24 +373,31 @@ FILES_gen_ex = \ java/nio/InvalidMarkException.java \ java/nio/ReadOnlyBufferException.java \ \ + java/nio/channels/AcceptPendingException.java \ java/nio/channels/AlreadyBoundException.java \ java/nio/channels/AlreadyConnectedException.java \ java/nio/channels/AsynchronousCloseException.java \ + java/nio/channels/CancelledKeyException.java \ java/nio/channels/ClosedByInterruptException.java \ java/nio/channels/ClosedChannelException.java \ java/nio/channels/ClosedSelectorException.java \ java/nio/channels/ConnectionPendingException.java \ java/nio/channels/FileLockInterruptionException.java \ java/nio/channels/IllegalBlockingModeException.java \ + java/nio/channels/IllegalChannelGroupException.java \ java/nio/channels/IllegalSelectorException.java \ + java/nio/channels/InterruptedByTimeoutException.java \ java/nio/channels/NoConnectionPendingException.java \ java/nio/channels/NonReadableChannelException.java \ java/nio/channels/NonWritableChannelException.java \ java/nio/channels/NotYetBoundException.java \ java/nio/channels/NotYetConnectedException.java \ java/nio/channels/OverlappingFileLockException.java \ + java/nio/channels/ReadPendingException.java \ + java/nio/channels/ShutdownChannelGroupException.java \ java/nio/channels/UnresolvedAddressException.java \ java/nio/channels/UnsupportedAddressTypeException.java \ + java/nio/channels/WritePendingException.java \ \ java/nio/charset/CharacterCodingException.java \ java/nio/charset/IllegalCharsetNameException.java \ diff --git a/jdk/make/java/nio/Makefile b/jdk/make/java/nio/Makefile index bf7bc2e0236..f85cc69e525 100644 --- a/jdk/make/java/nio/Makefile +++ b/jdk/make/java/nio/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -56,56 +56,214 @@ FILES_java += \ sun/nio/ch/DevPollSelectorProvider.java \ sun/nio/ch/InheritedChannel.java \ sun/nio/ch/PollSelectorProvider.java \ - sun/nio/ch/PollSelectorImpl.java + sun/nio/ch/PollSelectorImpl.java \ + sun/nio/ch/Port.java \ + sun/nio/ch/SimpleAsynchronousFileChannelImpl.java \ + sun/nio/ch/SolarisAsynchronousChannelProvider.java \ + sun/nio/ch/SolarisEventPort.java \ + sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ + \ + sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/PollingWatchService.java \ + sun/nio/fs/SolarisAclFileAttributeView.java \ + sun/nio/fs/SolarisFileStore.java \ + sun/nio/fs/SolarisFileSystem.java \ + sun/nio/fs/SolarisFileSystemProvider.java \ + sun/nio/fs/SolarisUserDefinedFileAttributeView.java \ + sun/nio/fs/SolarisNativeDispatcher.java \ + sun/nio/fs/SolarisWatchService.java \ + sun/nio/fs/UnixChannelFactory.java \ + sun/nio/fs/UnixCopyFile.java \ + sun/nio/fs/UnixDirectoryStream.java \ + sun/nio/fs/UnixException.java \ + sun/nio/fs/UnixFileAttributeViews.java \ + sun/nio/fs/UnixFileAttributes.java \ + sun/nio/fs/UnixFileKey.java \ + sun/nio/fs/UnixFileModeAttribute.java \ + sun/nio/fs/UnixFileStore.java \ + sun/nio/fs/UnixFileStoreAttributes.java \ + sun/nio/fs/UnixFileSystem.java \ + sun/nio/fs/UnixFileSystemProvider.java \ + sun/nio/fs/UnixMountEntry.java \ + sun/nio/fs/UnixNativeDispatcher.java \ + sun/nio/fs/UnixPath.java \ + sun/nio/fs/UnixSecureDirectoryStream.java \ + sun/nio/fs/UnixUriUtils.java \ + sun/nio/fs/UnixUserPrincipals.java FILES_c += \ DevPollArrayWrapper.c \ InheritedChannel.c \ NativeThread.c \ - PollArrayWrapper.c + PollArrayWrapper.c \ + SolarisEventPort.c \ + UnixAsynchronousServerSocketChannelImpl.c \ + UnixAsynchronousSocketChannelImpl.c \ + \ + GnomeFileTypeDetector.c \ + SolarisNativeDispatcher.c \ + SolarisWatchService.c \ + UnixCopyFile.c \ + UnixNativeDispatcher.c FILES_export += \ sun/nio/ch/DevPollArrayWrapper.java \ sun/nio/ch/InheritedChannel.java \ - sun/nio/ch/NativeThread.java + sun/nio/ch/NativeThread.java \ + sun/nio/ch/SolarisEventPort.java \ + sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ + \ + sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/SolarisNativeDispatcher.java \ + sun/nio/fs/SolarisWatchService.java \ + sun/nio/fs/UnixCopyFile.java \ + sun/nio/fs/UnixNativeDispatcher.java + +FILES_gen += \ + sun/nio/fs/SolarisConstants.java \ + sun/nio/fs/UnixConstants.java endif # PLATFORM = solaris ifeq ($(PLATFORM), windows) FILES_java += \ + sun/nio/ch/Iocp.java \ + sun/nio/ch/PendingIoCache.java \ + sun/nio/ch/WindowsAsynchronousChannelProvider.java \ + sun/nio/ch/WindowsAsynchronousFileChannelImpl.java \ + sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java \ sun/nio/ch/WindowsSelectorImpl.java \ - sun/nio/ch/WindowsSelectorProvider.java + sun/nio/ch/WindowsSelectorProvider.java \ + \ + sun/nio/fs/RegistryFileTypeDetector.java \ + sun/nio/fs/WindowsAclFileAttributeView.java \ + sun/nio/fs/WindowsChannelFactory.java \ + sun/nio/fs/WindowsConstants.java \ + sun/nio/fs/WindowsDirectoryStream.java \ + sun/nio/fs/WindowsException.java \ + sun/nio/fs/WindowsFileAttributeViews.java \ + sun/nio/fs/WindowsFileAttributes.java \ + sun/nio/fs/WindowsFileCopy.java \ + sun/nio/fs/WindowsFileStore.java \ + sun/nio/fs/WindowsFileSystem.java \ + sun/nio/fs/WindowsFileSystemProvider.java \ + sun/nio/fs/WindowsLinkSupport.java \ + sun/nio/fs/WindowsUserDefinedFileAttributeView.java \ + sun/nio/fs/WindowsNativeDispatcher.java \ + sun/nio/fs/WindowsPath.java \ + sun/nio/fs/WindowsPathParser.java \ + sun/nio/fs/WindowsPathType.java \ + sun/nio/fs/WindowsSecurity.java \ + sun/nio/fs/WindowsSecurityDescriptor.java \ + sun/nio/fs/WindowsUriSupport.java \ + sun/nio/fs/WindowsUserPrincipals.java \ + sun/nio/fs/WindowsWatchService.java FILES_c += \ + Iocp.c \ + RegistryFileTypeDetector.c \ + WindowsAsynchronousFileChannelImpl.c \ + WindowsAsynchronousServerSocketChannelImpl.c \ + WindowsAsynchronousSocketChannelImpl.c \ + WindowsNativeDispatcher.c \ WindowsSelectorImpl.c FILES_export += \ - sun/nio/ch/WindowsSelectorImpl.java + sun/nio/ch/Iocp.java \ + sun/nio/ch/WindowsAsynchronousFileChannelImpl.java \ + sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java \ + sun/nio/ch/WindowsSelectorImpl.java \ + sun/nio/fs/WindowsNativeDispatcher.java \ + sun/nio/fs/RegistryFileTypeDetector.java endif # PLATFORM = windows ifeq ($(PLATFORM), linux) FILES_java += \ sun/nio/ch/AbstractPollSelectorImpl.java \ + sun/nio/ch/EPoll.java \ sun/nio/ch/EPollArrayWrapper.java \ + sun/nio/ch/EPollPort.java \ sun/nio/ch/EPollSelectorProvider.java \ sun/nio/ch/EPollSelectorImpl.java \ sun/nio/ch/InheritedChannel.java \ + sun/nio/ch/LinuxAsynchronousChannelProvider.java \ sun/nio/ch/PollSelectorProvider.java \ - sun/nio/ch/PollSelectorImpl.java + sun/nio/ch/PollSelectorImpl.java \ + sun/nio/ch/Port.java \ + sun/nio/ch/SimpleAsynchronousFileChannelImpl.java \ + sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ + \ + sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/LinuxDosFileAttributeView.java \ + sun/nio/fs/LinuxFileStore.java \ + sun/nio/fs/LinuxFileSystem.java \ + sun/nio/fs/LinuxFileSystemProvider.java \ + sun/nio/fs/LinuxUserDefinedFileAttributeView.java \ + sun/nio/fs/LinuxNativeDispatcher.java \ + sun/nio/fs/LinuxWatchService.java \ + sun/nio/fs/PollingWatchService.java \ + sun/nio/fs/UnixChannelFactory.java \ + sun/nio/fs/UnixCopyFile.java \ + sun/nio/fs/UnixDirectoryStream.java \ + sun/nio/fs/UnixException.java \ + sun/nio/fs/UnixFileAttributeViews.java \ + sun/nio/fs/UnixFileAttributes.java \ + sun/nio/fs/UnixFileKey.java \ + sun/nio/fs/UnixFileModeAttribute.java \ + sun/nio/fs/UnixFileStore.java \ + sun/nio/fs/UnixFileStoreAttributes.java \ + sun/nio/fs/UnixFileSystem.java \ + sun/nio/fs/UnixFileSystemProvider.java \ + sun/nio/fs/UnixMountEntry.java \ + sun/nio/fs/UnixNativeDispatcher.java \ + sun/nio/fs/UnixPath.java \ + sun/nio/fs/UnixSecureDirectoryStream.java \ + sun/nio/fs/UnixUriUtils.java \ + sun/nio/fs/UnixUserPrincipals.java FILES_c += \ + EPoll.c \ EPollArrayWrapper.c \ + EPollPort.c \ InheritedChannel.c \ NativeThread.c \ - PollArrayWrapper.c + PollArrayWrapper.c \ + UnixAsynchronousServerSocketChannelImpl.c \ + UnixAsynchronousSocketChannelImpl.c \ + \ + GnomeFileTypeDetector.c \ + LinuxNativeDispatcher.c \ + LinuxWatchService.c \ + UnixCopyFile.c \ + UnixNativeDispatcher.c FILES_export += \ + sun/nio/ch/EPoll.java \ sun/nio/ch/EPollArrayWrapper.java \ + sun/nio/ch/EPollPort.java \ sun/nio/ch/InheritedChannel.java \ - sun/nio/ch/NativeThread.java + sun/nio/ch/NativeThread.java \ + sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ + sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ + \ + sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/LinuxNativeDispatcher.java \ + sun/nio/fs/LinuxWatchService.java \ + sun/nio/fs/UnixCopyFile.java \ + sun/nio/fs/UnixNativeDispatcher.java + +FILES_gen += \ + sun/nio/fs/UnixConstants.java endif # PLATFORM = linux +# # Find platform-specific C source files # +vpath %.c $(PLATFORM_SRC)/native/sun/nio/fs vpath %.c $(PLATFORM_SRC)/native/sun/nio/ch vpath %.c $(SHARE_SRC)/native/sun/nio/ch @@ -175,12 +333,14 @@ CH_SRC=$(NIO_SRC)/channels CS_SRC=$(NIO_SRC)/charset SCH_SRC=$(SNIO_SRC)/ch SCS_SRC=$(SNIO_SRC)/cs +SFS_SRC=$(SNIO_SRC)/fs BUF_GEN=$(NIO_GEN) CH_GEN=$(NIO_GEN)/channels CS_GEN=$(NIO_GEN)/charset SCH_GEN=$(SNIO_GEN)/ch SCS_GEN=$(SNIO_GEN)/cs +SFS_GEN=$(SNIO_GEN)/fs FILES_gensbcs_out = $(FILES_gen_sbcs:%.java=$(GENSRCDIR)/%.java) @@ -670,4 +830,40 @@ $(FILES_gensbcs_out): $(GENCSSRC)/SingleByte-X.java $(GENCSSRC)/sbcs $(BOOT_JAVA_CMD) -cp $(CHARSETMAPPING_JARFILE) build.tools.charsetmapping.GenerateSBCS \ $(GENCSSRC) $(SCS_GEN) sbcs +# +# Generated file system implementation classes (Unix only) +# + +GENUC_SRC = $(PLATFORM_SRC)/native/sun/nio/fs/genUnixConstants.c + +GENUC_EXE = $(TEMPDIR)/genUnixConstants + +GENUC_COPYRIGHT_YEARS = $(shell $(CAT) $(GENUC_SRC) | \ + $(NAWK) '/^.*Copyright.*Sun/ { print $$3 }') + +$(GENUC_EXE) : $(GENUC_SRC) + $(prep-target) + $(CC) $(CPPFLAGS) -o $@ $(GENUC_SRC) + +$(SFS_GEN)/UnixConstants.java: $(GENUC_EXE) + $(prep-target) + NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(GENUC_COPYRIGHT_YEARS) > $@ + $(GENUC_EXE) >> $@ + +GENSC_SRC = $(PLATFORM_SRC)/native/sun/nio/fs/genSolarisConstants.c + +GENSC_EXE = $(TEMPDIR)/genSolarisConstants + +GENSC_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSC_SRC) | \ + $(NAWK) '/^.*Copyright.*Sun/ { print $$3 }') + +$(GENSC_EXE) : $(GENSC_SRC) + $(prep-target) + $(CC) $(CPPFLAGS) -o $@ $(GENSC_SRC) + +$(SFS_GEN)/SolarisConstants.java: $(GENSC_EXE) + $(prep-target) + NAWK="$(NAWK)" SH="$(SH)" $(SH) -e addNotices.sh $(GENSC_COPYRIGHT_YEARS) > $@ + $(GENSC_EXE) >> $@ + .PHONY: sources diff --git a/jdk/make/java/nio/mapfile-linux b/jdk/make/java/nio/mapfile-linux index 3fb47b0eb7c..0bd240811c5 100644 --- a/jdk/make/java/nio/mapfile-linux +++ b/jdk/make/java/nio/mapfile-linux @@ -1,5 +1,5 @@ # -# Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -44,27 +44,38 @@ SUNWprivate_1.1 { Java_sun_nio_ch_EPollArrayWrapper_interrupt; Java_sun_nio_ch_EPollArrayWrapper_offsetofData; Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent; + Java_sun_nio_ch_EPoll_init; + Java_sun_nio_ch_EPoll_eventSize; + Java_sun_nio_ch_EPoll_eventsOffset; + Java_sun_nio_ch_EPoll_dataOffset; + Java_sun_nio_ch_EPoll_epollCreate; + Java_sun_nio_ch_EPoll_epollCtl; + Java_sun_nio_ch_EPoll_epollWait; + Java_sun_nio_ch_EPollPort_close0; + Java_sun_nio_ch_EPollPort_drain1; + Java_sun_nio_ch_EPollPort_interrupt; + Java_sun_nio_ch_EPollPort_socketpair; Java_sun_nio_ch_FileChannelImpl_close0; - Java_sun_nio_ch_FileChannelImpl_force0; Java_sun_nio_ch_FileChannelImpl_initIDs; - Java_sun_nio_ch_FileChannelImpl_lock0; Java_sun_nio_ch_FileChannelImpl_map0; Java_sun_nio_ch_FileChannelImpl_position0; - Java_sun_nio_ch_FileChannelImpl_release0; - Java_sun_nio_ch_FileChannelImpl_size0; Java_sun_nio_ch_FileChannelImpl_transferTo0; - Java_sun_nio_ch_FileChannelImpl_truncate0; Java_sun_nio_ch_FileChannelImpl_unmap0; - Java_sun_nio_ch_FileDispatcher_close0; - Java_sun_nio_ch_FileDispatcher_closeIntFD; - Java_sun_nio_ch_FileDispatcher_init; - Java_sun_nio_ch_FileDispatcher_preClose0; - Java_sun_nio_ch_FileDispatcher_pread0; - Java_sun_nio_ch_FileDispatcher_pwrite0; - Java_sun_nio_ch_FileDispatcher_read0; - Java_sun_nio_ch_FileDispatcher_readv0; - Java_sun_nio_ch_FileDispatcher_write0; - Java_sun_nio_ch_FileDispatcher_writev0; + Java_sun_nio_ch_FileDispatcherImpl_close0; + Java_sun_nio_ch_FileDispatcherImpl_closeIntFD; + Java_sun_nio_ch_FileDispatcherImpl_force0; + Java_sun_nio_ch_FileDispatcherImpl_init; + Java_sun_nio_ch_FileDispatcherImpl_lock0; + Java_sun_nio_ch_FileDispatcherImpl_preClose0; + Java_sun_nio_ch_FileDispatcherImpl_pread0; + Java_sun_nio_ch_FileDispatcherImpl_pwrite0; + Java_sun_nio_ch_FileDispatcherImpl_read0; + Java_sun_nio_ch_FileDispatcherImpl_readv0; + Java_sun_nio_ch_FileDispatcherImpl_release0; + Java_sun_nio_ch_FileDispatcherImpl_size0; + Java_sun_nio_ch_FileDispatcherImpl_truncate0; + Java_sun_nio_ch_FileDispatcherImpl_write0; + Java_sun_nio_ch_FileDispatcherImpl_writev0; Java_sun_nio_ch_FileKey_init; Java_sun_nio_ch_FileKey_initIDs; Java_sun_nio_ch_InheritedChannel_close0; @@ -108,6 +119,76 @@ SUNWprivate_1.1 { Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_SocketChannelImpl_checkConnect; + Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; + Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; + Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; + Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio; + Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; + Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; + Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs; + Java_sun_nio_fs_LinuxWatchService_init; + Java_sun_nio_fs_LinuxWatchService_eventSize; + Java_sun_nio_fs_LinuxWatchService_eventOffsets; + Java_sun_nio_fs_LinuxWatchService_inotifyInit; + Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch; + Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch; + Java_sun_nio_fs_LinuxWatchService_configureBlocking; + Java_sun_nio_fs_LinuxWatchService_socketpair; + Java_sun_nio_fs_LinuxWatchService_poll; + Java_sun_nio_fs_LinuxNativeDispatcher_init; + Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0; + Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr; + Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0; + Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0; + Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0; + Java_sun_nio_fs_LinuxNativeDispatcher_endmntent; + Java_sun_nio_fs_UnixNativeDispatcher_initIDs; + Java_sun_nio_fs_UnixNativeDispatcher_getcwd; + Java_sun_nio_fs_UnixNativeDispatcher_strerror; + Java_sun_nio_fs_UnixNativeDispatcher_dup; + Java_sun_nio_fs_UnixNativeDispatcher_access0; + Java_sun_nio_fs_UnixNativeDispatcher_stat0; + Java_sun_nio_fs_UnixNativeDispatcher_lstat0; + Java_sun_nio_fs_UnixNativeDispatcher_fstat; + Java_sun_nio_fs_UnixNativeDispatcher_fstatat0; + Java_sun_nio_fs_UnixNativeDispatcher_chmod0; + Java_sun_nio_fs_UnixNativeDispatcher_fchmod; + Java_sun_nio_fs_UnixNativeDispatcher_chown0; + Java_sun_nio_fs_UnixNativeDispatcher_lchown0; + Java_sun_nio_fs_UnixNativeDispatcher_fchown; + Java_sun_nio_fs_UnixNativeDispatcher_utimes0; + Java_sun_nio_fs_UnixNativeDispatcher_futimes; + Java_sun_nio_fs_UnixNativeDispatcher_open0; + Java_sun_nio_fs_UnixNativeDispatcher_openat0; + Java_sun_nio_fs_UnixNativeDispatcher_close; + Java_sun_nio_fs_UnixNativeDispatcher_read; + Java_sun_nio_fs_UnixNativeDispatcher_write; + Java_sun_nio_fs_UnixNativeDispatcher_fopen0; + Java_sun_nio_fs_UnixNativeDispatcher_fclose; + Java_sun_nio_fs_UnixNativeDispatcher_opendir0; + Java_sun_nio_fs_UnixNativeDispatcher_fdopendir; + Java_sun_nio_fs_UnixNativeDispatcher_readdir; + Java_sun_nio_fs_UnixNativeDispatcher_closedir; + Java_sun_nio_fs_UnixNativeDispatcher_link0; + Java_sun_nio_fs_UnixNativeDispatcher_unlink0; + Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0; + Java_sun_nio_fs_UnixNativeDispatcher_rename0; + Java_sun_nio_fs_UnixNativeDispatcher_renameat0; + Java_sun_nio_fs_UnixNativeDispatcher_mkdir0; + Java_sun_nio_fs_UnixNativeDispatcher_rmdir0; + Java_sun_nio_fs_UnixNativeDispatcher_symlink0; + Java_sun_nio_fs_UnixNativeDispatcher_readlink0; + Java_sun_nio_fs_UnixNativeDispatcher_realpath0; + Java_sun_nio_fs_UnixNativeDispatcher_statvfs0; + Java_sun_nio_fs_UnixNativeDispatcher_pathconf0; + Java_sun_nio_fs_UnixNativeDispatcher_fpathconf; + Java_sun_nio_fs_UnixNativeDispatcher_mknod0; + Java_sun_nio_fs_UnixNativeDispatcher_getpwuid; + Java_sun_nio_fs_UnixNativeDispatcher_getgrgid; + Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0; + Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0; + Java_sun_nio_fs_UnixNativeDispatcher_getextmntent; + Java_sun_nio_fs_UnixCopyFile_transfer; local: *; diff --git a/jdk/make/java/nio/mapfile-solaris b/jdk/make/java/nio/mapfile-solaris index 6e109e2faba..2192a5a7751 100644 --- a/jdk/make/java/nio/mapfile-solaris +++ b/jdk/make/java/nio/mapfile-solaris @@ -1,5 +1,5 @@ # -# Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,26 +43,26 @@ SUNWprivate_1.1 { Java_sun_nio_ch_DevPollArrayWrapper_register; Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple; Java_sun_nio_ch_FileChannelImpl_close0; - Java_sun_nio_ch_FileChannelImpl_force0; Java_sun_nio_ch_FileChannelImpl_initIDs; - Java_sun_nio_ch_FileChannelImpl_lock0; Java_sun_nio_ch_FileChannelImpl_map0; Java_sun_nio_ch_FileChannelImpl_position0; - Java_sun_nio_ch_FileChannelImpl_release0; - Java_sun_nio_ch_FileChannelImpl_size0; Java_sun_nio_ch_FileChannelImpl_transferTo0; - Java_sun_nio_ch_FileChannelImpl_truncate0; Java_sun_nio_ch_FileChannelImpl_unmap0; - Java_sun_nio_ch_FileDispatcher_close0; - Java_sun_nio_ch_FileDispatcher_closeIntFD; - Java_sun_nio_ch_FileDispatcher_init; - Java_sun_nio_ch_FileDispatcher_preClose0; - Java_sun_nio_ch_FileDispatcher_pread0; - Java_sun_nio_ch_FileDispatcher_pwrite0; - Java_sun_nio_ch_FileDispatcher_read0; - Java_sun_nio_ch_FileDispatcher_readv0; - Java_sun_nio_ch_FileDispatcher_write0; - Java_sun_nio_ch_FileDispatcher_writev0; + Java_sun_nio_ch_FileDispatcherImpl_close0; + Java_sun_nio_ch_FileDispatcherImpl_closeIntFD; + Java_sun_nio_ch_FileDispatcherImpl_force0; + Java_sun_nio_ch_FileDispatcherImpl_init; + Java_sun_nio_ch_FileDispatcherImpl_lock0; + Java_sun_nio_ch_FileDispatcherImpl_preClose0; + Java_sun_nio_ch_FileDispatcherImpl_pread0; + Java_sun_nio_ch_FileDispatcherImpl_pwrite0; + Java_sun_nio_ch_FileDispatcherImpl_read0; + Java_sun_nio_ch_FileDispatcherImpl_readv0; + Java_sun_nio_ch_FileDispatcherImpl_release0; + Java_sun_nio_ch_FileDispatcherImpl_size0; + Java_sun_nio_ch_FileDispatcherImpl_truncate0; + Java_sun_nio_ch_FileDispatcherImpl_write0; + Java_sun_nio_ch_FileDispatcherImpl_writev0; Java_sun_nio_ch_FileKey_init; Java_sun_nio_ch_FileKey_initIDs; Java_sun_nio_ch_InheritedChannel_close0; @@ -106,6 +106,75 @@ SUNWprivate_1.1 { Java_sun_nio_ch_ServerSocketChannelImpl_accept0; Java_sun_nio_ch_ServerSocketChannelImpl_initIDs; Java_sun_nio_ch_SocketChannelImpl_checkConnect; + Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; + Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; + Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; + Java_sun_nio_ch_SolarisEventPort_init; + Java_sun_nio_ch_SolarisEventPort_portCreate; + Java_sun_nio_ch_SolarisEventPort_portClose; + Java_sun_nio_ch_SolarisEventPort_portAssociate; + Java_sun_nio_ch_SolarisEventPort_portGet; + Java_sun_nio_ch_SolarisEventPort_portGetn; + Java_sun_nio_ch_SolarisEventPort_portSend; + Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio; + Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; + Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; + Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs; + Java_sun_nio_fs_UnixNativeDispatcher_initIDs; + Java_sun_nio_fs_UnixNativeDispatcher_getcwd; + Java_sun_nio_fs_UnixNativeDispatcher_strerror; + Java_sun_nio_fs_UnixNativeDispatcher_dup; + Java_sun_nio_fs_UnixNativeDispatcher_access0; + Java_sun_nio_fs_UnixNativeDispatcher_stat0; + Java_sun_nio_fs_UnixNativeDispatcher_lstat0; + Java_sun_nio_fs_UnixNativeDispatcher_fstat; + Java_sun_nio_fs_UnixNativeDispatcher_fstatat0; + Java_sun_nio_fs_UnixNativeDispatcher_chmod0; + Java_sun_nio_fs_UnixNativeDispatcher_fchmod; + Java_sun_nio_fs_UnixNativeDispatcher_chown0; + Java_sun_nio_fs_UnixNativeDispatcher_lchown0; + Java_sun_nio_fs_UnixNativeDispatcher_fchown; + Java_sun_nio_fs_UnixNativeDispatcher_utimes0; + Java_sun_nio_fs_UnixNativeDispatcher_futimes; + Java_sun_nio_fs_UnixNativeDispatcher_open0; + Java_sun_nio_fs_UnixNativeDispatcher_openat0; + Java_sun_nio_fs_UnixNativeDispatcher_close; + Java_sun_nio_fs_UnixNativeDispatcher_read; + Java_sun_nio_fs_UnixNativeDispatcher_write; + Java_sun_nio_fs_UnixNativeDispatcher_fopen0; + Java_sun_nio_fs_UnixNativeDispatcher_fclose; + Java_sun_nio_fs_UnixNativeDispatcher_opendir0; + Java_sun_nio_fs_UnixNativeDispatcher_fdopendir; + Java_sun_nio_fs_UnixNativeDispatcher_readdir; + Java_sun_nio_fs_UnixNativeDispatcher_closedir; + Java_sun_nio_fs_UnixNativeDispatcher_link0; + Java_sun_nio_fs_UnixNativeDispatcher_unlink0; + Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0; + Java_sun_nio_fs_UnixNativeDispatcher_rename0; + Java_sun_nio_fs_UnixNativeDispatcher_renameat0; + Java_sun_nio_fs_UnixNativeDispatcher_mkdir0; + Java_sun_nio_fs_UnixNativeDispatcher_rmdir0; + Java_sun_nio_fs_UnixNativeDispatcher_symlink0; + Java_sun_nio_fs_UnixNativeDispatcher_readlink0; + Java_sun_nio_fs_UnixNativeDispatcher_realpath0; + Java_sun_nio_fs_UnixNativeDispatcher_statvfs0; + Java_sun_nio_fs_UnixNativeDispatcher_pathconf0; + Java_sun_nio_fs_UnixNativeDispatcher_fpathconf; + Java_sun_nio_fs_UnixNativeDispatcher_mknod0; + Java_sun_nio_fs_UnixNativeDispatcher_getpwuid; + Java_sun_nio_fs_UnixNativeDispatcher_getgrgid; + Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0; + Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0; + Java_sun_nio_fs_UnixNativeDispatcher_getextmntent; + Java_sun_nio_fs_UnixCopyFile_transfer; + Java_sun_nio_fs_SolarisNativeDispatcher_init; + Java_sun_nio_fs_SolarisNativeDispatcher_facl; + Java_sun_nio_fs_SolarisWatchService_init; + Java_sun_nio_fs_SolarisWatchService_portCreate; + Java_sun_nio_fs_SolarisWatchService_portAssociate; + Java_sun_nio_fs_SolarisWatchService_portDissociate; + Java_sun_nio_fs_SolarisWatchService_portSend; + Java_sun_nio_fs_SolarisWatchService_portGetn; local: *; diff --git a/jdk/make/javax/sound/Makefile b/jdk/make/javax/sound/Makefile index 9b5346003d1..c3e0524fd46 100644 --- a/jdk/make/javax/sound/Makefile +++ b/jdk/make/javax/sound/Makefile @@ -53,18 +53,6 @@ include FILES_c.gmk # add java files AUTO_FILES_JAVA_DIRS = javax/sound com/sun/media/sound -# -# Specific to OpenJDK building -# -ifdef OPENJDK - -# copy closed .class files -build: import-binary-plug-sound-classes - -include $(BUILDDIR)/common/internal/BinaryPlugs.gmk - -endif # OPENJDK - # # Files that just need cp. # @@ -79,13 +67,11 @@ FILES_copy = \ $(SERVICEDIR)/javax.sound.sampled.spi.AudioFileReader \ $(SERVICEDIR)/javax.sound.sampled.spi.FormatConversionProvider \ $(SERVICEDIR)/javax.sound.sampled.spi.MixerProvider \ - $(LIBDIR)/audio/soundbank.gm \ $(LIBDIR)/sound.properties FILES_mkdirs = \ $(CLASSBINDIR)/META-INF \ - $(CLASSBINDIR)/META-INF/services \ - $(LIBDIR)/audio + $(CLASSBINDIR)/META-INF/services FILES_copydirs = \ $(CLASSBINDIR) \ @@ -95,11 +81,6 @@ FILES_copydirs = \ FILES_c += $(FILES_$(PLATFORM)) -# -# add "closed" library -# -SUBDIRS += jsoundhs - # # system dependent flags # diff --git a/jdk/make/javax/sound/jsoundhs/FILES.gmk b/jdk/make/javax/sound/jsoundhs/FILES.gmk deleted file mode 100644 index 6bc7a57da83..00000000000 --- a/jdk/make/javax/sound/jsoundhs/FILES.gmk +++ /dev/null @@ -1,91 +0,0 @@ -# -# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -FILES_c = \ - Utilities.c \ - MixerThread.c \ - HeadspaceMixer.c \ - MixerClip.c \ - MixerSourceLine.c \ - SimpleInputDevice.c \ - SimpleInputDeviceProvider.c \ - HeadspaceSoundbank.c \ - MixerMidiChannel.c \ - AbstractPlayer.c \ - MixerSequencer.c \ - MixerSynth.c - -FILES_engine = \ - DriverTools.c \ - GenAudioCaptureStreams.c \ - GenAudioStreams.c \ - GenOutput.c \ - GenPatch.c \ - GenReverb.c \ - GenSample.c \ - GenSeq.c \ - GenSetup.c \ - GenSong.c \ - GenSynth.c \ - GenSynthFilters.c \ - GenSynthInterp2.c \ - GenSynthResample.c \ - NewNewLZSS.c \ - SampleTools.c \ - SMOD_Volume_Scaler.c \ - X_API.c \ - X_Decompress.c \ - X_IMA.c \ - GenFiltersReverb.c \ - GenInterp2Reverb.c \ - GenSoundFiles.c \ - SincResample.c - -FILES_solaris = \ - HAE_API_SolarisOS.c \ - HAE_API_SolarisOS_Capture.c - -FILES_linux = \ - HAE_API_LinuxOS.c \ - HAE_API_LinuxOS_Capture.c - -FILES_windows = \ - HAE_API_WinOS.c \ - HAE_API_WinOS_Capture.c \ - HAE_API_WinOS_Synth.c - -FILES_export = \ - com/sun/media/sound/AbstractPlayer.java \ - com/sun/media/sound/HeadspaceMixer.java \ - com/sun/media/sound/HeadspaceSoundbank.java \ - com/sun/media/sound/MixerClip.java \ - com/sun/media/sound/MixerMidiChannel.java \ - com/sun/media/sound/MixerSequencer.java \ - com/sun/media/sound/MixerSourceLine.java \ - com/sun/media/sound/MixerSynth.java \ - com/sun/media/sound/MixerThread.java \ - com/sun/media/sound/SimpleInputDevice.java \ - com/sun/media/sound/SimpleInputDeviceProvider.java - diff --git a/jdk/make/javax/sound/jsoundhs/Makefile b/jdk/make/javax/sound/jsoundhs/Makefile deleted file mode 100644 index 6a4952c6522..00000000000 --- a/jdk/make/javax/sound/jsoundhs/Makefile +++ /dev/null @@ -1,100 +0,0 @@ -# -# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -BUILDDIR = ../../.. -PACKAGE = javax.sound -LIBRARY = jsoundhs -PRODUCT = sun -CPLUSPLUSLIBRARY = true -include $(BUILDDIR)/common/Defs.gmk - -# this Makefile compiles "closed" JavaSound library - -ifdef OPENJDK - -# precompiled lib will be copied by the rules in Library.gmk instead of compiling. -USE_BINARY_PLUG_LIBRARY=true - -build: import-binary-plug-jsound-library - -include $(BUILDDIR)/common/internal/BinaryPlugs.gmk - -else # OPENJDK - -# include defines for sound -include ../SoundDefs.gmk - -# -# Add use of mapfile -# -FILES_m = mapfile-vers -include $(BUILDDIR)/common/Mapfile-vers.gmk - -# -# Files -# -include FILES.gmk - -FILES_c += $(FILES_engine) $(FILES_$(PLATFORM)) - -# -# Extra cc/linker flags. -# -# flags needed for all platforms -CPPFLAGS += \ - -DJAVA_SOUND -DJAVA_THREAD \ - -I$(CLOSED_SHARE_SRC)/native/com/sun/media/sound \ - -I$(CLOSED_SHARE_SRC)/native/com/sun/media/sound/engine - -# system dependent flags -ifeq ($(PLATFORM), windows) - CPPFLAGS += -DUSE_DIRECTSOUND=0 \ - -DUSE_EXTERNAL_SYNTH=TRUE - LDLIBS += winmm.lib -endif # PLATFORM windows - -ifeq ($(PLATFORM), linux) -endif # PLATFORM linux - -ifeq ($(PLATFORM), solaris) -endif # PLATFORM solaris - - -# -# Add to the ambient VPATH. -# -vpath %.c $(CLOSED_SHARE_SRC)/native/com/sun/media/sound -vpath %.c $(CLOSED_SHARE_SRC)/native/com/sun/media/sound/engine -vpath %.c $(CLOSED_PLATFORM_SRC)/native/com/sun/media/sound/engine - - -endif # OPENJDK - - -# -# Include rules -# -include $(BUILDDIR)/common/Library.gmk - diff --git a/jdk/make/javax/sound/jsoundhs/mapfile-vers b/jdk/make/javax/sound/jsoundhs/mapfile-vers deleted file mode 100644 index 7961825600c..00000000000 --- a/jdk/make/javax/sound/jsoundhs/mapfile-vers +++ /dev/null @@ -1,153 +0,0 @@ -# -# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Sun designates this -# particular file as subject to the "Classpath" exception as provided -# by Sun in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, -# CA 95054 USA or visit www.sun.com if you need additional information or -# have any questions. -# - -# Define library interface. - -SUNWprivate_1.1 { - global: - Java_com_sun_media_sound_AbstractPlayer_nAddReceiver; - Java_com_sun_media_sound_AbstractPlayer_nClose; - Java_com_sun_media_sound_AbstractPlayer_nLoadInstrument; - Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument; - Java_com_sun_media_sound_AbstractPlayer_nRemoveReceiver; - Java_com_sun_media_sound_AbstractPlayer_nUnloadInstrument; - Java_com_sun_media_sound_HeadspaceMixer_nAllocateVoices; - Java_com_sun_media_sound_HeadspaceMixer_nCloseMixer; - Java_com_sun_media_sound_HeadspaceMixer_nCreateLinkedStreams; - Java_com_sun_media_sound_HeadspaceMixer_nDrain; - Java_com_sun_media_sound_HeadspaceMixer_nFlush; - Java_com_sun_media_sound_HeadspaceMixer_nGetCpuLoad; - Java_com_sun_media_sound_HeadspaceMixer_nGetDefaultBufferSize; - Java_com_sun_media_sound_HeadspaceMixer_nGetLevel; - Java_com_sun_media_sound_HeadspaceMixer_nGetPosition; - Java_com_sun_media_sound_HeadspaceMixer_nGetTotalVoices; - Java_com_sun_media_sound_HeadspaceMixer_nOpenMixer; - Java_com_sun_media_sound_HeadspaceMixer_nPause; - Java_com_sun_media_sound_HeadspaceMixer_nResume; - Java_com_sun_media_sound_HeadspaceMixer_nSetInterpolation; - Java_com_sun_media_sound_HeadspaceMixer_nSetMixerFormat; - Java_com_sun_media_sound_HeadspaceMixer_nSetMixLevel; - Java_com_sun_media_sound_HeadspaceMixer_nSetReverb; - Java_com_sun_media_sound_HeadspaceMixer_nStartLinkedStreams; - Java_com_sun_media_sound_HeadspaceMixer_nStopLinkedStreams; - Java_com_sun_media_sound_HeadspaceSoundbank_nCloseResource; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetInstruments; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetName; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetSamples; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetVersionMajor; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetVersionMinor; - Java_com_sun_media_sound_HeadspaceSoundbank_nGetVersionSubMinor; - Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResource; - Java_com_sun_media_sound_HeadspaceSoundbank_nOpenResourceFromByteArray; - Java_com_sun_media_sound_MixerClip_nClose; - Java_com_sun_media_sound_MixerClip_nDrain; - Java_com_sun_media_sound_MixerClip_nFlush; - Java_com_sun_media_sound_MixerClip_nGetPosition; - Java_com_sun_media_sound_MixerClip_nOpen; - Java_com_sun_media_sound_MixerClip_nSetLinearGain; - Java_com_sun_media_sound_MixerClip_nSetPan; - Java_com_sun_media_sound_MixerClip_nSetSampleRate; - Java_com_sun_media_sound_MixerClip_nSetup; - Java_com_sun_media_sound_MixerClip_nStart; - Java_com_sun_media_sound_MixerClip_nStop; - Java_com_sun_media_sound_MixerMidiChannel_nAllNotesOff; - Java_com_sun_media_sound_MixerMidiChannel_nControlChange; - Java_com_sun_media_sound_MixerMidiChannel_nGetController; - Java_com_sun_media_sound_MixerMidiChannel_nGetPitchBend; - Java_com_sun_media_sound_MixerMidiChannel_nGetSolo; - Java_com_sun_media_sound_MixerMidiChannel_nNoteOff; - Java_com_sun_media_sound_MixerMidiChannel_nNoteOn; - Java_com_sun_media_sound_MixerMidiChannel_nProgramChange__JIIIJ; - Java_com_sun_media_sound_MixerMidiChannel_nProgramChange__JIIJ; - Java_com_sun_media_sound_MixerMidiChannel_nResetAllControllers; - Java_com_sun_media_sound_MixerMidiChannel_nSetMute; - Java_com_sun_media_sound_MixerMidiChannel_nSetPitchBend; - Java_com_sun_media_sound_MixerMidiChannel_nSetSolo; - Java_com_sun_media_sound_MixerSequencer_nAddControllerEventCallback; - Java_com_sun_media_sound_MixerSequencer_nGetMasterTempo; - Java_com_sun_media_sound_MixerSequencer_nGetSequenceMicrosecondLength; - Java_com_sun_media_sound_MixerSequencer_nGetSequencerMicrosecondPosition; - Java_com_sun_media_sound_MixerSequencer_nGetSequencerTickPosition; - Java_com_sun_media_sound_MixerSequencer_nGetSequenceTickLength; - Java_com_sun_media_sound_MixerSequencer_nGetTempoInBPM; - Java_com_sun_media_sound_MixerSequencer_nGetTempoInMPQ; - Java_com_sun_media_sound_MixerSequencer_nGetTrackMute; - Java_com_sun_media_sound_MixerSequencer_nGetTrackSolo; - Java_com_sun_media_sound_MixerSequencer_nOpenMidiSequencer; - Java_com_sun_media_sound_MixerSequencer_nOpenRmfSequencer; - Java_com_sun_media_sound_MixerSequencer_nPauseSequencer; - Java_com_sun_media_sound_MixerSequencer_nResumeSequencer; - Java_com_sun_media_sound_MixerSequencer_nSetMasterTempo; - Java_com_sun_media_sound_MixerSequencer_nSetSequencerMicrosecondPosition; - Java_com_sun_media_sound_MixerSequencer_nSetSequencerTickPosition; - Java_com_sun_media_sound_MixerSequencer_nSetTempoInBPM; - Java_com_sun_media_sound_MixerSequencer_nSetTempoInMPQ; - Java_com_sun_media_sound_MixerSequencer_nSetTrackMute; - Java_com_sun_media_sound_MixerSequencer_nSetTrackSolo; - Java_com_sun_media_sound_MixerSequencer_nStartSequencer; - Java_com_sun_media_sound_MixerSourceLine_nClose; - Java_com_sun_media_sound_MixerSourceLine_nDrain; - Java_com_sun_media_sound_MixerSourceLine_nFlush; - Java_com_sun_media_sound_MixerSourceLine_nGetLevel; - Java_com_sun_media_sound_MixerSourceLine_nGetPosition; - Java_com_sun_media_sound_MixerSourceLine_nOpen; - Java_com_sun_media_sound_MixerSourceLine_nPause; - Java_com_sun_media_sound_MixerSourceLine_nResume; - Java_com_sun_media_sound_MixerSourceLine_nSetLinearGain; - Java_com_sun_media_sound_MixerSourceLine_nSetPan; - Java_com_sun_media_sound_MixerSourceLine_nSetSampleRate; - Java_com_sun_media_sound_MixerSourceLine_nStart; - Java_com_sun_media_sound_MixerSynth_nCreateSynthesizer; - Java_com_sun_media_sound_MixerSynth_nDestroySynthesizer; - Java_com_sun_media_sound_MixerSynth_nGetLatency; - Java_com_sun_media_sound_MixerSynth_nLoadInstrument; - Java_com_sun_media_sound_MixerSynth_nRemapInstrument; - Java_com_sun_media_sound_MixerSynth_nStartSynthesizer; - Java_com_sun_media_sound_MixerSynth_nUnloadInstrument; - Java_com_sun_media_sound_MixerThread_runNative; - Java_com_sun_media_sound_SimpleInputDevice_nClose; - Java_com_sun_media_sound_SimpleInputDevice_nDrain; - Java_com_sun_media_sound_SimpleInputDevice_nFlush; - Java_com_sun_media_sound_SimpleInputDevice_nGetBufferSizeInFrames; - Java_com_sun_media_sound_SimpleInputDevice_nGetFormats; - Java_com_sun_media_sound_SimpleInputDevice_nGetNumPorts; - Java_com_sun_media_sound_SimpleInputDevice_nGetPortName; - Java_com_sun_media_sound_SimpleInputDevice_nGetPosition; - Java_com_sun_media_sound_SimpleInputDevice_nOpen; - Java_com_sun_media_sound_SimpleInputDevice_nPause; - Java_com_sun_media_sound_SimpleInputDevice_nResume; - Java_com_sun_media_sound_SimpleInputDevice_nStart; - Java_com_sun_media_sound_SimpleInputDevice_nStop; - Java_com_sun_media_sound_SimpleInputDevice_nSupportsChannels; - Java_com_sun_media_sound_SimpleInputDevice_nSupportsSampleRate; - Java_com_sun_media_sound_SimpleInputDevice_nSupportsSampleSizeInBits; - Java_com_sun_media_sound_SimpleInputDeviceProvider_nGetDescription; - Java_com_sun_media_sound_SimpleInputDeviceProvider_nGetName; - Java_com_sun_media_sound_SimpleInputDeviceProvider_nGetNumDevices; - Java_com_sun_media_sound_SimpleInputDeviceProvider_nGetVendor; - Java_com_sun_media_sound_SimpleInputDeviceProvider_nGetVersion; - local: - *; -}; diff --git a/jdk/make/mksample/nio/Makefile b/jdk/make/mksample/nio/Makefile index e05106293bb..5fcfd03a783 100644 --- a/jdk/make/mksample/nio/Makefile +++ b/jdk/make/mksample/nio/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2004-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ BUILDDIR = ../.. PRODUCT = java include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = multicast server +SUBDIRS = file multicast server all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/nio/file/Makefile b/jdk/make/mksample/nio/file/Makefile new file mode 100644 index 00000000000..f7159de83a3 --- /dev/null +++ b/jdk/make/mksample/nio/file/Makefile @@ -0,0 +1,56 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for the nio/file sample code +# + +BUILDDIR = ../../.. + +PRODUCT = java + +include $(BUILDDIR)/common/Defs.gmk + +SAMPLE_SRC_DIR = $(SHARE_SRC)/sample/nio/file +SAMPLE_DST_DIR = $(SAMPLEDIR)/nio/file + +SAMPLE_FILES = \ + $(SAMPLE_DST_DIR)/AclEdit.java \ + $(SAMPLE_DST_DIR)/Chmod.java \ + $(SAMPLE_DST_DIR)/Copy.java \ + $(SAMPLE_DST_DIR)/DiskUsage.java \ + $(SAMPLE_DST_DIR)/FileType.java \ + $(SAMPLE_DST_DIR)/WatchDir.java \ + $(SAMPLE_DST_DIR)/Xdd.java + +all build: $(SAMPLE_FILES) + +$(SAMPLE_DST_DIR)/%: $(SAMPLE_SRC_DIR)/% + $(install-file) + +clean clobber: + $(RM) -r $(SAMPLE_DST_DIR) + +.PHONY: all build clean clobber diff --git a/jdk/make/sun/awt/FILES_c_windows.gmk b/jdk/make/sun/awt/FILES_c_windows.gmk index 1bd3d485366..1a9b3b6ad3c 100644 --- a/jdk/make/sun/awt/FILES_c_windows.gmk +++ b/jdk/make/sun/awt/FILES_c_windows.gmk @@ -153,7 +153,6 @@ FILES_cpp = \ awt_Menu.cpp \ awt_MenuBar.cpp \ awt_MenuItem.cpp \ - awt_MMStub.cpp \ awt_MouseEvent.cpp \ awt_Object.cpp \ awt_Palette.cpp \ @@ -171,7 +170,6 @@ FILES_cpp = \ awt_TextComponent.cpp \ awt_TextField.cpp \ awt_Toolkit.cpp \ - awt_Unicode.cpp \ awt_Window.cpp \ awt_Win32GraphicsEnv.cpp \ awt_Win32GraphicsDevice.cpp \ @@ -202,6 +200,4 @@ FILES_cpp = \ ThemeReader.cpp \ ComCtl32Util.cpp \ initIDs.cpp \ - awt_dlls.cpp \ - UnicowsLoader.cpp \ MouseInfo.cpp diff --git a/jdk/make/sun/awt/Makefile b/jdk/make/sun/awt/Makefile index 3f9fa64eb11..ef1be7354ac 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -47,7 +47,7 @@ OTHER_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES # sun/awt/resources handled by java/awt/Makefile # sun/java2d/pisces handled by sun/pisces/Makefile # -AUTO_FILES_JAVA_DIRS = sun/awt sun/java2d +AUTO_FILES_JAVA_DIRS = sun/awt sun/java2d com/sun/awt AUTO_JAVA_PRUNE = resources pisces ifeq ($(PLATFORM), windows) @@ -247,8 +247,14 @@ endif # PLATFORM ifeq ($(PLATFORM), windows) # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv WINDOWS OTHER_LDLIBS = kernel32.lib user32.lib gdi32.lib winspool.lib \ - imm32.lib ole32.lib uuid.lib $(JVMLIB) \ - shell32.lib + imm32.lib ole32.lib uuid.lib shell32.lib \ + comdlg32.lib winmm.lib comctl32.lib delayimp.lib \ + $(JVMLIB) \ + /DELAYLOAD:user32.dll /DELAYLOAD:gdi32.dll \ + /DELAYLOAD:shell32.dll /DELAYLOAD:winmm.dll \ + /DELAYLOAD:winspool.drv /DELAYLOAD:imm32.dll \ + /DELAYLOAD:ole32.dll /DELAYLOAD:comdlg32.dll \ + /DELAYLOAD:comctl32.dll clean:: awt.clean diff --git a/jdk/make/sun/awt/make.depend b/jdk/make/sun/awt/make.depend index a014b416426..650e4c7fde8 100644 --- a/jdk/make/sun/awt/make.depend +++ b/jdk/make/sun/awt/make.depend @@ -14,141 +14,135 @@ $(OBJDIR)/AnyInt.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/sha $(OBJDIR)/AnyShort.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/AnyShort.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/awt_AWTEvent.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_AWTEvent.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_BitmapUtil.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_BitmapUtil.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Brush.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Brush.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Button.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Button.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WButtonPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Button.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Button.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Button.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WButtonPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Button.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Canvas.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsConfig.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Canvas.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsConfig.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Checkbox.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Checkbox.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCheckboxPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Checkbox.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Checkbox.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Checkbox.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCheckboxPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Checkbox.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Choice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Choice.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WChoicePeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Choice.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Choice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Choice.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WChoicePeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Choice.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Clipboard.obj:: $(CLASSHDRDIR)/sun_awt_windows_WClipboard.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Clipboard.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Clipboard.obj:: $(CLASSHDRDIR)/sun_awt_windows_WClipboard.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Clipboard.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Color.obj:: $(CLASSHDRDIR)/sun_awt_windows_WColor.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Color.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Color.obj:: $(CLASSHDRDIR)/sun_awt_windows_WColor.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Color.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Component.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Color.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_MouseWheelEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_KeyboardFocusManager.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethod.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPanelPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/awt_InputTextInfor.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_MouseEvent.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Component.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Color.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_MouseWheelEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_KeyboardFocusManager.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethod.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPanelPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/awt_InputTextInfor.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MouseEvent.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Container.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Container.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Cursor.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Cursor.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCustomCursor.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WGlobalCursorManager.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Cursor.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Cursor.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WCustomCursor.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WGlobalCursorManager.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_DataTransferer.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_datatransfer_DataTransferer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDataTransferer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/common/locale_str.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_DataTransferer.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_datatransfer_DataTransferer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDataTransferer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/common/locale_str.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Debug.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Debug.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/awt_Desktop.obj:: ../../../src/share/javavm/export/jni.h ../../../src/windows/javavm/export/jni_md.h -$(OBJDIR)/awt_DesktopProperties.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDesktopProperties.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_DesktopProperties.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDesktopProperties.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Dialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Dialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Dimension.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Dimension.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_dlls.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_DnDDS.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_dnd_DnDConstants.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_dnd_SunDragSourceContextPeer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDragSourceContextPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_DnDDS.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_dnd_DnDConstants.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_dnd_SunDragSourceContextPeer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDragSourceContextPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_DnDDT.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_dnd_DnDConstants.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDropTargetContextPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_DnDDT.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_dnd_DnDConstants.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDropTargetContextPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_DataTransferer.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_DrawingSurface.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_DrawingSurface.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Event.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Event.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Event.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Event.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_FileDialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_FileDialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Font.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDefaultFontCharset.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFontPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Font.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDefaultFontCharset.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFontPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Frame.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/java_lang_Integer.h $(CLASSHDRDIR)/sun_awt_EmbeddedFrame.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WEmbeddedFrame.h $(CLASSHDRDIR)/sun_awt_windows_WEmbeddedFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Frame.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/java_lang_Integer.h $(CLASSHDRDIR)/sun_awt_EmbeddedFrame.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WEmbeddedFrame.h $(CLASSHDRDIR)/sun_awt_windows_WEmbeddedFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_GDIObject.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_GDIObject.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h - -$(OBJDIR)/awt_IconCursor.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_IconCursor.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/awt_ImageRep.obj:: $(CLASSHDRDIR)/sun_awt_image_ImageRepresentation.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/image/awt_parseImage.h ../../../src/share/native/sun/awt/image/imageInitIDs.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h $(OBJDIR)/awt_ImagingLib.obj:: $(CLASSHDRDIR)/java_awt_color_ColorSpace.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_image_BufferedImage.h $(CLASSHDRDIR)/java_awt_image_ConvolveOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_image_ImagingLib.h $(CLASSHDRDIR)/sun_awt_image_IntegerComponentRaster.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/image/awt_parseImage.h ../../../src/share/native/sun/awt/image/imageInitIDs.h ../../../src/share/native/sun/awt/medialib/awt_ImagingLib.h ../../../src/share/native/sun/awt/medialib/mlib_image_get.h ../../../src/share/native/sun/awt/medialib/mlib_image_types.h ../../../src/share/native/sun/awt/medialib/mlib_status.h ../../../src/share/native/sun/awt/medialib/mlib_types.h ../../../src/share/native/sun/awt/medialib/safe_alloc.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/awt_Mlib.h -$(OBJDIR)/awt_InputEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_InputEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_InputMethod.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethod.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethodDescriptor.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/common/locale_str.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_InputMethod.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethod.h $(CLASSHDRDIR)/sun_awt_windows_WInputMethodDescriptor.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/common/locale_str.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_InputTextInfor.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputTextInfor.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_InputTextInfor.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputTextInfor.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Insets.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Insets.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_KeyboardFocusManager.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_KeyboardFocusManager.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_KeyboardFocusManager.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_KeyboardFocusManager.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_KeyEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_KeyEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Label.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Label.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WLabelPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Label.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Label.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Label.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WLabelPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Label.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_List.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_List.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WListPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_List.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_List.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_List.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WListPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dimension.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_List.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Menu.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Menu.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_MenuBar.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_MenuBar.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_MenuItem.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_CheckboxMenuItem.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCheckboxMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_MenuItem.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_CheckboxMenuItem.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCheckboxMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/awt_Mlib.obj:: $(CLASSHDRDIR)/java_awt_image_BufferedImage.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/medialib/awt_ImagingLib.h ../../../src/share/native/sun/awt/medialib/mlib_image_get.h ../../../src/share/native/sun/awt/medialib/mlib_image_types.h ../../../src/share/native/sun/awt/medialib/mlib_status.h ../../../src/share/native/sun/awt/medialib/mlib_types.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt_Mlib.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_MMStub.obj:: ../../../src/windows/native/sun/windows/awt_MMStub.h +$(OBJDIR)/awt_MouseEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MouseEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_MouseEvent.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MouseEvent.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_new.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_new.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_new.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_new.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Object.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Object.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Palette.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_CustomPaletteDef.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/img_util_md.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Palette.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_CustomPaletteDef.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/img_util_md.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h - -$(OBJDIR)/awt_Panel.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Panel.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/awt_parseImage.obj:: $(CLASSHDRDIR)/java_awt_color_ColorSpace.h $(CLASSHDRDIR)/java_awt_image_BufferedImage.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_image_ImagingLib.h $(CLASSHDRDIR)/sun_awt_image_IntegerComponentRaster.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/image/awt_parseImage.h ../../../src/share/native/sun/awt/image/imageInitIDs.h ../../../src/share/native/sun/awt/medialib/awt_ImagingLib.h ../../../src/share/native/sun/awt/medialib/mlib_image_get.h ../../../src/share/native/sun/awt/medialib/mlib_image_types.h ../../../src/share/native/sun/awt/medialib/mlib_status.h ../../../src/share/native/sun/awt/medialib/mlib_types.h ../../../src/share/native/sun/awt/medialib/safe_alloc.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/awt_Mlib.h -$(OBJDIR)/awt_Pen.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Pen.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_PopupMenu.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_PopupMenu.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPopupMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Event.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PopupMenu.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_PopupMenu.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_PopupMenu.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPopupMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Event.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PopupMenu.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_PrintControl.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_PrintControl.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_PrintDialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPrintDialog.h $(CLASSHDRDIR)/sun_awt_windows_WPrintDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_PrintDialog.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPrintDialog.h $(CLASSHDRDIR)/sun_awt_windows_WPrintDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_PrintJob.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPrinterJob.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_PrintJob.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPrinterJob.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Rectangle.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Rectangle.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Rectangle.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Rectangle.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Robot.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WRobotPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Robot.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Robot.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WRobotPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Robot.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Scrollbar.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Scrollbar.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollbarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Scrollbar.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Scrollbar.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Scrollbar.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollbarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Scrollbar.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_ScrollPane.obj:: $(CLASSHDRDIR)/java_awt_Adjustable.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_AdjustmentEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_Scrollbar.h $(CLASSHDRDIR)/java_awt_ScrollPane.h $(CLASSHDRDIR)/java_awt_ScrollPaneAdjustable.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollbarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollPanePeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Scrollbar.h ../../../src/windows/native/sun/windows/awt_ScrollPane.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_ScrollPane.obj:: $(CLASSHDRDIR)/java_awt_Adjustable.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_AdjustmentEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_Scrollbar.h $(CLASSHDRDIR)/java_awt_ScrollPane.h $(CLASSHDRDIR)/java_awt_ScrollPaneAdjustable.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollbarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WScrollPanePeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Scrollbar.h ../../../src/windows/native/sun/windows/awt_ScrollPane.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_TextArea.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextArea.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextAreaPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextArea.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_TextArea.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextArea.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextAreaPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextArea.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_TextComponent.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_TextComponent.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_TextField.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_TextField.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextFieldPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_TextField.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_TextField.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_TextComponent.h $(CLASSHDRDIR)/java_awt_TextField.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WTextFieldPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_KeyboardFocusManager.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_TextComponent.h ../../../src/windows/native/sun/windows/awt_TextField.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Toolkit.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_List.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_ComponentPeer.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_PopupMenu.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WListPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPopupMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Clipboard.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/awt_List.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_new.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PopupMenu.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/CmdIDList.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Toolkit.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputMethodEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_List.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_ComponentPeer.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_PopupMenu.h $(CLASSHDRDIR)/java_awt_Toolkit.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WListPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WPopupMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Clipboard.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Cursor.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DesktopProperties.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_DnDDS.h ../../../src/windows/native/sun/windows/awt_DnDDT.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_InputEvent.h ../../../src/windows/native/sun/windows/awt_KeyEvent.h ../../../src/windows/native/sun/windows/awt_List.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_new.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PopupMenu.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/CmdIDList.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_TrayIcon.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_ActionEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_TrayIcon.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WTrayIconPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_TrayIcon.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_TrayIcon.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_ActionEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_InputEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_TrayIcon.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WTrayIconPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_AWTEvent.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_TrayIcon.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Unicode.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Win32GraphicsConfig.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_DataBuffer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsConfig.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsConfig.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Win32GraphicsConfig.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_DataBuffer.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsConfig.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsConfig.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Win32GraphicsDevice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_color_ColorSpace.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_image_DataBuffer.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsDevice.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/awt/image/dither.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/img_util_md.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Win32GraphicsDevice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_color_ColorSpace.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_image_DataBuffer.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsDevice.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/awt/image/dither.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/img_util_md.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Win32GraphicsEnv.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsEnvironment.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/awt_Win32GraphicsEnv.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_Win32GraphicsEnvironment.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h - -$(OBJDIR)/awt_Window.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Container.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_ComponentEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/awt_Window.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Container.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_ComponentEvent.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Insets.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Container.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_IconCursor.h ../../../src/windows/native/sun/windows/awt_Insets.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Panel.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/Blit.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_Blit.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -170,9 +164,9 @@ $(OBJDIR)/ByteGray.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/s $(OBJDIR)/ByteIndexed.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/AnyByte.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/Index12Gray.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbBm.h ../../../src/share/native/sun/java2d/loops/IntArgbPre.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/loops/ThreeByteBgr.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/CmdIDList.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/CmdIDList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/CmdIDList.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/CmdIDList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/ComCtl32Util.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/ComCtl32Util.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/ComCtl32Util.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/D3DBlitLoops.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DBlitLoops.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbPre.h ../../../src/share/native/sun/java2d/loops/IntBgr.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/Ushort555Rgb.h ../../../src/share/native/sun/java2d/loops/Ushort565Rgb.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DBlitLoops.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -182,7 +176,7 @@ $(OBJDIR)/D3DContext.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDI $(OBJDIR)/D3DGlyphCache.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DGlyphCache.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/D3DGraphicsDevice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DGraphicsDevice.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/D3DGraphicsDevice.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DGraphicsDevice.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/D3DMaskBlit.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskBlit.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -192,15 +186,15 @@ $(OBJDIR)/D3DMaskFill.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $( $(OBJDIR)/D3DPaints.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h $(CLASSHDRDIR)/sun_java2d_SunGraphics2D.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPaints.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/D3DPipelineManager.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DBadHardware.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/D3DPipelineManager.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DBadHardware.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/D3DRenderer.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DRenderer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedRenderPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/D3DRenderQueue.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DBlitLoops.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedOpCodes.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedRenderPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h $(CLASSHDRDIR)/sun_java2d_SunGraphics2D.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DBlitLoops.h ../../../src/windows/native/sun/java2d/d3d/D3DBufImgOps.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskBlit.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskFill.h ../../../src/windows/native/sun/java2d/d3d/D3DPaints.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/D3DRenderQueue.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DBlitLoops.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedOpCodes.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedRenderPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h $(CLASSHDRDIR)/sun_java2d_SunGraphics2D.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DBlitLoops.h ../../../src/windows/native/sun/java2d/d3d/D3DBufImgOps.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskBlit.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskFill.h ../../../src/windows/native/sun/java2d/d3d/D3DPaints.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/D3DResourceManager.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h $(CLASSHDRDIR)/sun_java2d_SunGraphics2D.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPaints.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/D3DResourceManager.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h $(CLASSHDRDIR)/sun_java2d_SunGraphics2D.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPaints.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/D3DSurfaceData.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/D3DSurfaceData.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_BitmapUtil.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/D3DTextRenderer.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DTextRenderer.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedTextPipe.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/sun/font/AccelGlyphCache.h ../../../src/share/native/sun/font/fontscalerdefs.h ../../../src/share/native/sun/font/sunfontids.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DGlyphCache.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DRenderQueue.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DTextRenderer.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -216,7 +210,7 @@ $(OBJDIR)/debug_trace.obj:: ../../../src/share/javavm/export/jni.h ../../../src/ $(OBJDIR)/debug_util.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h -$(OBJDIR)/Devices.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/Devices.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/java_awt_Transparency.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DContext.h $(CLASSHDRDIR)/sun_java2d_d3d_D3DSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelDeviceEventNotifier.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/ShaderList.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/d3d/D3DContext.h ../../../src/windows/native/sun/java2d/d3d/D3DMaskCache.h ../../../src/windows/native/sun/java2d/d3d/D3DPipeline.h ../../../src/windows/native/sun/java2d/d3d/D3DPipelineManager.h ../../../src/windows/native/sun/java2d/d3d/D3DResourceManager.h ../../../src/windows/native/sun/java2d/d3d/D3DSurfaceData.h ../../../src/windows/native/sun/java2d/d3d/D3DVertexCacher.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/Disposer.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h @@ -240,19 +234,19 @@ $(OBJDIR)/FourByteAbgr.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../s $(OBJDIR)/FourByteAbgrPre.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/Any4Byte.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/FourByteAbgrPre.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbBm.h ../../../src/share/native/sun/java2d/loops/IntArgbPre.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/loops/ThreeByteBgr.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/GDIBlitLoops.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIBlitLoops.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/GDIBlitLoops.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIBlitLoops.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/GDIHashtable.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/GDIHashtable.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/GDIRenderer.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_geom_PathIterator.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIRenderer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/GDIRenderer.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_geom_PathIterator.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIRenderer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/GDIWindowSurfaceData.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIWindowSurfaceData.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/GDIWindowSurfaceData.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_java2d_windows_GDIWindowSurfaceData.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/gifdecoder.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h $(OBJDIR)/GraphicsPrimitiveMgr.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_GraphicsPrimitiveMgr.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/Hashtable.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/Hashtable.obj:: $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/imageInitIDs.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/image/imageInitIDs.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h @@ -282,9 +276,9 @@ $(OBJDIR)/MaskBlit.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR) $(OBJDIR)/MaskFill.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/sun_java2d_loops_MaskFill.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/MouseInfo.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/MouseInfo.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/ObjectList.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/ObjectList.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/OGLBlitLoops.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/sun_java2d_opengl_OGLBlitLoops.h $(CLASSHDRDIR)/sun_java2d_opengl_OGLContext.h $(CLASSHDRDIR)/sun_java2d_opengl_OGLSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/opengl/J2D_GL/gl.h ../../../src/share/native/sun/java2d/opengl/J2D_GL/glext.h ../../../src/share/native/sun/java2d/opengl/OGLBlitLoops.h ../../../src/share/native/sun/java2d/opengl/OGLContext.h ../../../src/share/native/sun/java2d/opengl/OGLFuncMacros.h ../../../src/share/native/sun/java2d/opengl/OGLFuncs.h ../../../src/share/native/sun/java2d/opengl/OGLRenderQueue.h ../../../src/share/native/sun/java2d/opengl/OGLSurfaceData.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/opengl/J2D_GL/wglext.h ../../../src/windows/native/sun/java2d/opengl/OGLFuncs_md.h @@ -320,13 +314,13 @@ $(OBJDIR)/ScaledBlit.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDI $(OBJDIR)/ShapeSpanIterator.obj:: $(CLASSHDRDIR)/java_awt_geom_PathIterator.h $(CLASSHDRDIR)/sun_java2d_pipe_ShapeSpanIterator.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/pipe/PathConsumer2D.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/ShellFolder2.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/ShellFolder2.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/SpanClipRenderer.obj:: $(CLASSHDRDIR)/sun_java2d_pipe_RegionIterator.h $(CLASSHDRDIR)/sun_java2d_pipe_SpanClipRenderer.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h $(OBJDIR)/SurfaceData.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/Disposer.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h -$(OBJDIR)/ThemeReader.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_ThemeReader.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/ThemeReader.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_ThemeReader.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h $(OBJDIR)/ThreeByteBgr.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/Any3Byte.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbBm.h ../../../src/share/native/sun/java2d/loops/IntArgbPre.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/loops/ThreeByteBgr.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -334,8 +328,6 @@ $(OBJDIR)/Trace.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/ $(OBJDIR)/TransformHelper.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/sun_java2d_loops_TransformHelper.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/pipe/Region.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h -$(OBJDIR)/UnicowsLoader.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h - $(OBJDIR)/Ushort4444Argb.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/AnyShort.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbBm.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/loops/ThreeByteBgr.h ../../../src/share/native/sun/java2d/loops/Ushort4444Argb.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h $(OBJDIR)/Ushort555Rgb.obj:: $(CLASSHDRDIR)/java_awt_AlphaComposite.h ../../../src/share/javavm/export/jni.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/sun/java2d/loops/AlphaMacros.h ../../../src/share/native/sun/java2d/loops/AlphaMath.h ../../../src/share/native/sun/java2d/loops/AnyShort.h ../../../src/share/native/sun/java2d/loops/ByteGray.h ../../../src/share/native/sun/java2d/loops/ByteIndexed.h ../../../src/share/native/sun/java2d/loops/GlyphImageRef.h ../../../src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h ../../../src/share/native/sun/java2d/loops/IntArgb.h ../../../src/share/native/sun/java2d/loops/IntArgbBm.h ../../../src/share/native/sun/java2d/loops/IntArgbPre.h ../../../src/share/native/sun/java2d/loops/IntDcm.h ../../../src/share/native/sun/java2d/loops/IntRgb.h ../../../src/share/native/sun/java2d/loops/LineUtils.h ../../../src/share/native/sun/java2d/loops/LoopMacros.h ../../../src/share/native/sun/java2d/loops/ThreeByteBgr.h ../../../src/share/native/sun/java2d/loops/Ushort555Rgb.h ../../../src/share/native/sun/java2d/loops/UshortGray.h ../../../src/share/native/sun/java2d/pipe/SpanIterator.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/sun/java2d/j2d_md.h @@ -352,6 +344,6 @@ $(OBJDIR)/WGLGraphicsConfig.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformO $(OBJDIR)/WGLSurfaceData.obj:: $(CLASSHDRDIR)/java_awt_image_AffineTransformOp.h $(CLASSHDRDIR)/sun_java2d_opengl_OGLContext.h $(CLASSHDRDIR)/sun_java2d_opengl_OGLSurfaceData.h $(CLASSHDRDIR)/sun_java2d_opengl_WGLSurfaceData.h $(CLASSHDRDIR)/sun_java2d_pipe_BufferedContext.h $(CLASSHDRDIR)/sun_java2d_pipe_hw_AccelSurface.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/gdefs.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/opengl/J2D_GL/gl.h ../../../src/share/native/sun/java2d/opengl/J2D_GL/glext.h ../../../src/share/native/sun/java2d/opengl/OGLContext.h ../../../src/share/native/sun/java2d/opengl/OGLFuncMacros.h ../../../src/share/native/sun/java2d/opengl/OGLFuncs.h ../../../src/share/native/sun/java2d/opengl/OGLRenderQueue.h ../../../src/share/native/sun/java2d/opengl/OGLSurfaceData.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/gdefs_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/j2d_md.h ../../../src/windows/native/sun/java2d/opengl/J2D_GL/wglext.h ../../../src/windows/native/sun/java2d/opengl/OGLFuncs_md.h ../../../src/windows/native/sun/java2d/opengl/WGLGraphicsConfig.h ../../../src/windows/native/sun/java2d/opengl/WGLSurfaceData.h -$(OBJDIR)/WindowsFlags.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/WindowsFlags.obj:: ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/WindowsFlags.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/stdhdrs.h -$(OBJDIR)/WPrinterJob.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_dlls.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h ../../../src/windows/native/sun/windows/UnicowsLoader.h +$(OBJDIR)/WPrinterJob.obj:: $(CLASSHDRDIR)/java_awt_AWTEvent.h $(CLASSHDRDIR)/java_awt_Component.h $(CLASSHDRDIR)/java_awt_Dialog.h $(CLASSHDRDIR)/java_awt_Dimension.h $(CLASSHDRDIR)/java_awt_Event.h $(CLASSHDRDIR)/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/java_awt_FileDialog.h $(CLASSHDRDIR)/java_awt_Font.h $(CLASSHDRDIR)/java_awt_FontMetrics.h $(CLASSHDRDIR)/java_awt_Frame.h $(CLASSHDRDIR)/java_awt_Menu.h $(CLASSHDRDIR)/java_awt_MenuBar.h $(CLASSHDRDIR)/java_awt_MenuComponent.h $(CLASSHDRDIR)/java_awt_MenuItem.h $(CLASSHDRDIR)/java_awt_peer_MenuComponentPeer.h $(CLASSHDRDIR)/java_awt_Window.h $(CLASSHDRDIR)/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/sun_awt_PlatformFont.h $(CLASSHDRDIR)/sun_awt_windows_WCanvasPeer.h $(CLASSHDRDIR)/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/sun_awt_windows_WDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFileDialogPeer.h $(CLASSHDRDIR)/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/sun_awt_windows_WFramePeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuBarPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuItemPeer.h $(CLASSHDRDIR)/sun_awt_windows_WMenuPeer.h $(CLASSHDRDIR)/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/sun_awt_windows_WToolkit.h $(CLASSHDRDIR)/sun_awt_windows_WWindowPeer.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Canvas.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_Dialog.h ../../../src/windows/native/sun/windows/awt_FileDialog.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_Frame.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Menu.h ../../../src/windows/native/sun/windows/awt_MenuBar.h ../../../src/windows/native/sun/windows/awt_MenuItem.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_PrintControl.h ../../../src/windows/native/sun/windows/awt_PrintDialog.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awt_Window.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/stdhdrs.h diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION index 2f4f9df808f..2c19203a2c9 100644 --- a/jdk/make/sun/javazic/tzdata/VERSION +++ b/jdk/make/sun/javazic/tzdata/VERSION @@ -21,4 +21,4 @@ # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. # -tzdata2008e +tzdata2009a diff --git a/jdk/make/sun/javazic/tzdata/africa b/jdk/make/sun/javazic/tzdata/africa index 8141f080997..52289f12054 100644 --- a/jdk/make/sun/javazic/tzdata/africa +++ b/jdk/make/sun/javazic/tzdata/africa @@ -458,11 +458,36 @@ Zone Africa/Nouakchott -1:03:48 - LMT 1912 # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html # +# From Riad M. Hossen Ally (2008-08-03): +# The Government of Mauritius weblink +# +# http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=3D4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD +# +# Cabinet Decision of July 18th, 2008 states as follows: +# +# 4. ...Cabinet has agreed to the introduction into the National Assembly +# of the Time Bill which provides for the introduction of summer time in +# Mauritius. The summer time period which will be of one hour ahead of +# the standard time, will be aligned with that in Europe and the United +# States of America. It will start at two o'clock in the morning on the +# last Sunday of October and will end at two o'clock in the morning on +# the last Sunday of March the following year. The summer time for the +# year 2008 - 2009 will, therefore, be effective as from 26 October 2008 +# and end on 29 March 2009. + +# From Ed Maste (2008-10-07): +# THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the +# beginning / ending of summer time is 2 o'clock standard time in the +# morning of the last Sunday of October / last Sunday of March. +# +# http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Mauritius 1982 only - Oct 10 0:00 1:00 S Rule Mauritius 1983 only - Mar 21 0:00 0 - -Rule Mauritius 2008 only - Oct 26 2:00s 1:00 S -Rule Mauritius 2009 only - Mar 27 2:00s 0 - +Rule Mauritius 2008 max - Oct lastSun 2:00s 1:00 S +Rule Mauritius 2009 max - Mar lastSun 2:00s 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis 4:00 Mauritius MU%sT # Mauritius Time @@ -547,7 +572,22 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou # From Arthur David Olson (2008-05-09): # XXX--guess that it is only Morocco for now; guess only 2008 for now. +# From Steffen Thorsen (2008-08-27): +# Morocco will change the clocks back on the midnight between August 31 +# and September 1. They originally planned to observe DST to near the end +# of September: +# +# One article about it (in French): +# +# http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default +# +# +# We have some further details posted here: +# +# http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html +# # RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S + Rule Morocco 1939 only - Sep 12 0:00 1:00 S Rule Morocco 1939 only - Nov 19 0:00 0 - Rule Morocco 1940 only - Feb 25 0:00 1:00 S @@ -564,7 +604,7 @@ Rule Morocco 1977 only - Sep 28 0:00 0 - Rule Morocco 1978 only - Jun 1 0:00 1:00 S Rule Morocco 1978 only - Aug 4 0:00 0 - Rule Morocco 2008 only - Jun 1 0:00 1:00 S -Rule Morocco 2008 only - Sep 28 0:00 0 - +Rule Morocco 2008 only - Sep 1 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 0:00 Morocco WE%sT 1984 Mar 16 diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia index be581970001..b245bbf0653 100644 --- a/jdk/make/sun/javazic/tzdata/asia +++ b/jdk/make/sun/javazic/tzdata/asia @@ -1496,7 +1496,7 @@ Zone Asia/Choibalsan 7:38:00 - LMT 1905 Aug # Nepal # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Katmandu 5:41:16 - LMT 1920 +Zone Asia/Kathmandu 5:41:16 - LMT 1920 5:30 - IST 1986 5:45 - NPT # Nepal Time @@ -1563,11 +1563,24 @@ Zone Asia/Muscat 3:54:20 - LMT 1920 # From Arthur David Olson (2008-05-19): # XXX--midnight transitions is a guess; 2008 only is a guess. +# From Alexander Krivenyshev (2008-08-28): +# Pakistan government has decided to keep the watches one-hour advanced +# for another 2 months--plan to return to Standard Time on October 31 +# instead of August 31. +# +# +# http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html +# +# OR +# +# http://dailymailnews.com/200808/28/news/dmbrn03.html +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Pakistan 2002 only - Apr Sun>=2 0:01 1:00 S Rule Pakistan 2002 only - Oct Sun>=2 0:01 0 - Rule Pakistan 2008 only - Jun 1 0:00 1:00 S -Rule Pakistan 2008 only - Sep 1 0:00 0 - +Rule Pakistan 2008 only - Nov 1 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Karachi 4:28:12 - LMT 1907 5:30 - IST 1942 Sep @@ -1687,6 +1700,23 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # For lack of better information, predict that future changes will be # the 2nd Thursday of September at 02:00. +# From Alexander Krivenyshev (2008-08-28): +# Here is an article, that Mideast running on different clocks at Ramadan. +# +# Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while +# the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008). +# +# +# http://www.guardian.co.uk/world/feedarticle/7759001 +# +# +# http://www.abcnews.go.com/International/wireStory?id=5676087 +# +# or +# +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html +# + # The rules for Egypt are stolen from the `africa' file. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -1702,7 +1732,8 @@ Rule Palestine 2004 only - Oct 1 1:00 0 - Rule Palestine 2005 only - Oct 4 2:00 0 - Rule Palestine 2006 max - Apr 1 0:00 1:00 S Rule Palestine 2006 only - Sep 22 0:00 0 - -Rule Palestine 2007 max - Sep Thu>=8 2:00 0 - +Rule Palestine 2007 only - Sep Thu>=8 2:00 0 - +Rule Palestine 2008 max - Aug lastThu 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct @@ -1948,8 +1979,20 @@ Rule Syria 2007 only - Nov Fri>=1 0:00 0 - # compilers can't handle or having multiple Rules (a la Israel). # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end. +# From Steffen Thorsen (2008-10-07): +# Syria has now officially decided to end DST on 2008-11-01 this year, +# according to the following article in the Syrian Arab News Agency (SANA). +# +# The article is in Arabic, and seems to tell that they will go back to +# winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting +# clocks back 60 minutes). +# +# +# http://sana.sy/ara/2/2008/10/07/195459.htm +# + Rule Syria 2008 max - Apr Fri>=1 0:00 1:00 S -Rule Syria 2008 max - Oct 1 0:00 0 - +Rule Syria 2008 max - Nov 1 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq diff --git a/jdk/make/sun/javazic/tzdata/backward b/jdk/make/sun/javazic/tzdata/backward index 85522740f41..57bb988bc99 100644 --- a/jdk/make/sun/javazic/tzdata/backward +++ b/jdk/make/sun/javazic/tzdata/backward @@ -46,6 +46,7 @@ Link America/St_Thomas America/Virgin Link Asia/Ashgabat Asia/Ashkhabad Link Asia/Chongqing Asia/Chungking Link Asia/Dhaka Asia/Dacca +Link Asia/Kathmandu Asia/Katmandu Link Asia/Kolkata Asia/Calcutta Link Asia/Macau Asia/Macao Link Asia/Jerusalem Asia/Tel_Aviv diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe index 30724328383..a80f1bc9cff 100644 --- a/jdk/make/sun/javazic/tzdata/europe +++ b/jdk/make/sun/javazic/tzdata/europe @@ -2335,11 +2335,64 @@ Zone Europe/Stockholm 1:12:12 - LMT 1879 Jan 1 # mean time in preference to apparent time -- Geneva from 1780 .... # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S # From Whitman (who writes ``Midnight?''): -Rule Swiss 1940 only - Nov 2 0:00 1:00 S -Rule Swiss 1940 only - Dec 31 0:00 0 - +# Rule Swiss 1940 only - Nov 2 0:00 1:00 S +# Rule Swiss 1940 only - Dec 31 0:00 0 - # From Shanks & Pottenger: -Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S -Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 - +# Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S +# Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 - + +# From Alois Treindl (2008-12-17): +# I have researched the DST usage in Switzerland during the 1940ies. +# +# As I wrote in an earlier message, I suspected the current tzdata values +# to be wrong. This is now verified. +# +# I have found copies of the original ruling by the Swiss Federal +# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss +# federal law collection)... +# +# DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am +# DST ended on Monday 6 Oct 1941, 2:00 am by shifting the clocks to 1:00 am. +# +# DST began on Monday, 4 May 1942 at 01:00 am +# DST ended on Monday, 5 Oct 1942 at 02:00 am +# +# There was no DST in 1940, I have checked the law collection carefully. +# It is also indicated by the fact that the 1942 entry in the law +# collection points back to 1941 as a reference, but no reference to any +# other years are made. +# +# Newspaper articles I have read in the archives on 6 May 1941 reported +# about the introduction of DST (Sommerzeit in German) during the previous +# night as an absolute novelty, because this was the first time that such +# a thing had happened in Switzerland. +# +# I have also checked 1916, because one book source (Gabriel, Traite de +# l'heure dans le monde) claims that Switzerland had DST in 1916. This is +# false, no official document could be found. Probably Gabriel got misled +# by references to Germany, which introduced DST in 1916 for the first time. +# +# The tzdata rules for Switzerland must be changed to: +# Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S +# Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 - +# +# The 1940 rules must be deleted. +# +# One further detail for Switzerland, which is probably out of scope for +# most users of tzdata: +# The zone file +# Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 +# 0:29:44 - BMT 1894 Jun #Bern Mean Time +# 1:00 Swiss CE%sT 1981 +# 1:00 EU CE%sT +# describes all of Switzerland correctly, with the exception of +# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not +# follow Bern Mean Time but kept its own local mean time. +# To represent this, an extra zone would be needed. + +# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S +Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 0:29:44 - BMT 1894 Jun # Bern Mean Time @@ -2375,6 +2428,27 @@ Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 # (on a non-government server though) describing dates between 2002 and 2006: # http://www.alomaliye.com/bkk_2002_3769.htm +# From Sue Williams (2008-08-11): +# I spotted this news article about a potential change in Turkey. +# +# +# http://www.hurriyet.com.tr/english/domestic/9626174.asp?scr=1 +# + +# From Sue Williams (2008-08-20): +# This article says that around the end of March 2011, Turkey wants to +# adjust the clocks forward by 1/2 hour and stay that way permanently. +# The article indicates that this is a change in timezone offset in addition +# to stopping observance of DST. +# This proposal has not yet been approved. +# +# Read more here... +# +# Turkey to abandon daylight saving time in 2011 +# +# http://www.turkishdailynews.com.tr/article.php?enewsid=112989 +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Turkey 1916 only - May 1 0:00 1:00 S Rule Turkey 1916 only - Oct 1 0:00 0 - diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica index 6e0317277b7..1638f1fecbb 100644 --- a/jdk/make/sun/javazic/tzdata/northamerica +++ b/jdk/make/sun/javazic/tzdata/northamerica @@ -1764,9 +1764,13 @@ Zone America/Dawson_Creek -8:00:56 - LMT 1884 # The individual that answered the phone confirmed that the clocks did not # move at the end of daylight saving on October 29/2006. He also told me that # the clocks did not move this past weekend (March 11/2007).... -# -# America/Resolute should use the "Canada" Rule up to October 29/2006. -# After that it should be fixed on Eastern Standard Time until further notice. + +# From Chris Walton (2008-11-13): +# ...the residents of Resolute believe that they are changing "time zones" +# twice a year. In winter months, local time is qualified with "Eastern +# Time" which is really "Eastern Standard Time (UTC-5)". In summer +# months, local time is qualified with "Central Time" which is really +# "Central Daylight Time (UTC-5)"... # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule NT_YK 1918 only - Apr 14 2:00 1:00 D @@ -1794,11 +1798,14 @@ Zone America/Iqaluit 0 - zzz 1942 Aug # Frobisher Bay est. -6:00 Canada C%sT 2000 Oct 29 2:00 -5:00 Canada E%sT # aka Qausuittuq +# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +Rule Resolute 2006 max - Nov Sun>=1 2:00 0 ES +Rule Resolute 2007 max - Mar Sun>=8 2:00 0 CD Zone America/Resolute 0 - zzz 1947 Aug 31 # Resolute founded -6:00 NT_YK C%sT 2000 Oct 29 2:00 -5:00 - EST 2001 Apr 1 3:00 -6:00 Canada C%sT 2006 Oct 29 2:00 - -5:00 - EST + -5:00 Resolute %sT # aka Kangiqiniq Zone America/Rankin_Inlet 0 - zzz 1957 # Rankin Inlet founded -6:00 NT_YK C%sT 2000 Oct 29 2:00 @@ -2302,7 +2309,7 @@ Rule Cuba 1996 only - Oct 6 0:00s 0 S Rule Cuba 1997 only - Oct 12 0:00s 0 S Rule Cuba 1998 1999 - Mar lastSun 0:00s 1:00 D Rule Cuba 1998 2003 - Oct lastSun 0:00s 0 S -Rule Cuba 2000 2006 - Apr Sun>=1 0:00s 1:00 D +Rule Cuba 2000 2004 - Apr Sun>=1 0:00s 1:00 D Rule Cuba 2006 max - Oct lastSun 0:00s 0 S Rule Cuba 2007 only - Mar Sun>=8 0:00s 1:00 D Rule Cuba 2008 max - Mar Sun>=15 0:00s 1:00 D diff --git a/jdk/make/sun/javazic/tzdata/southamerica b/jdk/make/sun/javazic/tzdata/southamerica index 06a8d130e39..6c82a557a70 100644 --- a/jdk/make/sun/javazic/tzdata/southamerica +++ b/jdk/make/sun/javazic/tzdata/southamerica @@ -186,9 +186,58 @@ Rule Arg 2000 only - Mar 3 0:00 0 - # From Paul Eggert (2007-12-22): # For dates after mid-2008, the following rules are my guesses and # are quite possibly wrong, but are more likely than no DST at all. + +# From Alexander Krivenyshev (2008-09-05): +# As per message from Carlos Alberto Fonseca Arauz (Nicaragua), +# Argentina will start DST on Sunday October 19, 2008. +# +# +# http://www.worldtimezone.com/dst_news/dst_news_argentina03.html +# +# OR +# +# http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish) +# + +# From Rodrigo Severo (2008-10-06): +# Here is some info available at a Gentoo bug related to TZ on Argentina's DST: +# ... +# ------- Comment #1 from [jmdocile] 2008-10-06 16:28 0000 ------- +# Hi, there is a problem with timezone-data-2008e and maybe with +# timezone-data-2008f +# Argentinian law [Number] 25.155 is no longer valid. +# +# http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm +# +# The new one is law [Number] 26.350 +# +# http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm +# +# So there is no summer time in Argentina for now. + +# From Mariano Absatz (2008-10-20): +# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina +# From 2008-10-19 until 2009-03-15 +# +# http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01 +# +# +# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009: +# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz +# and Tierra del Fuego +# +# http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01 +# +# +# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying +# it will not apply DST either (even when it was not included in Decree 1705/2008) +# +# http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc +# + Rule Arg 2007 only - Dec 30 0:00 1:00 S Rule Arg 2008 max - Mar Sun>=15 0:00 0 - -Rule Arg 2008 max - Oct Sun>=1 0:00 1:00 S +Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S # From Mariano Absatz (2004-05-21): # Today it was officially published that the Province of Mendoza is changing @@ -336,9 +385,8 @@ Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 Arg AR%sT # -# Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN), Chaco (CC), -# Formosa (FM), Salta (SA), Santiago del Estero (SE), Cordoba (CB), -# La Pampa (LP), Neuquen (NQ), Rio Negro (RN) +# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN), +# Chaco (CC), Formosa (FM), Santiago del Estero (SE) # # Shanks & Pottenger also make the following claims, which we haven't verified: # - Formosa switched to -3:00 on 1991-01-07. @@ -357,6 +405,18 @@ Zone America/Argentina/Cordoba -4:16:48 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 Arg AR%sT # +# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN) +Zone America/Argentina/Salta -4:21:40 - LMT 1894 Oct 31 + -4:16:48 - CMT 1920 May + -4:00 - ART 1930 Dec + -4:00 Arg AR%sT 1969 Oct 5 + -3:00 Arg AR%sT 1991 Mar 3 + -4:00 - WART 1991 Oct 20 + -3:00 Arg AR%sT 1999 Oct 3 + -4:00 Arg AR%sT 2000 Mar 3 + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART +# # Tucuman (TM) Zone America/Argentina/Tucuman -4:20:52 - LMT 1894 Oct 31 -4:16:48 - CMT 1920 May @@ -381,7 +441,8 @@ Zone America/Argentina/La_Rioja -4:27:24 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 Jun 1 -4:00 - WART 2004 Jun 20 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # San Juan (SJ) Zone America/Argentina/San_Juan -4:34:04 - LMT 1894 Oct 31 @@ -394,7 +455,8 @@ Zone America/Argentina/San_Juan -4:34:04 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 May 31 -4:00 - WART 2004 Jul 25 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # Jujuy (JY) Zone America/Argentina/Jujuy -4:21:12 - LMT 1894 Oct 31 @@ -408,7 +470,8 @@ Zone America/Argentina/Jujuy -4:21:12 - LMT 1894 Oct 31 -3:00 1:00 ARST 1992 -3:00 Arg AR%sT 1999 Oct 3 -4:00 Arg AR%sT 2000 Mar 3 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # Catamarca (CT), Chubut (CH) Zone America/Argentina/Catamarca -4:23:08 - LMT 1894 Oct 31 @@ -421,7 +484,8 @@ Zone America/Argentina/Catamarca -4:23:08 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 Jun 1 -4:00 - WART 2004 Jun 20 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # Mendoza (MZ) Zone America/Argentina/Mendoza -4:35:16 - LMT 1894 Oct 31 @@ -438,7 +502,8 @@ Zone America/Argentina/Mendoza -4:35:16 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 May 23 -4:00 - WART 2004 Sep 26 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # San Luis (SL) Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31 @@ -466,7 +531,8 @@ Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 Jun 1 -4:00 - WART 2004 Jun 20 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # # Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF) Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31 @@ -477,7 +543,8 @@ Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31 -4:00 Arg AR%sT 2000 Mar 3 -3:00 - ART 2004 May 30 -4:00 - WART 2004 Jun 20 - -3:00 Arg AR%sT + -3:00 Arg AR%sT 2008 Oct 18 + -3:00 - ART # Aruba # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -613,6 +680,36 @@ Zone America/La_Paz -4:32:36 - LMT 1890 # Decretos sobre o Horario de Verao no Brasil # . +# From Steffen Thorsen (2008-08-29): +# As announced by the government and many newspapers in Brazil late +# yesterday, Brazil will start DST on 2008-10-19 (need to change rule) and +# it will end on 2009-02-15 (current rule for Brazil is fine). Based on +# past years experience with the elections, there was a good chance that +# the start was postponed to November, but it did not happen this year. +# +# It has not yet been posted to http://pcdsh01.on.br/DecHV.html +# +# An official page about it: +# +# http://www.mme.gov.br/site/news/detail.do?newsId=16722 +# +# Note that this link does not always work directly, but must be accessed +# by going to +# +# http://www.mme.gov.br/first +# +# +# One example link that works directly: +# +# http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54 +# (Portuguese) +# +# +# We have a written a short article about it as well: +# +# http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S # Decree 20,466 (1931-10-01) # Decree 21,896 (1932-01-10) @@ -746,12 +843,34 @@ Rule Brazil 2006 only - Nov 5 0:00 1:00 S Rule Brazil 2007 only - Feb 25 0:00 0 - # Decree 6,212 (2007-09-26), # adopted by the same states as before. -Rule Brazil 2007 max - Oct Sun>=8 0:00 1:00 S -Rule Brazil 2008 max - Feb Sun>=15 0:00 0 - +Rule Brazil 2007 only - Oct Sun>=8 0:00 1:00 S +# From Frederico A. C. Neves (2008-09-10): +# Acording to this decree +# +# http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm +# +# [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the +# 3rd Feb Sunday. There is an exception on the return date when this is +# the Carnival Sunday then the return date will be the next Sunday... +Rule Brazil 2008 max - Oct Sun>=15 0:00 1:00 S +Rule Brazil 2008 2011 - Feb Sun>=15 0:00 0 - +Rule Brazil 2012 only - Feb Sun>=22 0:00 0 - +Rule Brazil 2013 2014 - Feb Sun>=15 0:00 0 - +Rule Brazil 2015 only - Feb Sun>=22 0:00 0 - +Rule Brazil 2016 2022 - Feb Sun>=15 0:00 0 - +Rule Brazil 2023 only - Feb Sun>=22 0:00 0 - +Rule Brazil 2024 2025 - Feb Sun>=15 0:00 0 - +Rule Brazil 2026 only - Feb Sun>=22 0:00 0 - +Rule Brazil 2027 2033 - Feb Sun>=15 0:00 0 - +Rule Brazil 2034 only - Feb Sun>=22 0:00 0 - +Rule Brazil 2035 2036 - Feb Sun>=15 0:00 0 - +Rule Brazil 2037 only - Feb Sun>=22 0:00 0 - +# From Arthur David Olson (2008-09-29): +# The next is wrong in some years but is better than nothing. +Rule Brazil 2038 max - Feb Sun>=15 0:00 0 - + # The latest ruleset listed above says that the following states observe DST: # DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP. -# For dates after mid-2008, the above rules with TO="max" are guesses -# and are quite possibly wrong, but are more likely than no DST at all. # Zone NAME GMTOFF RULES FORMAT [UNTIL] # diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab index a9c686227ec..467367e2d72 100644 --- a/jdk/make/sun/javazic/tzdata/zone.tab +++ b/jdk/make/sun/javazic/tzdata/zone.tab @@ -64,14 +64,15 @@ AQ -7824+10654 Antarctica/Vostok Vostok Station, S Magnetic Pole AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) -AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, LP, MN, NQ, RN, SA, SE, SF) -AR -3319-06621 America/Argentina/San_Luis San Luis (SL) +AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) +AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) AR -2649-06513 America/Argentina/Tucuman Tucuman (TM) AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) +AR -3319-06621 America/Argentina/San_Luis San Luis (SL) AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) AS -1416-17042 Pacific/Pago_Pago @@ -137,7 +138,7 @@ CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut -CA +744144-0944945 America/Resolute Eastern Time - Resolute, Nunavut +CA +744144-0944945 America/Resolute Eastern Standard Time - Resolute, Nunavut CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario @@ -313,9 +314,9 @@ NG +0627+00324 Africa/Lagos NI +1209-08617 America/Managua NL +5222+00454 Europe/Amsterdam NO +5955+01045 Europe/Oslo -NP +2743+08519 Asia/Katmandu +NP +2743+08519 Asia/Kathmandu NR -0031+16655 Pacific/Nauru -NU -1901+16955 Pacific/Niue +NU -1901-16955 Pacific/Niue NZ -3652+17446 Pacific/Auckland most locations NZ -4357-17633 Pacific/Chatham Chatham Islands OM +2336+05835 Asia/Muscat @@ -406,13 +407,13 @@ US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisvi US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties -US +411745-0863730 America/Indiana/Knox Eastern Time - Indiana - Starke County US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County +US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County US +415100-0873900 America/Chicago Central Time US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County -US +382931-0871643 America/Indiana/Petersburg Central Time - Indiana - Pike County +US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) diff --git a/jdk/make/sun/jawt/make.depend b/jdk/make/sun/jawt/make.depend index 47792f71696..2eefe099c35 100644 --- a/jdk/make/sun/jawt/make.depend +++ b/jdk/make/sun/jawt/make.depend @@ -1 +1 @@ -$(OBJDIR)/jawt.obj:: $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_AWTEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Component.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Dimension.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Event.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Font.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_PlatformFont.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/UnicowsLoader.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_MMStub.h ../../../src/windows/native/sun/windows/awt_Multimon.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Unicode.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/stdhdrs.h +$(OBJDIR)/jawt.obj:: $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_AWTEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Component.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Dimension.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Event.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_Font.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_FocusEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_KeyEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_MouseEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/java_awt_event_WindowEvent.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_FontDescriptor.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_PlatformFont.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WComponentPeer.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WFontMetrics.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WObjectPeer.h $(CLASSHDRDIR)/../../awt/CClassHeaders/sun_awt_windows_WToolkit.h ../../../src/share/javavm/export/jawt.h ../../../src/share/javavm/export/jni.h ../../../src/share/javavm/export/jvm.h ../../../src/share/native/common/jlong.h ../../../src/share/native/common/jni_util.h ../../../src/share/native/sun/awt/debug/debug_assert.h ../../../src/share/native/sun/awt/debug/debug_mem.h ../../../src/share/native/sun/awt/debug/debug_trace.h ../../../src/share/native/sun/awt/debug/debug_util.h ../../../src/share/native/sun/awt/image/cvutils/img_globals.h ../../../src/share/native/sun/java2d/SurfaceData.h ../../../src/share/native/sun/java2d/Trace.h ../../../src/windows/javavm/export/jawt_md.h ../../../src/windows/javavm/export/jni_md.h ../../../src/windows/javavm/export/jvm_md.h ../../../src/windows/native/common/jlong_md.h ../../../src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.h ../../../src/windows/native/sun/windows/Devices.h ../../../src/windows/native/sun/windows/GDIHashtable.h ../../../src/windows/native/sun/windows/Hashtable.h ../../../src/windows/native/sun/windows/ObjectList.h ../../../src/windows/native/sun/windows/alloc.h ../../../src/windows/native/sun/windows/awt.h ../../../src/windows/native/sun/windows/awt_Brush.h ../../../src/windows/native/sun/windows/awt_Component.h ../../../src/windows/native/sun/windows/awt_Debug.h ../../../src/windows/native/sun/windows/awt_DrawingSurface.h ../../../src/windows/native/sun/windows/awt_Font.h ../../../src/windows/native/sun/windows/awt_GDIObject.h ../../../src/windows/native/sun/windows/awt_Object.h ../../../src/windows/native/sun/windows/awt_Palette.h ../../../src/windows/native/sun/windows/awt_Pen.h ../../../src/windows/native/sun/windows/awt_Toolkit.h ../../../src/windows/native/sun/windows/awt_Win32GraphicsDevice.h ../../../src/windows/native/sun/windows/awtmsg.h ../../../src/windows/native/sun/windows/colordata.h ../../../src/windows/native/sun/windows/stdhdrs.h diff --git a/jdk/make/sun/launcher/Makefile b/jdk/make/sun/launcher/Makefile index d9fba17bbbe..1346bc4e200 100644 --- a/jdk/make/sun/launcher/Makefile +++ b/jdk/make/sun/launcher/Makefile @@ -37,7 +37,7 @@ AUTO_FILES_JAVA_DIRS = sun/launcher # Resources # LOCALE_SET_DEFINITION = jre -NEW_RESOURCE_BUNDLES_PROPERTIES = $(PKGDIR)/resources/launcher.properties +NEW_RESOURCE_BUNDLES_COMPILED_PROPERTIES = $(PKGDIR)/resources/launcher.properties # # Rules diff --git a/jdk/make/sun/rmi/oldtools/Makefile b/jdk/make/sun/rmi/oldtools/Makefile index 1b5dfaaa8de..ad610ffca41 100644 --- a/jdk/make/sun/rmi/oldtools/Makefile +++ b/jdk/make/sun/rmi/oldtools/Makefile @@ -41,7 +41,7 @@ include FILES_java.gmk # Resources # LOCALE_SET_DEFINITION = j2sdk -RESOURCE_BUNDLES_PROPERTIES = sun/tools/javac/resources/javac.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = sun/tools/javac/resources/javac.properties # # Rules diff --git a/jdk/make/sun/rmi/registry/Makefile b/jdk/make/sun/rmi/registry/Makefile index 552131848d7..c5254a7f3c9 100644 --- a/jdk/make/sun/rmi/registry/Makefile +++ b/jdk/make/sun/rmi/registry/Makefile @@ -41,7 +41,7 @@ AUTO_FILES_JAVA_DIRS = sun/rmi/registry # Resources # LOCALE_SET_DEFINITION = jre -RESOURCE_BUNDLES_PROPERTIES = $(PKGDIR)/resources/rmiregistry.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = $(PKGDIR)/resources/rmiregistry.properties # # Rules diff --git a/jdk/make/sun/rmi/rmic/Makefile b/jdk/make/sun/rmi/rmic/Makefile index c6c7c53e23c..8d9f435e6ec 100644 --- a/jdk/make/sun/rmi/rmic/Makefile +++ b/jdk/make/sun/rmi/rmic/Makefile @@ -43,7 +43,7 @@ FILES_java = $(RMIC_java) # Resources # LOCALE_SET_DEFINITION = jdk -RESOURCE_BUNDLES_PROPERTIES = $(PKGDIR)/resources/rmic.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = $(PKGDIR)/resources/rmic.properties # # Rules diff --git a/jdk/make/sun/rmi/rmid/Makefile b/jdk/make/sun/rmi/rmid/Makefile index 48c62d1a942..845b103220d 100644 --- a/jdk/make/sun/rmi/rmid/Makefile +++ b/jdk/make/sun/rmi/rmid/Makefile @@ -39,7 +39,7 @@ build: stubs # Resources # LOCALE_SET_DEFINITION = jre -RESOURCE_BUNDLES_PROPERTIES = sun/rmi/server/resources/rmid.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = sun/rmi/server/resources/rmid.properties # # Extra dependencies. diff --git a/jdk/make/sun/serialver/Makefile b/jdk/make/sun/serialver/Makefile index 3dfae491160..e848154af6a 100644 --- a/jdk/make/sun/serialver/Makefile +++ b/jdk/make/sun/serialver/Makefile @@ -41,7 +41,7 @@ AUTO_FILES_JAVA_DIRS = sun/tools/serialver # Resources # LOCALE_SET_DEFINITION = jdk -RESOURCE_BUNDLES_PROPERTIES = $(PKGDIR)/resources/serialver.properties +RESOURCE_BUNDLES_UNCOMPILED_PROPERTIES = $(PKGDIR)/resources/serialver.properties # # Rules diff --git a/jdk/make/sun/splashscreen/Makefile b/jdk/make/sun/splashscreen/Makefile index e65ab7ec181..0df06e4482e 100644 --- a/jdk/make/sun/splashscreen/Makefile +++ b/jdk/make/sun/splashscreen/Makefile @@ -67,7 +67,7 @@ ifneq ($(PLATFORM), windows) OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -lpthread else # PLATFORM CFLAGS += -DWITH_WIN32 - OTHER_LDLIBS += kernel32.lib user32.lib gdi32.lib + OTHER_LDLIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib /DELAYLOAD:user32.dll #$(JVMLIB) $(OBJDIR)/../../jpeg/$(OBJDIRNAME)/jpeg$(SUFFIX).lib endif # PLATFORM @@ -85,13 +85,6 @@ vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3 -ifeq ($(PLATFORM), linux) - ifeq ($(ARCH_DATA_MODEL), 64) - # 64-bit gcc has problems compiling MMX instructions. - # Google it for more details. Possibly the newer versions of - # the PNG-library and/or the new compiler will not need this - # option in the future. - CPPFLAGS += -DPNG_NO_MMX_CODE - endif -endif - +# Shun the less than portable MMX assembly code in pnggccrd.c, +# and use alternative implementations in C. +CPPFLAGS += -DPNG_NO_MMX_CODE diff --git a/jdk/make/sun/xawt/mapfile-vers b/jdk/make/sun/xawt/mapfile-vers index 07b16cefcc8..3913f4060f1 100644 --- a/jdk/make/sun/xawt/mapfile-vers +++ b/jdk/make/sun/xawt/mapfile-vers @@ -151,6 +151,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl; Java_sun_awt_X11_XRobotPeer_mouseWheelImpl; Java_sun_awt_X11_XRobotPeer_setup; + Java_sun_awt_X11_XRobotPeer_getNumberOfButtonsImpl; Java_java_awt_Component_initIDs; Java_java_awt_Container_initIDs; Java_java_awt_Button_initIDs; @@ -288,6 +289,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_XGetIconSizes; Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym; Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode; + Java_sun_awt_X11_XlibWrapper_XQueryKeymap; Java_sun_awt_X11_XlibWrapper_XGetModifierMapping; Java_sun_awt_X11_XlibWrapper_XFreeModifiermap; Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab; diff --git a/jdk/make/tools/sharing/classlist.linux b/jdk/make/tools/sharing/classlist.linux index b61d94f54ab..0b8c11e8b3a 100644 --- a/jdk/make/tools/sharing/classlist.linux +++ b/jdk/make/tools/sharing/classlist.linux @@ -1718,6 +1718,7 @@ javax/swing/plaf/basic/BasicToolBarSeparatorUI sun/awt/color/CMM java/applet/Applet java/awt/Panel +com/sun/awt/AWTUtilities javax/swing/KeyboardManager$ComponentKeyStrokePair sun/awt/EmbeddedFrame sun/awt/im/InputMethodContext diff --git a/jdk/make/tools/sharing/classlist.solaris b/jdk/make/tools/sharing/classlist.solaris index e645a4ba065..898bca057c2 100644 --- a/jdk/make/tools/sharing/classlist.solaris +++ b/jdk/make/tools/sharing/classlist.solaris @@ -961,6 +961,7 @@ sun/awt/SunToolkit$3 javax/swing/SystemEventQueueUtilities$ComponentWorkRequest java/applet/Applet java/awt/Panel +com/sun/awt/AWTUtilities sun/awt/X11/XExposeEvent java/util/jar/Manifest java/io/ByteArrayInputStream diff --git a/jdk/make/tools/sharing/classlist.windows b/jdk/make/tools/sharing/classlist.windows index 6459f9e5ab4..f1a5a693b9e 100644 --- a/jdk/make/tools/sharing/classlist.windows +++ b/jdk/make/tools/sharing/classlist.windows @@ -1621,6 +1621,7 @@ javax/swing/plaf/basic/BasicToolBarSeparatorUI sun/font/FontDesignMetrics$MetricsKey java/applet/Applet java/awt/Panel +com/sun/awt/AWTUtilities javax/swing/KeyboardManager$ComponentKeyStrokePair sun/awt/im/InputMethodContext java/awt/im/spi/InputMethodContext diff --git a/jdk/src/share/classes/com/sun/awt/AWTUtilities.java b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java new file mode 100644 index 00000000000..818ac6f53e0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/awt/AWTUtilities.java @@ -0,0 +1,104 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.awt; + +import java.awt.*; +import sun.awt.AWTAccessor; + + +/** + * A collection of utility methods for AWT. + * + * The functionality provided by the static methods of the class includes: + *
    + *
  • Setting a 'mixing-cutout' shape for a component. + *
+ *

+ * WARNING: This class is an implementation detail and only meant + * for limited use outside of the core platform. This API may change + * drastically between update release, and it may even be + * removed or be moved in some other package(s)/class(es). + */ +public final class AWTUtilities { + + /** + * The AWTUtilities class should not be instantiated + */ + private AWTUtilities() { + } + + /** + * Sets a 'mixing-cutout' shape for the given component. + * + * By default a lightweight component is treated as an opaque rectangle for + * the purposes of the Heavyweight/Lightweight Components Mixing feature. + * This method enables developers to set an arbitrary shape to be cut out + * from heavyweight components positioned underneath the lightweight + * component in the z-order. + *

+ * The {@code shape} argument may have the following values: + *

    + *
  • {@code null} - reverts the default cutout shape (the rectangle equal + * to the component's {@code getBounds()}) + *
  • empty-shape - does not cut out anything from heavyweight + * components. This makes the given lightweight component effectively + * transparent. Note that descendants of the lightweight component still + * affect the shapes of heavyweight components. An example of an + * empty-shape is {@code new Rectangle()}. + *
  • non-empty-shape - the given shape will be cut out from + * heavyweight components. + *
+ *

+ * The most common example when the 'mixing-cutout' shape is needed is a + * glass pane component. The {@link JRootPane#setGlassPane()} method + * automatically sets the empty-shape as the 'mixing-cutout' shape + * for the given glass pane component. If a developer needs some other + * 'mixing-cutout' shape for the glass pane (which is rare), this must be + * changed manually after installing the glass pane to the root pane. + *

+ * Note that the 'mixing-cutout' shape neither affects painting, nor the + * mouse events handling for the given component. It is used exclusively + * for the purposes of the Heavyweight/Lightweight Components Mixing + * feature. + * + * @param component the component that needs non-default + * 'mixing-cutout' shape + * @param shape the new 'mixing-cutout' shape + * @throws NullPointerException if the component argument is {@code null} + */ + public static void setComponentMixingCutoutShape(Component component, + Shape shape) + { + if (component == null) { + throw new NullPointerException( + "The component argument should not be null."); + } + + AWTAccessor.getComponentAccessor().setMixingCutoutShape(component, + shape); + } +} + diff --git a/jdk/src/share/classes/com/sun/beans/ObjectHandler.java b/jdk/src/share/classes/com/sun/beans/ObjectHandler.java deleted file mode 100644 index 6daeab953a2..00000000000 --- a/jdk/src/share/classes/com/sun/beans/ObjectHandler.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.beans; - -import com.sun.beans.finder.ClassFinder; - -import java.beans.*; -import java.util.*; - -import org.xml.sax.*; - -import static java.util.Locale.ENGLISH; - -/** - * WARNING: This class is an implementation detail and only meant - * for use within the core platform. You should NOT depend upon it! This - * API may change drastically between dot dot release, and it may even be - * removed. - * - * @see java.beans.XMLEncoder - * @see java.io.ObjectInputStream - * - * @since 1.4 - * - * @author Philip Milne - */ -public class ObjectHandler extends HandlerBase { - - public static Class typeNameToClass(String typeName) { - typeName = typeName.intern(); - if (typeName == "boolean") return Boolean.class; - if (typeName == "byte") return Byte.class; - if (typeName == "char") return Character.class; - if (typeName == "short") return Short.class; - if (typeName == "int") return Integer.class; - if (typeName == "long") return Long.class; - if (typeName == "float") return Float.class; - if (typeName == "double") return Double.class; - if (typeName == "void") return Void.class; - return null; - } - - public static Class typeNameToPrimitiveClass(String typeName) { - typeName = typeName.intern(); - if (typeName == "boolean") return boolean.class; - if (typeName == "byte") return byte.class; - if (typeName == "char") return char.class; - if (typeName == "short") return short.class; - if (typeName == "int") return int.class; - if (typeName == "long") return long.class; - if (typeName == "float") return float.class; - if (typeName == "double") return double.class; - if (typeName == "void") return void.class; - return null; - } - - /** - * Returns the Class object associated with - * the class or interface with the given string name, - * using the default class loader. - * - * @param name fully qualified name of the desired class - * @param cl class loader from which the class must be loaded - * @return class object representing the desired class - * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader - * - * @deprecated As of JDK version 7, replaced by - * {@link ClassFinder#resolveClass(String)}. - */ - @Deprecated - public static Class classForName(String name) throws ClassNotFoundException { - return ClassFinder.resolveClass(name); - } - - /** - * Returns the Class object associated with - * the class or interface with the given string name, - * using the given class loader. - * - * @param name fully qualified name of the desired class - * @param cl class loader from which the class must be loaded - * @return class object representing the desired class - * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader - * - * @deprecated As of JDK version 7, replaced by - * {@link ClassFinder#resolveClass(String,ClassLoader)}. - */ - @Deprecated - public static Class classForName(String name, ClassLoader cl) - throws ClassNotFoundException { - return ClassFinder.resolveClass(name, cl); - } - - private Hashtable environment; - private Vector expStack; - private StringBuffer chars; - private XMLDecoder is; - private ClassLoader ldr; - private int itemsRead = 0; - private boolean isString; - - public ObjectHandler() { - environment = new Hashtable(); - expStack = new Vector(); - chars = new StringBuffer(); - } - - public ObjectHandler(XMLDecoder is) { - this(); - this.is = is; - } - - /* loader can be null */ - public ObjectHandler(XMLDecoder is, ClassLoader loader) { - this(is); - this.ldr = loader; - } - - - public void reset() { - expStack.clear(); - chars.setLength(0); - MutableExpression e = new MutableExpression(); - e.setTarget(classForName2("java.lang.Object")); - e.setMethodName("null"); - expStack.add(e); - } - - private Object getValue(Expression exp) { - try { - return exp.getValue(); - } - catch (Exception e) { - if (is != null) { - is.getExceptionListener().exceptionThrown(e); - } - return null; - } - } - - private void addArg(Object arg) { - lastExp().addArg(arg); - } - - private Object pop(Vector v) { - int last = v.size()-1; - Object result = v.get(last); - v.remove(last); - return result; - } - - private Object eval() { - return getValue(lastExp()); - } - - private MutableExpression lastExp() { - return (MutableExpression)expStack.lastElement(); - } - - public Object dequeueResult() { - Object[] results = lastExp().getArguments(); - return results[itemsRead++]; - } - - private boolean isPrimitive(String name) { - return name != "void" && typeNameToClass(name) != null; - } - - private void simulateException(String message) { - Exception e = new Exception(message); - e.fillInStackTrace(); - if (is != null) { - is.getExceptionListener().exceptionThrown(e); - } - } - - private Class classForName2(String name) { - try { - return ClassFinder.resolveClass(name, this.ldr); - } - catch (ClassNotFoundException e) { - if (is != null) { - is.getExceptionListener().exceptionThrown(e); - } - } - return null; - } - - private HashMap getAttributes(AttributeList attrs) { - HashMap attributes = new HashMap(); - if (attrs != null && attrs.getLength() > 0) { - for(int i = 0; i < attrs.getLength(); i++) { - attributes.put(attrs.getName(i), attrs.getValue(i)); - } - } - return attributes; - } - - public void startElement(String name, AttributeList attrs) throws SAXException { - name = name.intern(); // Xerces parser does not supply unique tag names. - if (this.isString) { - parseCharCode(name, getAttributes(attrs)); - return; - } - chars.setLength(0); - - HashMap attributes = getAttributes(attrs); - MutableExpression e = new MutableExpression(); - - // Target - String className = (String)attributes.get("class"); - if (className != null) { - e.setTarget(classForName2(className)); - } - - // Property - Object property = attributes.get("property"); - String index = (String)attributes.get("index"); - if (index != null) { - property = new Integer(index); - e.addArg(property); - } - e.setProperty(property); - - // Method - String methodName = (String)attributes.get("method"); - if (methodName == null && property == null) { - methodName = "new"; - } - e.setMethodName(methodName); - - // Tags - if (name == "string") { - e.setTarget(String.class); - e.setMethodName("new"); - this.isString = true; - } - else if (isPrimitive(name)){ - Class wrapper = typeNameToClass(name); - e.setTarget(wrapper); - e.setMethodName("new"); - parseCharCode(name, attributes); - } - else if (name == "class") { - e.setTarget(Class.class); - e.setMethodName("forName"); - } - else if (name == "null") { - // Create an arbitrary expression that has a value of null - for - // consistency. - e.setTarget(Object.class); - e.setMethodName("getSuperclass"); - e.setValue(null); - } - else if (name == "void") { - if (e.getTarget() == null) { // this check is for "void class="foo" method= ..." - e.setTarget(eval()); - } - } - else if (name == "array") { - // The class attribute means sub-type for arrays. - String subtypeName = (String)attributes.get("class"); - Class subtype = (subtypeName == null) ? Object.class : classForName2(subtypeName); - String length = (String)attributes.get("length"); - if (length != null) { - e.setTarget(java.lang.reflect.Array.class); - e.addArg(subtype); - e.addArg(new Integer(length)); - } - else { - Class arrayClass = java.lang.reflect.Array.newInstance(subtype, 0).getClass(); - e.setTarget(arrayClass); - } - } - else if (name == "java") { - e.setValue(is); // The outermost scope is the stream itself. - } - else if (name == "object") { - } - else { - simulateException("Unrecognized opening tag: " + name + " " + attrsToString(attrs)); - return; - } - - // ids - String idName = (String)attributes.get("id"); - if (idName != null) { - environment.put(idName, e); - } - - // idrefs - String idrefName = (String)attributes.get("idref"); - if (idrefName != null) { - e.setValue(lookup(idrefName)); - } - - // fields - String fieldName = (String)attributes.get("field"); - if (fieldName != null) { - e.setValue(getFieldValue(e.getTarget(), fieldName)); - } - expStack.add(e); - } - - private Object getFieldValue(Object target, String fieldName) { - try { - Class type = target.getClass(); - if (type == Class.class) { - type = (Class)target; - } - java.lang.reflect.Field f = sun.reflect.misc.FieldUtil.getField(type, fieldName); - return f.get(target); - } - catch (Exception e) { - if (is != null) { - is.getExceptionListener().exceptionThrown(e); - } - return null; - } - } - - private String attrsToString(AttributeList attrs) { - StringBuffer b = new StringBuffer(); - for (int i = 0; i < attrs.getLength (); i++) { - b.append(attrs.getName(i)+"=\""+attrs.getValue(i)+"\" "); - } - return b.toString(); - } - - public void characters(char buf [], int offset, int len) throws SAXException { - chars.append(new String(buf, offset, len)); - } - - private void parseCharCode(String name, Map map) { - if (name == "char") { - String value = (String) map.get("code"); - if (value != null) { - int code = Integer.decode(value); - for (char ch : Character.toChars(code)) { - this.chars.append(ch); - } - } - } - } - - public Object lookup(String s) { - Expression e = (Expression)environment.get(s); - if (e == null) { - simulateException("Unbound variable: " + s); - } - return getValue(e); - } - - public void register(String id, Object value) { - Expression e = new MutableExpression(); - e.setValue(value); - environment.put(id, e); - } - - public void endElement(String name) throws SAXException { - name = name.intern(); // Xerces parser does not supply unique tag names. - if (name == "string") { - this.isString = false; - } else if (this.isString) { - return; - } - if (name == "java") { - return; - } - if (isPrimitive(name) || name == "string" || name == "class") { - addArg(chars.toString()); - } - if (name == "object" || name == "array" || name == "void" || - isPrimitive(name) || name == "string" || name == "class" || - name == "null") { - Expression e = (Expression)pop(expStack); - Object value = getValue(e); - if (name != "void") { - addArg(value); - } - } - else { - simulateException("Unrecognized closing tag: " + name); - } - } -} - - -class MutableExpression extends Expression { - private Object target; - private String methodName; - - private Object property; - private Vector argV = new Vector(); - - private String capitalize(String propertyName) { - if (propertyName.length() == 0) { - return propertyName; - } - return propertyName.substring(0, 1).toUpperCase(ENGLISH) + propertyName.substring(1); - } - - public MutableExpression() { - super(null, null, null); - } - - public Object[] getArguments() { - return argV.toArray(); - } - - public String getMethodName() { - if (property == null) { - return methodName; - } - int setterArgs = (property instanceof String) ? 1 : 2; - String methodName = (argV.size() == setterArgs) ? "set" : "get"; - if (property instanceof String) { - return methodName + capitalize((String)property); - } - else { - return methodName; - } - } - - public void addArg(Object arg) { - argV.add(arg); - } - - public void setTarget(Object target) { - this.target = target; - } - - public Object getTarget() { - return target; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - public void setProperty(Object property) { - this.property = property; - } - - public void setValue(Object value) { - super.setValue(value); - } - - public Object getValue() throws Exception { - return super.getValue(); - } -} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java new file mode 100644 index 00000000000..d34fce45635 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/AccessorElementHandler.java @@ -0,0 +1,105 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This is base class that simplifies access to entities (fields or properties). + * The {@code name} attribute specifies the name of the accessible entity. + * The element defines getter if it contains no argument + * or setter if it contains one argument. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +abstract class AccessorElementHandler extends ElementHandler { + private String name; + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *

+ *
name + *
the name of the accessible entity + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("name")) { // NON-NLS: the attribute name + this.name = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument that is used to set the value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.value != null) { + throw new IllegalStateException("Could not add argument to evaluated element"); + } + setValue(this.name, argument); + this.value = ValueObjectImpl.VOID; + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.value == null) { + this.value = ValueObjectImpl.create(getValue(this.name)); + } + return this.value; + } + + /** + * Returns the value of the entity with specified {@code name}. + * + * @param name the name of the accessible entity + * @return the value of the specified entity + */ + protected abstract Object getValue(String name); + + /** + * Sets the new value for the entity with specified {@code name}. + * + * @param name the name of the accessible entity + * @param value the new value for the specified entity + */ + protected abstract void setValue(String name, Object value); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java new file mode 100644 index 00000000000..0bfcec6e46a --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ArrayElementHandler.java @@ -0,0 +1,133 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.lang.reflect.Array; + +/** + * This class is intended to handle <array> element, + * that is used to array creation. + * The {@code length} attribute specifies the length of the array. + * The {@code class} attribute specifies the elements type. + * The {@link Object} type is used by default. + * For example:
+ * <array length="10"/>
+ * is equivalent to {@code new Component[10]} in Java code. + * The {@code set} and {@code get} methods, + * as defined in the {@link java.util.List} interface, + * can be used as if they could be applied to array instances. + * The {@code index} attribute can thus be used with arrays. + * For example:
+ * <array length="3" class="java.lang.String">
+ *     <void index="1">
+ *         <string>Hello, world</string>
+ *     </void>
+ * </array>
+ * is equivalent to the following Java code:
+ * String[] s = new String[3];
+ * s[1] = "Hello, world";
+ * It is possible to omit the {@code length} attribute and + * specify the values directly, without using {@code void} tags. + * The length of the array is equal to the number of values specified. + * For example:
+ * <array id="array" class="int">
+ *     <int>123</int>
+ *     <int>456</int>
+ * </array>
+ * is equivalent to {@code int[] array = {123, 456}} in Java code. + *

The following atributes are supported: + *

+ *
length + *
the array length + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ArrayElementHandler extends NewElementHandler { + private Integer length; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
length + *
the array length + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("length")) { // NON-NLS: the attribute name + this.length = Integer.valueOf(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Calculates the value of this element + * if the lentgh attribute is set. + */ + @Override + public void startElement() { + if (this.length != null) { + getValueObject(); + } + } + + /** + * Creates an instance of the array. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + */ + @Override + protected ValueObject getValueObject(Class type, Object[] args) { + if (type == null) { + type = Object.class; + } + if (this.length != null) { + return ValueObjectImpl.create(Array.newInstance(type, this.length)); + } + Object array = Array.newInstance(type, args.length); + for (int i = 0; i < args.length; i++) { + Array.set(array, i, args[i]); + } + return ValueObjectImpl.create(array); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java new file mode 100644 index 00000000000..a5f401b5f49 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/BooleanElementHandler.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <boolean> element. + * This element specifies {@code boolean} values. + * The class {@link Boolean} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <boolean>true</boolean>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Boolean">
+ *     <string>true</string>
+ * </method>
+ * which is equivalent to {@code Boolean.valueOf("true")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class BooleanElementHandler extends StringElementHandler { + + /** + * Creates {@code boolean} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code boolean} value + */ + @Override + public Object getValue(String argument) { + if (Boolean.TRUE.toString().equalsIgnoreCase(argument)) { + return Boolean.TRUE; + } + if (Boolean.FALSE.toString().equalsIgnoreCase(argument)) { + return Boolean.FALSE; + } + throw new IllegalArgumentException("Unsupported boolean argument: " + argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java new file mode 100644 index 00000000000..d7d458f0104 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ByteElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <byte> element. + * This element specifies {@code byte} values. + * The class {@link Byte} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <byte>127</byte>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Byte">
+ *     <string>127</string>
+ * </method>
+ * which is equivalent to {@code Byte.decode("127")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ByteElementHandler extends StringElementHandler { + + /** + * Creates {@code byte} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code byte} value + */ + @Override + public Object getValue(String argument) { + return Byte.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java new file mode 100644 index 00000000000..910b5a63f70 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/CharElementHandler.java @@ -0,0 +1,92 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <char> element. + * This element specifies {@code char} values. + * The class {@link Character} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <char>X</char>
+ * which is equivalent to {@code Character.valueOf('X')} in Java code. + *

The following atributes are supported: + *

+ *
code + *
this attribute specifies character code + *
id + *
the identifier of the variable that is intended to store the result + *
+ * The {@code code} attribute can be used for characters + * that are illegal in XML document, for example:
+ * <char code="0"/>
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class CharElementHandler extends StringElementHandler { + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
code + *
this attribute specifies character code + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("code")) { // NON-NLS: the attribute name + int code = Integer.decode(value); + for (char ch : Character.toChars(code)) { + addCharacter(ch); + } + } else { + super.addAttribute(name, value); + } + } + + /** + * Creates {@code char} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code char} value + */ + @Override + public Object getValue(String argument) { + if (argument.length() != 1) { + throw new IllegalArgumentException("Wrong characters count"); + } + return Character.valueOf(argument.charAt(0)); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java new file mode 100644 index 00000000000..c6ca9856416 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ClassElementHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <class> element. + * This element specifies {@link Class} values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <class>java.lang.Class</class>
+ * is shortcut to
+ * <method name="forName" class="java.lang.Class">
+ *     <string>java.lang.Class</string>
+ * </method>
+ * which is equivalent to {@code Class.forName("java.lang.Class")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ClassElementHandler extends StringElementHandler { + + /** + * Creates class by the name from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code Class} value + */ + @Override + public Object getValue(String argument) { + return getOwner().findClass(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java new file mode 100644 index 00000000000..4c409a12a9b --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/DocumentHandler.java @@ -0,0 +1,389 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.ClassFinder; + +import java.beans.ExceptionListener; + +import java.io.IOException; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * The main class to parse JavaBeans XML archive. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + * + * @see ElementHandler + */ +public final class DocumentHandler extends DefaultHandler { + private final Map> handlers = new HashMap>(); + + private final Map environment = new HashMap(); + + private final List objects = new ArrayList(); + + private Reference loader; + private ExceptionListener listener; + private Object owner; + + private ElementHandler handler; + + /** + * Creates new instance of document handler. + */ + public DocumentHandler() { + setElementHandler("java", JavaElementHandler.class); // NON-NLS: the element name + setElementHandler("null", NullElementHandler.class); // NON-NLS: the element name + setElementHandler("array", ArrayElementHandler.class); // NON-NLS: the element name + setElementHandler("class", ClassElementHandler.class); // NON-NLS: the element name + setElementHandler("string", StringElementHandler.class); // NON-NLS: the element name + setElementHandler("object", ObjectElementHandler.class); // NON-NLS: the element name + + setElementHandler("void", VoidElementHandler.class); // NON-NLS: the element name + setElementHandler("char", CharElementHandler.class); // NON-NLS: the element name + setElementHandler("byte", ByteElementHandler.class); // NON-NLS: the element name + setElementHandler("short", ShortElementHandler.class); // NON-NLS: the element name + setElementHandler("int", IntElementHandler.class); // NON-NLS: the element name + setElementHandler("long", LongElementHandler.class); // NON-NLS: the element name + setElementHandler("float", FloatElementHandler.class); // NON-NLS: the element name + setElementHandler("double", DoubleElementHandler.class); // NON-NLS: the element name + setElementHandler("boolean", BooleanElementHandler.class); // NON-NLS: the element name + + // some handlers for new elements + setElementHandler("new", NewElementHandler.class); // NON-NLS: the element name + setElementHandler("var", VarElementHandler.class); // NON-NLS: the element name + setElementHandler("true", TrueElementHandler.class); // NON-NLS: the element name + setElementHandler("false", FalseElementHandler.class); // NON-NLS: the element name + setElementHandler("field", FieldElementHandler.class); // NON-NLS: the element name + setElementHandler("method", MethodElementHandler.class); // NON-NLS: the element name + setElementHandler("property", PropertyElementHandler.class); // NON-NLS: the element name + } + + /** + * Returns the class loader used to instantiate objects. + * If the class loader has not been explicitly set + * then {@code null} is returned. + * + * @return the class loader used to instantiate objects + */ + public ClassLoader getClassLoader() { + return (this.loader != null) + ? this.loader.get() + : null; + } + + /** + * Sets the class loader used to instantiate objects. + * If the class loader is not set + * then default class loader will be used. + * + * @param loader a classloader to use + */ + public void setClassLoader(ClassLoader loader) { + this.loader = new WeakReference(loader); + } + + /** + * Returns the exception listener for parsing. + * The exception listener is notified + * when handler catches recoverable exceptions. + * If the exception listener has not been explicitly set + * then default exception listener is returned. + * + * @return the exception listener for parsing + */ + public ExceptionListener getExceptionListener() { + return this.listener; + } + + /** + * Sets the exception listener for parsing. + * The exception listener is notified + * when handler catches recoverable exceptions. + * + * @param listener the exception listener for parsing + */ + public void setExceptionListener(ExceptionListener listener) { + this.listener = listener; + } + + /** + * Returns the owner of this document handler. + * + * @return the owner of this document handler + */ + public Object getOwner() { + return this.owner; + } + + /** + * Sets the owner of this document handler. + * + * @param owner the owner of this document handler + */ + public void setOwner(Object owner) { + this.owner = owner; + } + + /** + * Returns the handler for the element with specified name. + * + * @param name the name of the element + * @return the corresponding element handler + */ + public Class getElementHandler(String name) { + Class type = this.handlers.get(name); + if (type == null) { + throw new IllegalArgumentException("Unsupported element: " + name); + } + return type; + } + + /** + * Sets the handler for the element with specified name. + * + * @param name the name of the element + * @param handler the corresponding element handler + */ + public void setElementHandler(String name, Class handler) { + this.handlers.put(name, handler); + } + + /** + * Indicates whether the variable with specified identifier is defined. + * + * @param id the identifier + * @return @{code true} if the variable is defined; + * @{code false} otherwise + */ + public boolean hasVariable(String id) { + return this.environment.containsKey(id); + } + + /** + * Returns the value of the variable with specified identifier. + * + * @param id the identifier + * @return the value of the variable + */ + public Object getVariable(String id) { + if (!this.environment.containsKey(id)) { + throw new IllegalArgumentException("Unbound variable: " + id); + } + return this.environment.get(id); + } + + /** + * Sets new value of the variable with specified identifier. + * + * @param id the identifier + * @param value new value of the variable + */ + public void setVariable(String id, Object value) { + this.environment.put(id, value); + } + + /** + * Returns the array of readed objects. + * + * @return the array of readed objects + */ + public Object[] getObjects() { + return this.objects.toArray(); + } + + /** + * Adds the object to the list of readed objects. + * + * @param object the object that is readed from XML document + */ + void addObject(Object object) { + this.objects.add(object); + } + + /** + * Prepares this handler to read objects from XML document. + */ + @Override + public void startDocument() { + this.objects.clear(); + this.handler = null; + } + + /** + * Parses opening tag of XML element + * using corresponding element handler. + * + * @param uri the namespace URI, or the empty string + * if the element has no namespace URI or + * if namespace processing is not being performed + * @param localName the local name (without prefix), or the empty string + * if namespace processing is not being performed + * @param qName the qualified name (with prefix), or the empty string + * if qualified names are not available + * @param attributes the attributes attached to the element + */ + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + ElementHandler parent = this.handler; + try { + this.handler = getElementHandler(qName).newInstance(); + this.handler.setOwner(this); + this.handler.setParent(parent); + } + catch (Exception exception) { + throw new SAXException(exception); + } + for (int i = 0; i < attributes.getLength(); i++) + try { + String name = attributes.getQName(i); + String value = attributes.getValue(i); + this.handler.addAttribute(name, value); + } + catch (RuntimeException exception) { + handleException(exception); + } + + this.handler.startElement(); + } + + /** + * Parses closing tag of XML element + * using corresponding element handler. + * + * @param uri the namespace URI, or the empty string + * if the element has no namespace URI or + * if namespace processing is not being performed + * @param localName the local name (without prefix), or the empty string + * if namespace processing is not being performed + * @param qName the qualified name (with prefix), or the empty string + * if qualified names are not available + */ + @Override + public void endElement(String uri, String localName, String qName) { + try { + this.handler.endElement(); + } + catch (RuntimeException exception) { + handleException(exception); + } + finally { + this.handler = this.handler.getParent(); + } + } + + /** + * Parses character data inside XML element. + * + * @param chars the array of characters + * @param start the start position in the character array + * @param length the number of characters to use + */ + @Override + public void characters(char[] chars, int start, int length) { + if (this.handler != null) { + try { + while (0 < length--) { + this.handler.addCharacter(chars[start++]); + } + } + catch (RuntimeException exception) { + handleException(exception); + } + } + } + + /** + * Handles an exception using current exception listener. + * + * @param exception an exception to handle + * @see #setExceptionListener + */ + public void handleException(Exception exception) { + if (this.listener == null) { + throw new IllegalStateException(exception); + } + this.listener.exceptionThrown(exception); + } + + /** + * Starts parsing of the specified input source. + * + * @param input the input source to parse + */ + public void parse(InputSource input) { + try { + SAXParserFactory.newInstance().newSAXParser().parse(input, this); + } + catch (ParserConfigurationException exception) { + handleException(exception); + } + catch (SAXException wrapper) { + Exception exception = wrapper.getException(); + if (exception == null) { + exception = wrapper; + } + handleException(exception); + } + catch (IOException exception) { + handleException(exception); + } + } + + /** + * Resolves class by name using current class loader. + * This method handles exception using current exception listener. + * + * @param name the name of the class + * @return the object that represents the class + */ + public Class findClass(String name) { + try { + return ClassFinder.resolveClass(name, getClassLoader()); + } + catch (ClassNotFoundException exception) { + handleException(exception); + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java new file mode 100644 index 00000000000..e0f58677627 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/DoubleElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <double> element. + * This element specifies {@code double} values. + * The class {@link Double} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <double>1.23e45</double>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Double">
+ *     <string>1.23e45</string>
+ * </method>
+ * which is equivalent to {@code Double.valueOf("1.23e45")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class DoubleElementHandler extends StringElementHandler { + + /** + * Creates {@code double} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code double} value + */ + @Override + public Object getValue(String argument) { + return Double.valueOf(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java new file mode 100644 index 00000000000..ca85cd6ed08 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ElementHandler.java @@ -0,0 +1,224 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * The base class for element handlers. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + * + * @see DocumentHandler + */ +public abstract class ElementHandler { + private DocumentHandler owner; + private ElementHandler parent; + + private String id; + + /** + * Returns the document handler that creates this element handler. + * + * @return the owner document handler + */ + public final DocumentHandler getOwner() { + return this.owner; + } + + /** + * Sets the document handler that creates this element handler. + * The owner document handler should be set after instantiation. + * Such approach is used to simplify the extensibility. + * + * @param owner the owner document handler + * @see DocumentHandler#startElement + */ + final void setOwner(DocumentHandler owner) { + if (owner == null) { + throw new IllegalArgumentException("Every element should have owner"); + } + this.owner = owner; + } + + /** + * Returns the element handler that contains this one. + * + * @return the parent element handler + */ + public final ElementHandler getParent() { + return this.parent; + } + + /** + * Sets the element handler that contains this one. + * The parent element handler should be set after instantiation. + * Such approach is used to simplify the extensibility. + * + * @param parent the parent element handler + * @see DocumentHandler#startElement + */ + final void setParent(ElementHandler parent) { + this.parent = parent; + } + + /** + * Returns the value of the variable with specified identifier. + * + * @param id the identifier + * @return the value of the variable + */ + protected final Object getVariable(String id) { + if (id.equals(this.id)) { + ValueObject value = getValueObject(); + if (value.isVoid()) { + throw new IllegalStateException("The element does not return value"); + } + return value.getValue(); + } + return (this.parent != null) + ? this.parent.getVariable(id) + : this.owner.getVariable(id); + } + + /** + * Returns the value of the parent element. + * + * @return the value of the parent element + */ + protected Object getContextBean() { + if (this.parent != null) { + ValueObject value = this.parent.getValueObject(); + if (!value.isVoid()) { + return value.getValue(); + } + throw new IllegalStateException("The outer element does not return value"); + } else { + Object value = this.owner.getOwner(); + if (value != null) { + return value; + } + throw new IllegalStateException("The topmost element does not have context"); + } + } + + /** + * Parses attributes of the element. + * By default, the following atribute is supported: + *
+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + public void addAttribute(String name, String value) { + if (name.equals("id")) { // NON-NLS: the attribute name + this.id = value; + } else { + throw new IllegalArgumentException("Unsupported attribute: " + name); + } + } + + /** + * This method is called before parsing of the element's body. + * All attributes are parsed at this point. + * By default, do nothing. + */ + public void startElement() { + } + + /** + * This method is called after parsing of the element's body. + * By default, it calculates the value of this element. + * The following tasks are executing for any non-void value: + *
    + *
  1. If the {@code id} attribute is set + * the value of the variable with the specified identifier + * is set to the value of this element.
  2. + *
  3. This element is used as an argument of parent element if it is possible.
  4. + *
+ * + * @see #isArgument + */ + public void endElement() { + // do nothing if no value returned + ValueObject value = getValueObject(); + if (!value.isVoid()) { + if (this.id != null) { + this.owner.setVariable(this.id, value.getValue()); + } + if (isArgument()) { + if (this.parent != null) { + this.parent.addArgument(value.getValue()); + } else { + this.owner.addObject(value.getValue()); + } + } + } + } + + /** + * Adds the character that contained in this element. + * By default, only whitespaces are acceptable. + * + * @param ch the character + */ + public void addCharacter(char ch) { + if ((ch != ' ') && (ch != '\n') && (ch != '\t') && (ch != '\r')) { + throw new IllegalStateException("Illegal character with code " + (int) ch); + } + } + + /** + * Adds the argument that is used to calculate the value of this element. + * By default, no arguments are acceptable. + * + * @param argument the value of the element that contained in this one + */ + protected void addArgument(Object argument) { + throw new IllegalStateException("Could not add argument to simple element"); + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element can be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + protected boolean isArgument() { + return this.id == null; + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + protected abstract ValueObject getValueObject(); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java new file mode 100644 index 00000000000..6e8d786aa14 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FalseElementHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <false> element. + * This element specifies {@code false} value. + * It should not contain body or inner elements. + * For example:
+ * <false/>
+ * is equivalent to {@code false} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FalseElementHandler extends NullElementHandler { + + /** + * Returns {@code Boolean.FALSE} + * as a value of <false> element. + * + * @return {@code Boolean.FALSE} by default + */ + @Override + public Object getValue() { + return Boolean.FALSE; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java new file mode 100644 index 00000000000..ac255dde7fd --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FieldElementHandler.java @@ -0,0 +1,189 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.FieldFinder; + +import java.lang.reflect.Field; + +/** + * This class is intended to handle <field> element. + * This element simplifies access to the fields. + * If the {@code class} attribute is specified + * this element accesses static field of specified class. + * This element defines getter if it contains no argument. + * It returns the value of the field in this case. + * For example:
+ * <field name="TYPE" class="java.lang.Long"/>
+ * is equivalent to {@code Long.TYPE} in Java code. + * This element defines setter if it contains one argument. + * It does not return the value of the field in this case. + * For example:
+ * <field name="id"><int>0</int></field>
+ * is equivalent to {@code id = 0} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the field name + *
class + *
the type is used for static fields only + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FieldElementHandler extends AccessorElementHandler { + private Class type; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the field name + *
class + *
the type is used for static fields only + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("class")) { // NON-NLS: the attribute name + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return super.isArgument() && (this.type != null); // only static accessor can be used an argument + } + + /** + * Returns the context of the field. + * The context of the static field is the class object. + * The context of the non-static field is the value of the parent element. + * + * @return the context of the field + */ + @Override + protected Object getContextBean() { + return (this.type != null) + ? this.type + : super.getContextBean(); + } + + /** + * Returns the value of the field with specified {@code name}. + * + * @param name the name of the field + * @return the value of the specified field + */ + @Override + protected Object getValue(String name) { + try { + return getFieldValue(getContextBean(), name); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + return null; + } + + /** + * Sets the new value for the field with specified {@code name}. + * + * @param name the name of the field + * @param value the new value for the specified field + */ + @Override + protected void setValue(String name, Object value) { + try { + setFieldValue(getContextBean(), name, value); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + } + + /** + * Performs the search of the field with specified {@code name} + * in specified context and returns its value. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @return the value of the field + * @throws IllegalAccessException if the field is not accesible + * @throws NoSuchFieldException if the field is not found + */ + static Object getFieldValue(Object bean, String name) throws IllegalAccessException, NoSuchFieldException { + return findField(bean, name).get(bean); + } + + /** + * Performs the search of the field with specified {@code name} + * in specified context and updates its value. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @param value the new value for the field + * @throws IllegalAccessException if the field is not accesible + * @throws NoSuchFieldException if the field is not found + */ + private static void setFieldValue(Object bean, String name, Object value) throws IllegalAccessException, NoSuchFieldException { + findField(bean, name).set(bean, value); + } + + /** + * Performs the search of the field + * with specified {@code name} in specified context. + * + * @param bean the context bean that contains field + * @param name the name of the field + * @return field object that represents found field + * @throws NoSuchFieldException if the field is not found + */ + private static Field findField(Object bean, String name) throws NoSuchFieldException { + return (bean instanceof Class) + ? FieldFinder.findStaticField((Class) bean, name) + : FieldFinder.findField(bean.getClass(), name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java new file mode 100644 index 00000000000..08311b49f29 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/FloatElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <float> element. + * This element specifies {@code float} values. + * The class {@link Float} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <float>-1.23</float>
+ * is shortcut to
+ * <method name="valueOf" class="java.lang.Float">
+ *     <string>-1.23</string>
+ * </method>
+ * which is equivalent to {@code Float.valueOf("-1.23")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class FloatElementHandler extends StringElementHandler { + + /** + * Creates {@code float} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code float} value + */ + @Override + public Object getValue(String argument) { + return Float.valueOf(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java new file mode 100644 index 00000000000..ec5063fcd8e --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/IntElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <int> element. + * This element specifies {@code int} values. + * The class {@link Integer} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <int>-1</int>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Integer">
+ *     <string>-1</string>
+ * </method>
+ * which is equivalent to {@code Integer.decode("-1")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class IntElementHandler extends StringElementHandler { + + /** + * Creates {@code int} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code int} value + */ + @Override + public Object getValue(String argument) { + return Integer.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java new file mode 100644 index 00000000000..2d416a139fb --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/JavaElementHandler.java @@ -0,0 +1,151 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.beans.XMLDecoder; + +/** + * This class is intended to handle <java> element. + * Each element that appears in the body of this element + * is evaluated in the context of the decoder itself. + * Typically this outer context is used to retrieve the owner of the decoder, + * which can be set before reading the archive. + *

The following atributes are supported: + *

+ *
version + *
the Java version (not supported) + *
class + *
the type of preferable parser (not supported) + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @see DocumentHandler#getOwner + * @see DocumentHandler#setOwner + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class JavaElementHandler extends ElementHandler { + private Class type; + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
version + *
the Java version (not supported) + *
class + *
the type of preferable parser (not supported) + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("version")) { // NON-NLS: the attribute name + // unsupported attribute + } else if (name.equals("class")) { // NON-NLS: the attribute name + // check class for owner + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument to the list of readed objects. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected void addArgument(Object argument) { + getOwner().addObject(argument); + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // do not use owner as object + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected ValueObject getValueObject() { + if (this.value == null) { + this.value = ValueObjectImpl.create(getValue()); + } + return this.value; + } + + /** + * Returns the owner of the owner document handler + * as a value of <java> element. + * + * @return the owner of the owner document handler + */ + private Object getValue() { + Object owner = getOwner().getOwner(); + if ((this.type == null) || isValid(owner)) { + return owner; + } + if (owner instanceof XMLDecoder) { + XMLDecoder decoder = (XMLDecoder) owner; + owner = decoder.getOwner(); + if (isValid(owner)) { + return owner; + } + } + throw new IllegalStateException("Unexpected owner class: " + owner.getClass().getName()); + } + + /** + * Validates the owner of the <java> element. + * The owner is valid if it is {@code null} or an instance + * of the class specified by the {@code class} attribute. + * + * @param owner the owner of the <java> element + * @return {@code true} if the {@code owner} is valid; + * {@code false} otherwise + */ + private boolean isValid(Object owner) { + return (owner == null) || this.type.isInstance(owner); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java new file mode 100644 index 00000000000..a26f2f57fb6 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/LongElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <long> element. + * This element specifies {@code long} values. + * The class {@link Long} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <long>0xFFFF</long>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Long">
+ *     <string>0xFFFF</string>
+ * </method>
+ * which is equivalent to {@code Long.decode("0xFFFF")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class LongElementHandler extends StringElementHandler { + + /** + * Creates {@code long} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code long} value + */ + @Override + public Object getValue(String argument) { + return Long.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java new file mode 100644 index 00000000000..34d030c90b3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/MethodElementHandler.java @@ -0,0 +1,109 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.MethodFinder; + +import java.lang.reflect.Method; + +/** + * This class is intended to handle <method> element. + * It describes invocation of the method. + * The {@code name} attribute denotes + * the name of the method to invoke. + * If the {@code class} attribute is specified + * this element invokes static method of specified class. + * The inner elements specifies the arguments of the method. + * For example:
+ * <method name="valueOf" class="java.lang.Long">
+ *     <string>10</string>
+ * </method>
+ * is equivalent to {@code Long.valueOf("10")} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the method name + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class MethodElementHandler extends NewElementHandler { + private String name; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the method name + *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("name")) { // NON-NLS: the attribute name + this.name = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Returns the result of method execution. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + @Override + protected ValueObject getValueObject(Class type, Object[] args) throws Exception { + Object bean = getContextBean(); + Class[] types = getArgumentTypes(args); + Method method = (type != null) + ? MethodFinder.findStaticMethod(type, this.name, types) + : MethodFinder.findMethod(bean.getClass(), this.name, types); + + if (method.isVarArgs()) { + args = getArguments(args, method.getParameterTypes()); + } + Object value = method.invoke(bean, args); + return method.getReturnType().equals(void.class) + ? ValueObjectImpl.VOID + : ValueObjectImpl.create(value); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java new file mode 100644 index 00000000000..fc7debfc500 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/NewElementHandler.java @@ -0,0 +1,205 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.ConstructorFinder; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is intended to handle <new> element. + * It describes instantiation of the object. + * The {@code class} attribute denotes + * the name of the class to instantiate. + * The inner elements specifies the arguments of the constructor. + * For example:
+ * <new class="java.lang.Long">
+ *     <string>10</string>
+ * </new>
+ * is equivalent to {@code new Long("10")} in Java code. + *

The following atributes are supported: + *

+ *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class NewElementHandler extends ElementHandler { + private List arguments = new ArrayList(); + private ValueObject value = ValueObjectImpl.VOID; + + private Class type; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
class + *
the type of object for instantiation + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("class")) { // NON-NLS: the attribute name + this.type = getOwner().findClass(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Adds the argument to the list of arguments + * that is used to calculate the value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.arguments == null) { + throw new IllegalStateException("Could not add argument to evaluated element"); + } + this.arguments.add(argument); + } + + /** + * Returns the context of the method. + * The context of the static method is the class object. + * The context of the non-static method is the value of the parent element. + * + * @return the context of the method + */ + @Override + protected final Object getContextBean() { + return (this.type != null) + ? this.type + : super.getContextBean(); + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.arguments != null) { + try { + this.value = getValueObject(this.type, this.arguments.toArray()); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + finally { + this.arguments = null; + } + } + return this.value; + } + + /** + * Calculates the value of this element + * using the base class and the array of arguments. + * By default, it creates an instance of the base class. + * This method should be overridden in those handlers + * that extend behavior of this element. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + ValueObject getValueObject(Class type, Object[] args) throws Exception { + if (type == null) { + throw new IllegalArgumentException("Class name is not set"); + } + Class[] types = getArgumentTypes(args); + Constructor constructor = ConstructorFinder.findConstructor(type, types); + if (constructor.isVarArgs()) { + args = getArguments(args, constructor.getParameterTypes()); + } + return ValueObjectImpl.create(constructor.newInstance(args)); + } + + /** + * Converts the array of arguments to the array of corresponding classes. + * If argument is {@code null} the class is {@code null} too. + * + * @param arguments the array of arguments + * @return the array of corresponding classes + */ + static Class[] getArgumentTypes(Object[] arguments) { + Class[] types = new Class[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + if (arguments[i] != null) { + types[i] = arguments[i].getClass(); + } + } + return types; + } + + /** + * Resolves variable arguments. + * + * @param arguments the array of arguments + * @param types the array of parameter types + * @return the resolved array of arguments + */ + static Object[] getArguments(Object[] arguments, Class[] types) { + int index = types.length - 1; + if (types.length == arguments.length) { + Object argument = arguments[index]; + if (argument == null) { + return arguments; + } + Class type = types[index]; + if (type.isAssignableFrom(argument.getClass())) { + return arguments; + } + } + int length = arguments.length - index; + Class type = types[index].getComponentType(); + Object array = Array.newInstance(type, length); + System.arraycopy(arguments, index, array, 0, length); + + Object[] args = new Object[types.length]; + System.arraycopy(arguments, 0, args, 0, index); + args[index] = array; + return args; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java new file mode 100644 index 00000000000..a3e2d699c39 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/NullElementHandler.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <null> element. + * This element specifies {@code null} value. + * It should not contain body or inner elements. + * For example:
+ * <null/>
+ * is equivalent to {@code null} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class NullElementHandler extends ElementHandler implements ValueObject { + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + return this; + } + + /** + * Returns {@code null} + * as a value of <null> element. + * This method should be overridden in those handlers + * that extend behavior of this element. + * + * @return {@code null} by default + */ + public Object getValue() { + return null; + } + + /** + * Returns {@code void} state of this value object. + * + * @return {@code false} always + */ + public final boolean isVoid() { + return false; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java new file mode 100644 index 00000000000..3ab5ddca942 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ObjectElementHandler.java @@ -0,0 +1,168 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import java.beans.Expression; + +import static java.util.Locale.ENGLISH; + +/** + * This class is intended to handle <object> element. + * This element looks like <void> element, + * but its value is always used as an argument for element + * that contains this one. + *

The following atributes are supported: + *

+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +class ObjectElementHandler extends NewElementHandler { + private String idref; + private String field; + private Integer index; + private String property; + private String method; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public final void addAttribute(String name, String value) { + if (name.equals("idref")) { // NON-NLS: the attribute name + this.idref = value; + } else if (name.equals("field")) { // NON-NLS: the attribute name + this.field = value; + } else if (name.equals("index")) { // NON-NLS: the attribute name + this.index = Integer.valueOf(value); + addArgument(this.index); // hack for compatibility + } else if (name.equals("property")) { // NON-NLS: the attribute name + this.property = value; + } else if (name.equals("method")) { // NON-NLS: the attribute name + this.method = value; + } else { + super.addAttribute(name, value); + } + } + + /** + * Calculates the value of this element + * if the field attribute or the idref attribute is set. + */ + @Override + public final void startElement() { + if ((this.field != null) || (this.idref != null)) { + getValueObject(); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element can be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return true; // hack for compatibility + } + + /** + * Creates the value of this element. + * + * @param type the base class + * @param args the array of arguments + * @return the value of this element + * @throws Exception if calculation is failed + */ + @Override + protected final ValueObject getValueObject(Class type, Object[] args) throws Exception { + if (this.field != null) { + return ValueObjectImpl.create(FieldElementHandler.getFieldValue(getContextBean(), this.field)); + } + if (this.idref != null) { + return ValueObjectImpl.create(getVariable(this.idref)); + } + Object bean = getContextBean(); + String name; + if (this.index != null) { + name = (args.length == 2) + ? PropertyElementHandler.SETTER + : PropertyElementHandler.GETTER; + } else if (this.property != null) { + name = (args.length == 1) + ? PropertyElementHandler.SETTER + : PropertyElementHandler.GETTER; + + if (0 < this.property.length()) { + name += this.property.substring(0, 1).toUpperCase(ENGLISH) + this.property.substring(1); + } + } else { + name = (this.method != null) && (0 < this.method.length()) + ? this.method + : "new"; // NON-NLS: the constructor marker + } + Expression expression = new Expression(bean, name, args); + return ValueObjectImpl.create(expression.getValue()); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java new file mode 100644 index 00000000000..dcc55062945 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/PropertyElementHandler.java @@ -0,0 +1,287 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +import com.sun.beans.finder.MethodFinder; + +import java.beans.IndexedPropertyDescriptor; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class is intended to handle <property> element. + * This element simplifies access to the properties. + * If the {@code index} attribute is specified + * this element uses additional {@code int} parameter. + * If the {@code name} attribute is not specified + * this element uses method "get" as getter + * and method "set" as setter. + * This element defines getter if it contains no argument. + * It returns the value of the property in this case. + * For example:
+ * <property name="object" index="10"/>
+ * is shortcut to
+ * <method name="getObject">
+ *     <int>10</int>
+ * </method>
+ * which is equivalent to {@code getObject(10)} in Java code. + * This element defines setter if it contains one argument. + * It does not return the value of the property in this case. + * For example:
+ * <property><int>0</int></property>
+ * is shortcut to
+ * <method name="set">
+ *     <int>0</int>
+ * </method>
+ * which is equivalent to {@code set(0)} in Java code. + *

The following atributes are supported: + *

+ *
name + *
the property name + *
index + *
the property index + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class PropertyElementHandler extends AccessorElementHandler { + static final String GETTER = "get"; // NON-NLS: the getter prefix + static final String SETTER = "set"; // NON-NLS: the setter prefix + + private Integer index; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
name + *
the property name + *
index + *
the property index + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("index")) { // NON-NLS: the attribute name + this.index = Integer.valueOf(value); + } else { + super.addAttribute(name, value); + } + } + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // non-static accessor cannot be used an argument + } + + /** + * Returns the value of the property with specified {@code name}. + * + * @param name the name of the property + * @return the value of the specified property + */ + @Override + protected Object getValue(String name) { + try { + return getPropertyValue(getContextBean(), name, this.index); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + return null; + } + + /** + * Sets the new value for the property with specified {@code name}. + * + * @param name the name of the property + * @param value the new value for the specified property + */ + @Override + protected void setValue(String name, Object value) { + try { + setPropertyValue(getContextBean(), name, this.index, value); + } + catch (Exception exception) { + getOwner().handleException(exception); + } + } + + /** + * Performs the search of the getter for the property + * with specified {@code name} in specified class + * and returns value of the property. + * + * @param bean the context bean that contains property + * @param name the name of the property + * @param index the index of the indexed property + * @return the value of the property + * @throws IllegalAccessException if the property is not accesible + * @throws IntrospectionException if the bean introspection is failed + * @throws InvocationTargetException if the getter cannot be invoked + * @throws NoSuchMethodException if the getter is not found + */ + private static Object getPropertyValue(Object bean, String name, Integer index) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException { + Class type = bean.getClass(); + if (index == null) { + return findGetter(type, name).invoke(bean); + } else if (type.isArray() && (name == null)) { + return Array.get(bean, index); + } else { + return findGetter(type, name, int.class).invoke(bean, index); + } + } + + /** + * Performs the search of the setter for the property + * with specified {@code name} in specified class + * and updates value of the property. + * + * @param bean the context bean that contains property + * @param name the name of the property + * @param index the index of the indexed property + * @param value the new value for the property + * @throws IllegalAccessException if the property is not accesible + * @throws IntrospectionException if the bean introspection is failed + * @throws InvocationTargetException if the setter cannot be invoked + * @throws NoSuchMethodException if the setter is not found + */ + private static void setPropertyValue(Object bean, String name, Integer index, Object value) throws IllegalAccessException, IntrospectionException, InvocationTargetException, NoSuchMethodException { + Class type = bean.getClass(); + Class param = (value != null) + ? value.getClass() + : null; + + if (index == null) { + findSetter(type, name, param).invoke(bean, value); + } else if (type.isArray() && (name == null)) { + Array.set(bean, index, value); + } else { + findSetter(type, name, int.class, param).invoke(bean, index, value); + } + } + + /** + * Performs the search of the getter for the property + * with specified {@code name} in specified class. + * + * @param type the class that contains method + * @param name the name of the property + * @param args the method arguments + * @return method object that represents found getter + * @throws IntrospectionException if the bean introspection is failed + * @throws NoSuchMethodException if method is not found + */ + private static Method findGetter(Class type, String name, Class...args) throws IntrospectionException, NoSuchMethodException { + if (name == null) { + return MethodFinder.findInstanceMethod(type, GETTER, args); + } + PropertyDescriptor pd = getProperty(type, name); + if (args.length == 0) { + Method method = pd.getReadMethod(); + if (method != null) { + return method; + } + } else if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + Method method = ipd.getIndexedReadMethod(); + if (method != null) { + return method; + } + } + throw new IntrospectionException("Could not find getter for the " + name + " property"); + } + + /** + * Performs the search of the setter for the property + * with specified {@code name} in specified class. + * + * @param type the class that contains method + * @param name the name of the property + * @param args the method arguments + * @return method object that represents found setter + * @throws IntrospectionException if the bean introspection is failed + * @throws NoSuchMethodException if method is not found + */ + private static Method findSetter(Class type, String name, Class...args) throws IntrospectionException, NoSuchMethodException { + if (name == null) { + return MethodFinder.findInstanceMethod(type, SETTER, args); + } + PropertyDescriptor pd = getProperty(type, name); + if (args.length == 1) { + Method method = pd.getWriteMethod(); + if (method != null) { + return method; + } + } else if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + Method method = ipd.getIndexedWriteMethod(); + if (method != null) { + return method; + } + } + throw new IntrospectionException("Could not find setter for the " + name + " property"); + } + + /** + * Performs the search of the descriptor for the property + * with specified {@code name} in specified class. + * + * @param type the class to introspect + * @param name the property name + * @return descriptor for the named property + * @throws IntrospectionException if property descriptor is not found + */ + private static PropertyDescriptor getProperty(Class type, String name) throws IntrospectionException { + for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) { + if (name.equals(pd.getName())) { + return pd; + } + } + throw new IntrospectionException("Could not find the " + name + " property descriptor"); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java new file mode 100644 index 00000000000..5f91e254424 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ShortElementHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <short> element. + * This element specifies {@code short} values. + * The class {@link Short} is used as wrapper for these values. + * The result value is created from text of the body of this element. + * The body parsing is described in the class {@link StringElementHandler}. + * For example:
+ * <short>200</short>
+ * is shortcut to
+ * <method name="decode" class="java.lang.Short">
+ *     <string>200</string>
+ * </method>
+ * which is equivalent to {@code Short.decode("200")} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ShortElementHandler extends StringElementHandler { + + /** + * Creates {@code short} value from + * the text of the body of this element. + * + * @param argument the text of the body + * @return evaluated {@code short} value + */ + @Override + public Object getValue(String argument) { + return Short.decode(argument); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java new file mode 100644 index 00000000000..6075f436aa0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/StringElementHandler.java @@ -0,0 +1,116 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <string> element. + * This element specifies {@link String} values. + * The result value is created from text of the body of this element. + * For example:
+ * <string>description</string>
+ * is equivalent to {@code "description"} in Java code. + * The value of inner element is calculated + * before adding to the string using {@link String#valueOf(Object)}. + * Note that all characters are used including whitespaces (' ', '\t', '\n', '\r'). + * So the value of the element
+ * <string><true></string>
+ * is not equal to the value of the element
+ * <string>
+ *     <true>
+ * </string>
+ *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public class StringElementHandler extends ElementHandler { + private StringBuilder sb = new StringBuilder(); + private ValueObject value = ValueObjectImpl.NULL; + + /** + * Adds the character that contained in this element. + * + * @param ch the character + */ + @Override + public final void addCharacter(char ch) { + if (this.sb == null) { + throw new IllegalStateException("Could not add chararcter to evaluated string element"); + } + this.sb.append(ch); + } + + /** + * Adds the string value of the argument to the string value of this element. + * + * @param argument the value of the element that contained in this one + */ + @Override + protected final void addArgument(Object argument) { + if (this.sb == null) { + throw new IllegalStateException("Could not add argument to evaluated string element"); + } + this.sb.append(argument); + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected final ValueObject getValueObject() { + if (this.sb != null) { + try { + this.value = ValueObjectImpl.create(getValue(this.sb.toString())); + } + catch (RuntimeException exception) { + getOwner().handleException(exception); + } + finally { + this.sb = null; + } + } + return this.value; + } + + /** + * Returns the text of the body of this element. + * This method evaluates value from text of the body, + * and should be overridden in those handlers + * that extend behavior of this element. + * + * @param argument the text of the body + * @return evaluated value + */ + protected Object getValue(String argument) { + return argument; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java new file mode 100644 index 00000000000..faf8904d4d0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/TrueElementHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <true> element. + * This element specifies {@code true} value. + * It should not contain body or inner elements. + * For example:
+ * <true/>
+ * is equivalent to {@code true} in Java code. + *

The following atribute is supported: + *

+ *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class TrueElementHandler extends NullElementHandler { + + /** + * Returns {@code Boolean.TRUE} + * as a value of <true> element. + * + * @return {@code Boolean.TRUE} by default + */ + @Override + public Object getValue() { + return Boolean.TRUE; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java b/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java new file mode 100644 index 00000000000..04f28278e34 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ValueObject.java @@ -0,0 +1,50 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This interface represents the result of method execution. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public interface ValueObject { + + /** + * Returns the result of method execution. + * + * @return the result of method execution + */ + Object getValue(); + + /** + * Returns {@code void} state of this value object. + * + * @return {@code true} if value can be ignored, + * {@code false} otherwise + */ + boolean isVoid(); +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java b/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java new file mode 100644 index 00000000000..cb891fe6c61 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/ValueObjectImpl.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This utility class provides {@code static} method + * to create the object that contains the result of method execution. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class ValueObjectImpl implements ValueObject { + static final ValueObject NULL = new ValueObjectImpl(null); + static final ValueObject VOID = new ValueObjectImpl(); + + /** + * Returns the object that describes returning value. + * + * @param value the result of method execution + * @return the object that describes value + */ + static ValueObject create(Object value) { + return (value != null) + ? new ValueObjectImpl(value) + : NULL; + } + + private Object value; + private boolean isVoid; + + /** + * Creates the object that describes returning void value. + */ + private ValueObjectImpl() { + this.isVoid = true; + } + + /** + * Creates the object that describes returning non-void value. + * + * @param value the result of method execution + */ + private ValueObjectImpl(Object value) { + this.value = value; + } + + /** + * Returns the result of method execution. + * + * @return the result of method execution + */ + public Object getValue() { + return this.value; + } + + /** + * Returns {@code void} state of this value object. + * + * @return {@code true} if value should be ignored, + * {@code false} otherwise + */ + public boolean isVoid() { + return this.isVoid; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java new file mode 100644 index 00000000000..d948c18e538 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/VarElementHandler.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <var> element. + * This element retrieves the value of specified variable. + * For example:
+ * <var id="id1" idref="id2"/>
+ * is equivalent to {@code id1 = id2} in Java code. + *

The following atributes are supported: + *

+ *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class VarElementHandler extends ElementHandler { + private ValueObject value; + + /** + * Parses attributes of the element. + * The following atributes are supported: + *
+ *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @param name the attribute name + * @param value the attribute value + */ + @Override + public void addAttribute(String name, String value) { + if (name.equals("idref")) { // NON-NLS: the attribute name + this.value = ValueObjectImpl.create(getVariable(value)); + } else { + super.addAttribute(name, value); + } + } + + /** + * Returns the value of this element. + * + * @return the value of this element + */ + @Override + protected ValueObject getValueObject() { + if (this.value == null) { + throw new IllegalArgumentException("Variable name is not set"); + } + return this.value; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java b/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java new file mode 100644 index 00000000000..44726a0f7a1 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/decoder/VoidElementHandler.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.decoder; + +/** + * This class is intended to handle <void> element. + * This element looks like <object> element, + * but its value is not used as an argument for element + * that contains this one. + *

The following atributes are supported: + *

+ *
class + *
the type is used for static methods and fields + *
method + *
the method name + *
property + *
the property name + *
index + *
the property index + *
field + *
the field name + *
idref + *
the identifier to refer to the variable + *
id + *
the identifier of the variable that is intended to store the result + *
+ * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class VoidElementHandler extends ObjectElementHandler { + + /** + * Tests whether the value of this element can be used + * as an argument of the element that contained in this one. + * + * @return {@code true} if the value of this element should be used + * as an argument of the element that contained in this one, + * {@code false} otherwise + */ + @Override + protected boolean isArgument() { + return false; // hack for compatibility + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java new file mode 100644 index 00000000000..396d6cbf8f8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/AbstractFinder.java @@ -0,0 +1,213 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.util.HashMap; +import java.util.Map; + +/** + * This abstract class provides functionality + * to find a public method or constructor + * with specified parameter types. + * It supports a variable number of parameters. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +abstract class AbstractFinder { + private final Class[] args; + + /** + * Creates finder for array of classes of arguments. + * If a particular element of array equals {@code null}, + * than the appropriate pair of classes + * does not take into consideration. + * + * @param args array of classes of arguments + */ + protected AbstractFinder(Class[] args) { + this.args = args; + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the method + * Returns an empty array if the method takes no parameters. + * + * @param method the object that represents method + * @return the parameter types of the method + */ + protected abstract Class[] getParameters(T method); + + /** + * Returns {@code true} if and only if the method + * was declared to take a variable number of arguments. + * + * @param method the object that represents method + * @return {@code true} if the method was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + protected abstract boolean isVarArgs(T method); + + /** + * Checks validness of the method. + * At least the valid method should be public. + * + * @param method the object that represents method + * @return {@code true} if the method is valid, + * {@code false} otherwise + */ + protected abstract boolean isValid(T method); + + /** + * Performs a search in the {@code methods} array. + * The one method is selected from the array of the valid methods. + * The list of parameters of the selected method shows + * the best correlation with the list of arguments + * specified at class initialization. + * If more than one method is both accessible and applicable + * to a method invocation, it is necessary to choose one + * to provide the descriptor for the run-time method dispatch. + * The most specific method should be chosen. + * + * @param methods the array of methods to search within + * @return the object that represents found method + * @throws NoSuchMethodException if no method was found or several + * methods meet the search criteria + * @see #isAssignable + */ + final T find(T[] methods) throws NoSuchMethodException { + Map[]> map = new HashMap[]>(); + + T oldMethod = null; + Class[] oldParams = null; + boolean ambiguous = false; + + for (T newMethod : methods) { + if (isValid(newMethod)) { + Class[] newParams = getParameters(newMethod); + if (newParams.length == this.args.length) { + PrimitiveWrapperMap.replacePrimitivesWithWrappers(newParams); + if (isAssignable(newParams, this.args)) { + if (oldMethod == null) { + oldMethod = newMethod; + oldParams = newParams; + } else { + boolean useNew = isAssignable(oldParams, newParams); + boolean useOld = isAssignable(newParams, oldParams); + + if (useOld == useNew) { + ambiguous = true; + } else if (useNew) { + oldMethod = newMethod; + oldParams = newParams; + ambiguous = false; + } + } + } + } + if (isVarArgs(newMethod)) { + int length = newParams.length - 1; + if (length <= this.args.length) { + Class[] array = new Class[this.args.length]; + System.arraycopy(newParams, 0, array, 0, length); + if (length < this.args.length) { + Class type = newParams[length].getComponentType(); + if (type.isPrimitive()) { + type = PrimitiveWrapperMap.getType(type.getName()); + } + for (int i = length; i < this.args.length; i++) { + array[i] = type; + } + } + map.put(newMethod, array); + } + } + } + } + for (T newMethod : methods) { + Class[] newParams = map.get(newMethod); + if (newParams != null) { + if (isAssignable(newParams, this.args)) { + if (oldMethod == null) { + oldMethod = newMethod; + oldParams = newParams; + } else { + boolean useNew = isAssignable(oldParams, newParams); + boolean useOld = isAssignable(newParams, oldParams); + + if (useOld == useNew) { + if (oldParams == map.get(oldMethod)) { + ambiguous = true; + } + } else if (useNew) { + oldMethod = newMethod; + oldParams = newParams; + ambiguous = false; + } + } + } + } + } + + if (ambiguous) { + throw new NoSuchMethodException("Ambiguous methods are found"); + } + if (oldMethod == null) { + throw new NoSuchMethodException("Method is not found"); + } + return oldMethod; + } + + /** + * Determines if every class in {@code min} array is either the same as, + * or is a superclass of, the corresponding class in {@code max} array. + * The length of every array must equal the number of arguments. + * This comparison is performed in the {@link #find} method + * before the first call of the isAssignable method. + * If an argument equals {@code null} + * the appropriate pair of classes does not take into consideration. + * + * @param min the array of classes to be checked + * @param max the array of classes that is used to check + * @return {@code true} if all classes in {@code min} array + * are assignable from corresponding classes in {@code max} array, + * {@code false} otherwise + * + * @see Class#isAssignableFrom + */ + private boolean isAssignable(Class[] min, Class[] max) { + for (int i = 0; i < this.args.length; i++) { + if (null != this.args[i]) { + if (!min[i].isAssignableFrom(max[i])) { + return false; + } + } + } + return true; + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java b/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java index 79b77415653..01a72fa5809 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java +++ b/jdk/src/share/classes/com/sun/beans/finder/ClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package com.sun.beans.finder; /** - * This is utility class that provides static methods + * This is utility class that provides {@code static} methods * to find a class with the specified name using the specified class loader. * * @since 1.7 @@ -33,137 +33,138 @@ package com.sun.beans.finder; * @author Sergey A. Malenkov */ public final class ClassFinder { + /** - * Returns the Class object associated + * Returns the {@code Class} object associated * with the class or interface with the given string name, * using the default class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). * * @param name fully qualified name of the desired class * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see Class#forName(String) * @see Class#forName(String,boolean,ClassLoader) * @see ClassLoader#getSystemClassLoader() * @see Thread#getContextClassLoader() */ - public static Class findClass( String name ) throws ClassNotFoundException { + public static Class findClass(String name) throws ClassNotFoundException { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if ( loader == null ) { + if (loader == null) { // can be null in IE (see 6204697) loader = ClassLoader.getSystemClassLoader(); } - if ( loader != null ) { - return Class.forName( name, false, loader ); + if (loader != null) { + return Class.forName(name, false, loader); } - } catch ( ClassNotFoundException exception ) { + } catch (ClassNotFoundException exception) { // use current class loader instead - } catch ( SecurityException exception ) { + } catch (SecurityException exception) { // use current class loader instead } - return Class.forName( name ); + return Class.forName(name); } /** - * Returns the Class object associated with + * Returns the {@code Class} object associated with * the class or interface with the given string name, * using the given class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

- * If the parameter loader is null, + * If the parameter {@code loader} is null, * the class is loaded through the default class loader. * * @param name fully qualified name of the desired class * @param loader class loader from which the class must be loaded * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #findClass(String,ClassLoader) * @see Class#forName(String,boolean,ClassLoader) */ - public static Class findClass( String name, ClassLoader loader ) throws ClassNotFoundException { - if ( loader != null ) { + public static Class findClass(String name, ClassLoader loader) throws ClassNotFoundException { + if (loader != null) { try { - return Class.forName( name, false, loader ); - } catch ( ClassNotFoundException exception ) { + return Class.forName(name, false, loader); + } catch (ClassNotFoundException exception) { // use default class loader instead - } catch ( SecurityException exception ) { + } catch (SecurityException exception) { // use default class loader instead } } - return findClass( name ); + return findClass(name); } /** - * Returns the Class object associated + * Returns the {@code Class} object associated * with the class or interface with the given string name, * using the default class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

* This method can be used to obtain - * any of the Class objects - * representing void or primitive Java types: - * char, byte, short, - * int, long, float, - * double and boolean. + * any of the {@code Class} objects + * representing {@code void} or primitive Java types: + * {@code char}, {@code byte}, {@code short}, + * {@code int}, {@code long}, {@code float}, + * {@code double} and {@code boolean}. * * @param name fully qualified name of the desired class * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #resolveClass(String,ClassLoader) */ - public static Class resolveClass( String name ) throws ClassNotFoundException { - return resolveClass( name, null ); + public static Class resolveClass(String name) throws ClassNotFoundException { + return resolveClass(name, null); } /** - * Returns the Class object associated with + * Returns the {@code Class} object associated with * the class or interface with the given string name, * using the given class loader. *

- * The name can denote an array class + * The {@code name} can denote an array class * (see {@link Class#getName} for details). *

- * If the parameter loader is null, + * If the parameter {@code loader} is null, * the class is loaded through the default class loader. *

* This method can be used to obtain - * any of the Class objects - * representing void or primitive Java types: - * char, byte, short, - * int, long, float, - * double and boolean. + * any of the {@code Class} objects + * representing {@code void} or primitive Java types: + * {@code char}, {@code byte}, {@code short}, + * {@code int}, {@code long}, {@code float}, + * {@code double} and {@code boolean}. * * @param name fully qualified name of the desired class * @param loader class loader from which the class must be loaded * @return class object representing the desired class * - * @exception ClassNotFoundException if the class cannot be located - * by the specified class loader + * @throws ClassNotFoundException if the class cannot be located + * by the specified class loader * * @see #findClass(String,ClassLoader) * @see PrimitiveTypeMap#getType(String) */ - public static Class resolveClass( String name, ClassLoader loader ) throws ClassNotFoundException { - Class type = PrimitiveTypeMap.getType( name ); - return ( type == null ) - ? findClass( name, loader ) + public static Class resolveClass(String name, ClassLoader loader) throws ClassNotFoundException { + Class type = PrimitiveTypeMap.getType(name); + return (type == null) + ? findClass(name, loader) : type; } diff --git a/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java new file mode 100644 index 00000000000..e7bb33421fe --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/ConstructorFinder.java @@ -0,0 +1,127 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.WeakCache; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +/** + * This utility class provides {@code static} methods + * to find a public constructor with specified parameter types + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class ConstructorFinder extends AbstractFinder> { + private static final WeakCache> CACHE = new WeakCache>(); + + /** + * Finds public constructor + * that is declared in public class. + * + * @param type the class that can have constructor + * @param args parameter types that is used to find constructor + * @return object that represents found constructor + * @throws NoSuchMethodException if constructor could not be found + * or some constructors are found + */ + public static Constructor findConstructor(Class type, Class...args) throws NoSuchMethodException { + if (type.isPrimitive()) { + throw new NoSuchMethodException("Primitive wrapper does not contain constructors"); + } + if (type.isInterface()) { + throw new NoSuchMethodException("Interface does not contain constructors"); + } + if (Modifier.isAbstract(type.getModifiers())) { + throw new NoSuchMethodException("Abstract class cannot be instantiated"); + } + if (!Modifier.isPublic(type.getModifiers())) { + throw new NoSuchMethodException("Class is not accessible"); + } + PrimitiveWrapperMap.replacePrimitivesWithWrappers(args); + Signature signature = new Signature(type, args); + + Constructor constructor = CACHE.get(signature); + if (constructor != null) { + return constructor; + } + constructor = new ConstructorFinder(args).find(type.getConstructors()); + CACHE.put(signature, constructor); + return constructor; + } + + /** + * Creates constructor finder with specified array of parameter types. + * + * @param args the array of parameter types + */ + private ConstructorFinder(Class[] args) { + super(args); + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the constructor + * Returns an empty array if the constructor takes no parameters. + * + * @param constructor the object that represents constructor + * @return the parameter types of the constructor + */ + @Override + protected Class[] getParameters(Constructor constructor) { + return constructor.getParameterTypes(); + } + + /** + * Returns {@code true} if and only if the constructor + * was declared to take a variable number of arguments. + * + * @param constructor the object that represents constructor + * @return {@code true} if the constructor was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + @Override + protected boolean isVarArgs(Constructor constructor) { + return constructor.isVarArgs(); + } + + /** + * Checks validness of the constructor. + * The valid constructor should be public. + * + * @param constructor the object that represents constructor + * @return {@code true} if the constructor is valid, + * {@code false} otherwise + */ + @Override + protected boolean isValid(Constructor constructor) { + return Modifier.isPublic(constructor.getModifiers()); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java b/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java new file mode 100644 index 00000000000..cb17d02417d --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/FieldFinder.java @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * This utility class provides {@code static} methods + * to find a public field with specified name + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class FieldFinder { + + /** + * Finds public field (static or non-static) + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findField(Class type, String name) throws NoSuchFieldException { + if (name == null) { + throw new IllegalArgumentException("Field name is not set"); + } + Field field = type.getField(name); + if (!Modifier.isPublic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not public"); + } + if (!Modifier.isPublic(field.getDeclaringClass().getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not accessible"); + } + return field; + } + + /** + * Finds public non-static field + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findInstanceField(Class type, String name) throws NoSuchFieldException { + Field field = findField(type, name); + if (Modifier.isStatic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is static"); + } + return field; + } + + /** + * Finds public static field + * that is declared in public class. + * + * @param type the class that can have field + * @param name the name of field to find + * @return object that represents found field + * @throws NoSuchFieldException if field is not found + * @see Class#getField + */ + public static Field findStaticField(Class type, String name) throws NoSuchFieldException { + Field field = findField(type, name); + if (!Modifier.isStatic(field.getModifiers())) { + throw new NoSuchFieldException("Field '" + name + "' is not static"); + } + return field; + } + + /** + * Disable instantiation. + */ + private FieldFinder() { + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java new file mode 100644 index 00000000000..9ccb4c4397f --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java @@ -0,0 +1,231 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import com.sun.beans.TypeResolver; +import com.sun.beans.WeakCache; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +/** + * This utility class provides {@code static} methods + * to find a public method with specified name and parameter types + * in specified class. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class MethodFinder extends AbstractFinder { + private static final WeakCache CACHE = new WeakCache(); + + /** + * Finds public method (static or non-static) + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findMethod(Class type, String name, Class...args) throws NoSuchMethodException { + if (name == null) { + throw new IllegalArgumentException("Method name is not set"); + } + PrimitiveWrapperMap.replacePrimitivesWithWrappers(args); + Signature signature = new Signature(type, name, args); + + Method method = CACHE.get(signature); + if (method != null) { + return method; + } + method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); + CACHE.put(signature, method); + return method; + } + + /** + * Finds public non-static method + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findInstanceMethod(Class type, String name, Class... args) throws NoSuchMethodException { + Method method = findMethod(type, name, args); + if (Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + name + "' is static"); + } + return method; + } + + /** + * Finds public static method + * that is accessible from public class. + * + * @param type the class that can have method + * @param name the name of method to find + * @param args parameter types that is used to find method + * @return object that represents found method + * @throws NoSuchMethodException if method could not be found + * or some methods are found + */ + public static Method findStaticMethod(Class type, String name, Class...args) throws NoSuchMethodException { + Method method = findMethod(type, name, args); + if (!Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + name + "' is not static"); + } + return method; + } + + /** + * Finds method that is accessible from public class or interface through class hierarchy. + * + * @param method object that represents found method + * @return object that represents accessible method + * @throws NoSuchMethodException if method is not accessible or is not found + * in specified superclass or interface + */ + private static Method findAccessibleMethod(Method method) throws NoSuchMethodException { + Class type = method.getDeclaringClass(); + if (Modifier.isPublic(type.getModifiers())) { + return method; + } + if (Modifier.isStatic(method.getModifiers())) { + throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible"); + } + for (Type generic : type.getGenericInterfaces()) { + try { + return findAccessibleMethod(method, generic); + } + catch (NoSuchMethodException exception) { + // try to find in superclass or another interface + } + } + return findAccessibleMethod(method, type.getGenericSuperclass()); + } + + /** + * Finds method that accessible from specified class. + * + * @param method object that represents found method + * @param generic generic type that is used to find accessible method + * @return object that represents accessible method + * @throws NoSuchMethodException if method is not accessible or is not found + * in specified superclass or interface + */ + private static Method findAccessibleMethod(Method method, Type generic) throws NoSuchMethodException { + String name = method.getName(); + Class[] params = method.getParameterTypes(); + if (generic instanceof Class) { + Class type = (Class) generic; + return findAccessibleMethod(type.getMethod(name, params)); + } + if (generic instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) generic; + Class type = (Class) pt.getRawType(); + for (Method m : type.getMethods()) { + if (m.getName().equals(name)) { + Class[] pts = m.getParameterTypes(); + if (pts.length == params.length) { + if (Arrays.equals(params, pts)) { + return findAccessibleMethod(m); + } + Type[] gpts = m.getGenericParameterTypes(); + if (Arrays.equals(params, TypeResolver.erase(TypeResolver.resolve(pt, gpts)))) { + return findAccessibleMethod(m); + } + } + } + } + } + throw new NoSuchMethodException("Method '" + name + "' is not accessible"); + } + + + private final String name; + + /** + * Creates method finder with specified array of parameter types. + * + * @param name the name of method to find + * @param args the array of parameter types + */ + private MethodFinder(String name, Class[] args) { + super(args); + this.name = name; + } + + /** + * Returns an array of {@code Class} objects + * that represent the formal parameter types of the method + * Returns an empty array if the method takes no parameters. + * + * @param method the object that represents method + * @return the parameter types of the method + */ + @Override + protected Class[] getParameters(Method method) { + return method.getParameterTypes(); + } + + /** + * Returns {@code true} if and only if the method + * was declared to take a variable number of arguments. + * + * @param method the object that represents method + * @return {@code true} if the method was declared + * to take a variable number of arguments; + * {@code false} otherwise + */ + @Override + protected boolean isVarArgs(Method method) { + return method.isVarArgs(); + } + + /** + * Checks validness of the method. + * The valid method should be public and + * should have the specified name. + * + * @param method the object that represents method + * @return {@code true} if the method is valid, + * {@code false} otherwise + */ + @Override + protected boolean isValid(Method method) { + return Modifier.isPublic(method.getModifiers()) && method.getName().equals(this.name); + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java index 0bdb09e5be1..36a552b906c 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java +++ b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveTypeMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,29 +36,30 @@ import java.util.Map; * @author Sergey A. Malenkov */ final class PrimitiveTypeMap { + /** * Returns primitive type class by its name. * * @param name the name of primitive type * @return found primitive type class, - * or null if not found + * or {@code null} if not found */ - static Class getType( String name ) { - return map.get( name ); + static Class getType(String name) { + return map.get(name); } - private static final Map map = new HashMap( 9 ); + private static final Map> map = new HashMap>(9); static { - map.put( boolean.class.getName(), boolean.class ); - map.put( char.class.getName(), char.class ); - map.put( byte.class.getName(), byte.class ); - map.put( short.class.getName(), short.class ); - map.put( int.class.getName(), int.class ); - map.put( long.class.getName(), long.class ); - map.put( float.class.getName(), float.class ); - map.put( double.class.getName(), double.class ); - map.put( void.class.getName(), void.class ); + map.put(boolean.class.getName(), boolean.class); + map.put(char.class.getName(), char.class); + map.put(byte.class.getName(), byte.class); + map.put(short.class.getName(), short.class); + map.put(int.class.getName(), int.class); + map.put(long.class.getName(), long.class); + map.put(float.class.getName(), float.class); + map.put(double.class.getName(), double.class); + map.put(void.class.getName(), void.class); } /** diff --git a/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java new file mode 100644 index 00000000000..f39b3ea3df0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/PrimitiveWrapperMap.java @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +import java.util.HashMap; +import java.util.Map; + +/** + * This utility class associates + * name of primitive type with appropriate wrapper. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +public final class PrimitiveWrapperMap { + + /** + * Replaces all primitive types in specified array with wrappers. + * + * @param types array of classes where all primitive types + * will be replaced by appropriate wrappers + */ + static void replacePrimitivesWithWrappers(Class[] types) { + for (int i = 0; i < types.length; i++) { + if (types[i] != null) { + if (types[i].isPrimitive()) { + types[i] = getType(types[i].getName()); + } + } + } + } + + /** + * Returns wrapper for primitive type by its name. + * + * @param name the name of primitive type + * @return found wrapper for primitive type, + * or {@code null} if not found + */ + public static Class getType(String name) { + return map.get(name); + } + + private static final Map> map = new HashMap>(9); + + static { + map.put(Boolean.TYPE.getName(), Boolean.class); + map.put(Character.TYPE.getName(), Character.class); + map.put(Byte.TYPE.getName(), Byte.class); + map.put(Short.TYPE.getName(), Short.class); + map.put(Integer.TYPE.getName(), Integer.class); + map.put(Long.TYPE.getName(), Long.class); + map.put(Float.TYPE.getName(), Float.class); + map.put(Double.TYPE.getName(), Double.class); + map.put(Void.TYPE.getName(), Void.class); + } + + /** + * Disable instantiation. + */ + private PrimitiveWrapperMap() { + } +} diff --git a/jdk/src/share/classes/com/sun/beans/finder/Signature.java b/jdk/src/share/classes/com/sun/beans/finder/Signature.java new file mode 100644 index 00000000000..8c09e11f4b4 --- /dev/null +++ b/jdk/src/share/classes/com/sun/beans/finder/Signature.java @@ -0,0 +1,169 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans.finder; + +/** + * This class is designed to be a key of a cache + * of constructors or methods. + * + * @since 1.7 + * + * @author Sergey A. Malenkov + */ +final class Signature { + private final Class type; + private final String name; + private final Class[] args; + + private volatile int code; + + /** + * Constructs signature for constructor. + * + * @param type the class that contains constructor + * @param args the types of constructor's parameters + */ + Signature(Class type, Class[] args) { + this(type, null, args); + } + + /** + * Constructs signature for method. + * + * @param type the class that contains method + * @param name the name of the method + * @param args the types of method's parameters + */ + Signature(Class type, String name, Class[] args) { + this.type = type; + this.name = name; + this.args = args; + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param object the reference object with which to compare + * @return {@code true} if this object is the same as the + * {@code object} argument, {@code false} otherwise + * @see #hashCode() + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Signature) { + Signature signature = (Signature) object; + return isEqual(signature.type, this.type) + && isEqual(signature.name, this.name) + && isEqual(signature.args, this.args); + } + return false; + } + + /** + * Indicates whether some object is "equal to" another one. + * This method supports {@code null} values. + * + * @param obj1 the first reference object that will compared + * @param obj2 the second reference object that will compared + * @return {@code true} if first object is the same as the second object, + * {@code false} otherwise + */ + private static boolean isEqual(Object obj1, Object obj2) { + return (obj1 == null) + ? obj2 == null + : obj1.equals(obj2); + } + + /** + * Indicates whether some array is "equal to" another one. + * This method supports {@code null} values. + * + * @param args1 the first reference array that will compared + * @param args2 the second reference array that will compared + * @return {@code true} if first array is the same as the second array, + * {@code false} otherwise + */ + private static boolean isEqual(Class[] args1, Class[] args2) { + if ((args1 == null) || (args2 == null)) { + return args1 == args2; + } + if (args1.length != args2.length) { + return false; + } + for (int i = 0; i < args1.length; i++) { + if (!isEqual(args1[i], args2[i])) { + return false; + } + } + return true; + } + + /** + * Returns a hash code value for the object. + * This method is supported for the benefit of hashtables + * such as {@link java.util.HashMap} or {@link java.util.HashSet}. + * Hash code computed using algorithm + * suggested in Effective Java, Item 8. + * + * @return a hash code value for this object + * @see #equals(Object) + */ + @Override + public int hashCode() { + if (this.code == 0) { + int code = 17; + code = addHashCode(code, this.type); + code = addHashCode(code, this.name); + + if (this.args != null) { + for (Class arg : this.args) { + code = addHashCode(code, arg); + } + } + this.code = code; + } + return this.code; + } + + /** + * Adds hash code value if specified object. + * This is a part of the algorithm + * suggested in Effective Java, Item 8. + * + * @param code current hash code value + * @param object object that updates hash code value + * @return updated hash code value + * @see #hashCode() + */ + private static int addHashCode(int code, Object object) { + code *= 37; + return (object != null) + ? code + object.hashCode() + : code; + } +} diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java index c70d889f453..d54839f7e3c 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java @@ -799,9 +799,9 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements Graphics g = triangleImage.getGraphics(); g.setColor(new Color(0, 0, 0, 0)); g.fillRect(0, 0, a, a); - g.translate((int)(a / 2), 0); + g.translate(a / 2, 0); paintTriangle(g, triangleSize, getColor()); - g.translate((int)(-a / 2), 0); + g.translate(-a / 2, 0); g.dispose(); g = wheelImage.getGraphics(); @@ -897,7 +897,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements return false; } // Rotate to origin and and verify x is valid. - int triangleSize = (int)innerR * 3 / 2; + int triangleSize = innerR * 3 / 2; double x1 = Math.cos(angle) * x - Math.sin(angle) * y; double y1 = Math.sin(angle) * x + Math.cos(angle) * y; if (x1 < -(innerR / 2)) { @@ -960,7 +960,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements */ private void setSaturationAndBrightness(float s, float b) { int innerR = getTriangleCircumscribedRadius(); - int triangleSize = (int)innerR * 3 / 2; + int triangleSize = innerR * 3 / 2; double x = b * triangleSize; double maxY = x * Math.tan(Math.toRadians(30.0)); double y = 2 * maxY * s - maxY; @@ -1156,7 +1156,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements * @param x X location to get color for * @param y Y location to get color for * @param rad Radius from center of color wheel - * @param integer with red, green and blue components + * @return integer with red, green and blue components */ private int colorWheelLocationToRGB(int x, int y, double rad) { double angle = Math.acos((double)x / rad); @@ -1165,12 +1165,12 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements if (angle < PI_3) { if (y < 0) { // FFFF00 - FF0000 - rgb = 0xFF0000 | (int)Math.min(255, + rgb = 0xFF0000 | Math.min(255, (int)(255 * angle / PI_3)) << 8; } else { // FF0000 - FF00FF - rgb = 0xFF0000 | (int)Math.min(255, + rgb = 0xFF0000 | Math.min(255, (int)(255 * angle / PI_3)); } } @@ -1178,12 +1178,12 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements angle -= PI_3; if (y < 0) { // 00FF00 - FFFF00 - rgb = 0x00FF00 | (int)Math.max(0, 255 - + rgb = 0x00FF00 | Math.max(0, 255 - (int)(255 * angle / PI_3)) << 16; } else { // FF00FF - 0000FF - rgb = 0x0000FF | (int)Math.max(0, 255 - + rgb = 0x0000FF | Math.max(0, 255 - (int)(255 * angle / PI_3)) << 16; } } @@ -1191,12 +1191,12 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements angle -= 2 * PI_3; if (y < 0) { // 00FFFF - 00FF00 - rgb = 0x00FF00 | (int)Math.min(255, + rgb = 0x00FF00 | Math.min(255, (int)(255 * angle / PI_3)); } else { // 0000FF - 00FFFF - rgb = 0x0000FF | (int)Math.min(255, + rgb = 0x0000FF | Math.min(255, (int)(255 * angle / PI_3)) << 8; } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 95bf090b645..737e20c2243 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -112,7 +112,7 @@ class GTKEngine { } - private static HashMap regionToWidgetTypeMap; + private static HashMap regionToWidgetTypeMap; private ImageCache cache = new ImageCache(CACHE_SIZE); private int x0, y0, w0, h0; private Graphics graphics; @@ -178,7 +178,7 @@ class GTKEngine { Toolkit.getDefaultToolkit(); // Initialize regionToWidgetTypeMap - regionToWidgetTypeMap = new HashMap(50); + regionToWidgetTypeMap = new HashMap(50); regionToWidgetTypeMap.put(Region.ARROW_BUTTON, new WidgetType[] { WidgetType.SPINNER_ARROW_BUTTON, WidgetType.COMBO_BOX_ARROW_BUTTON, diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 8b786da73fb..acb944dfa56 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -148,7 +148,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { directoryList : fileList; Object[] files = list.getSelectedValues(); int len = files.length; - Vector result = new Vector(len + 1); + Vector result = new Vector(len + 1); // we return all selected file names for (int i = 0; i < len; i++) { @@ -263,13 +263,13 @@ class GTKFileChooserUI extends SynthFileChooserUI { ListSelectionModel sm = directoryList.getSelectionModel(); if (sm instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)sm).setAnchorSelectionIndex(0); + sm.setAnchorSelectionIndex(0); } fileList.clearSelection(); sm = fileList.getSelectionModel(); if (sm instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)sm).setAnchorSelectionIndex(0); + sm.setAnchorSelectionIndex(0); } File currentDirectory = getFileChooser().getCurrentDirectory(); @@ -425,16 +425,16 @@ class GTKFileChooserUI extends SynthFileChooserUI { setDirectorySelected(true); setDirectory(((File)objects[0])); } else { - ArrayList fList = new ArrayList(objects.length); - for (int i = 0; i < objects.length; i++) { - File f = (File)objects[i]; + ArrayList fList = new ArrayList(objects.length); + for (Object object : objects) { + File f = (File) object; if ((chooser.isFileSelectionEnabled() && f.isFile()) || (chooser.isDirectorySelectionEnabled() && f.isDirectory())) { fList.add(f); } } if (fList.size() > 0) { - files = (File[])fList.toArray(new File[fList.size()]); + files = fList.toArray(new File[fList.size()]); } setDirectorySelected(false); } @@ -671,9 +671,9 @@ class GTKFileChooserUI extends SynthFileChooserUI { pathFieldLabel.setLabelFor(fileNameTextField); - Set forwardTraversalKeys = fileNameTextField.getFocusTraversalKeys( + Set forwardTraversalKeys = fileNameTextField.getFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); - forwardTraversalKeys = new HashSet(forwardTraversalKeys); + forwardTraversalKeys = new HashSet(forwardTraversalKeys); forwardTraversalKeys.remove(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0)); fileNameTextField.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardTraversalKeys); @@ -895,10 +895,9 @@ class GTKFileChooserUI extends SynthFileChooserUI { private class GTKDirectoryModel extends BasicDirectoryModel { FileSystemView fsv; - private Comparator fileComparator = new Comparator() { - public int compare(Object o, Object o1) { - return fsv.getSystemDisplayName((File) o).compareTo - (fsv.getSystemDisplayName((File) o1)); + private Comparator fileComparator = new Comparator() { + public int compare(File o, File o1) { + return fsv.getSystemDisplayName(o).compareTo(fsv.getSystemDisplayName(o1)); } }; @@ -1074,7 +1073,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { * Data model for a type-face selection combo-box. */ protected class DirectoryComboBoxModel extends AbstractListModel implements ComboBoxModel { - Vector directories = new Vector(); + Vector directories = new Vector(); File selectedDirectory = null; JFileChooser chooser = getFileChooser(); FileSystemView fsv = chooser.getFileSystemView(); @@ -1216,7 +1215,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { ListSelectionModel sm = fileList.getSelectionModel(); if (sm instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)sm).setAnchorSelectionIndex(0); + sm.setAnchorSelectionIndex(0); } rescanCurrentDirectory(getFileChooser()); return; @@ -1352,8 +1351,8 @@ class GTKFileChooserUI extends SynthFileChooserUI { FileFilter currentFilter = getFileChooser().getFileFilter(); boolean found = false; if (currentFilter != null) { - for (int i = 0; i < filters.length; i++) { - if (filters[i] == currentFilter) { + for (FileFilter filter : filters) { + if (filter == currentFilter) { found = true; } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 6934aa213d1..23e4ee2eee5 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -1470,7 +1470,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { aaTextInfo = SwingUtilities2.AATextInfo.getAATextInfo(gtkAAFontSettingsCond); } - static ReferenceQueue queue = new ReferenceQueue(); + static ReferenceQueue queue = new ReferenceQueue(); private static void flushUnreferenced() { WeakPCL pcl; @@ -1480,12 +1480,12 @@ public class GTKLookAndFeel extends SynthLookAndFeel { } } - static class WeakPCL extends WeakReference implements + static class WeakPCL extends WeakReference implements PropertyChangeListener { private Toolkit kit; private String key; - WeakPCL(Object target, Toolkit kit, String key) { + WeakPCL(GTKLookAndFeel target, Toolkit kit, String key) { super(target, queue); this.kit = kit; this.key = key; @@ -1494,7 +1494,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { public String getKey() { return key; } public void propertyChange(final PropertyChangeEvent pce) { - final GTKLookAndFeel lnf = (GTKLookAndFeel)get(); + final GTKLookAndFeel lnf = get(); if (lnf == null || UIManager.getLookAndFeel() != lnf) { // The property was GC'ed, we're no longer interested in diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 780b01cf6d4..58d61dc909a 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -299,7 +299,7 @@ class GTKPainter extends SynthPainter { // Paint the default indicator GTKStyle style = (GTKStyle)context.getStyle(); if (defaultCapable && !toolButton) { - Insets defaultInsets = (Insets)style.getClassSpecificInsetsValue( + Insets defaultInsets = style.getClassSpecificInsetsValue( context, "default-border", GTKStyle.BUTTON_DEFAULT_BORDER_INSETS); diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java index a3eada90d84..d432bb088ba 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java @@ -124,7 +124,7 @@ class Metacity implements SynthConstants { } // Initialize constants - variables = new HashMap(); + variables = new HashMap(); NodeList nodes = xmlDoc.getElementsByTagName("constant"); int n = nodes.getLength(); for (int i = 0; i < n; i++) { @@ -144,14 +144,14 @@ class Metacity implements SynthConstants { } // Cache frame geometries - frameGeometries = new HashMap(); + frameGeometries = new HashMap>(); nodes = xmlDoc.getElementsByTagName("frame_geometry"); n = nodes.getLength(); for (int i = 0; i < n; i++) { Node node = nodes.item(i); String name = getStringAttr(node, "name"); if (name != null) { - HashMap gm = new HashMap(); + HashMap gm = new HashMap(); frameGeometries.put(name, gm); String parentGM = getStringAttr(node, "parent"); @@ -458,7 +458,7 @@ class Metacity implements SynthConstants { - private static class Privileged implements PrivilegedAction { + private static class Privileged implements PrivilegedAction { private static int GET_THEME_DIR = 0; private static int GET_USER_THEME = 1; private static int GET_IMAGE = 2; @@ -598,7 +598,7 @@ class Metacity implements SynthConstants { g2.setComposite(oldComp); } - private HashMap images = new HashMap(); + private HashMap images = new HashMap(); protected Image getImage(String key, Color c) { Image image = images.get(key+"-"+c.getRGB()); @@ -1530,8 +1530,8 @@ class Metacity implements SynthConstants { DocumentBuilderFactory.newInstance().newDocumentBuilder(); } InputStream inputStream = - (InputStream)AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public InputStream run() { try { return new BufferedInputStream(xmlFile.openStream()); } catch (IOException ex) { @@ -1551,7 +1551,7 @@ class Metacity implements SynthConstants { protected Node[] getNodesByName(Node parent, String name) { NodeList nodes = parent.getChildNodes(); // ElementNode int n = nodes.getLength(); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList(); for (int i=0; i < n; i++) { Node node = nodes.item(i); if (name.equals(node.getNodeName())) { @@ -1603,7 +1603,7 @@ class Metacity implements SynthConstants { String aValue = attrs[a * 2 + 1]; Node attr = nodeAttrs.getNamedItem(aName); if (attr == null || - aValue != null && !aValue.equals((String)attr.getNodeValue())) { + aValue != null && !aValue.equals(attr.getNodeValue())) { matches = false; break; } @@ -1642,7 +1642,7 @@ class Metacity implements SynthConstants { protected String getStringAttr(NamedNodeMap attrs, String name) { Node item = attrs.getNamedItem(name); - return (item != null) ? (String)item.getNodeValue() : null; + return (item != null) ? item.getNodeValue() : null; } protected boolean getBooleanAttr(Node node, String name, boolean fallback) { diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index f9f32f2ff73..57af97958dd 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -70,7 +70,6 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { private JTextField filenameTextField; private FilePane filePane; private WindowsPlacesBar placesBar; - private boolean useShellFolder; private JButton approveButton; private JButton cancelButton; @@ -210,10 +209,6 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { public ListSelectionListener createListSelectionListener() { return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser()); } - - public boolean usesShellFolder() { - return useShellFolder; - } } public void installComponents(JFileChooser fc) { @@ -625,15 +620,8 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { // Decide whether to use the ShellFolder class to populate shortcut // panel and combobox. JFileChooser fc = getFileChooser(); - Boolean prop = - (Boolean)fc.getClientProperty("FileChooser.useShellFolder"); - if (prop != null) { - useShellFolder = prop.booleanValue(); - } else { - useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView()); - } if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) >= 0) { - if (useShellFolder) { + if (FilePane.usesShellFolder(fc)) { if (placesBar == null && !UIManager.getBoolean("FileChooser.noPlacesBar")) { placesBar = new WindowsPlacesBar(fc, XPStyle.getXP() != null); fc.add(placesBar, BorderLayout.BEFORE_LINE_BEGINS); @@ -1149,6 +1137,8 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { return; } + boolean useShellFolder = FilePane.usesShellFolder(chooser); + directories.clear(); File[] baseFolders; diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index bb7842a0018..788fe9fec38 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -1554,10 +1554,10 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "Tree.selectionBackground", SelectionBackgroundColor, "Tree.expandedIcon", treeExpandedIcon, "Tree.collapsedIcon", treeCollapsedIcon, - "Tree.openIcon", new ActiveWindowsIcon("win.icon.shellIconBPP", "shell32Icon 5", - (Icon)table.get("Tree.openIcon")), - "Tree.closedIcon", new ActiveWindowsIcon("win.icon.shellIconBPP", "shell32Icon 4", - (Icon)table.get("Tree.closedIcon")), + "Tree.openIcon", new ActiveWindowsIcon("win.icon.shellIconBPP", + "shell32Icon 5", "icons/TreeOpen.gif"), + "Tree.closedIcon", new ActiveWindowsIcon("win.icon.shellIconBPP", + "shell32Icon 4", "icons/TreeClosed.gif"), "Tree.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { "ADD", "expand", @@ -2205,21 +2205,21 @@ public class WindowsLookAndFeel extends BasicLookAndFeel */ private class ActiveWindowsIcon implements UIDefaults.ActiveValue { private Icon icon; - private Icon fallback; private String nativeImageName; + private String fallbackName; private DesktopProperty desktopProperty; ActiveWindowsIcon(String desktopPropertyName, - String nativeImageName, Icon fallback) { + String nativeImageName, String fallbackName) { this.nativeImageName = nativeImageName; - this.fallback = fallback; + this.fallbackName = fallbackName; if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) < 0) { // This desktop property is needed to trigger reloading the icon. // It is kept in member variable to avoid GC. this.desktopProperty = new TriggerDesktopProperty(desktopPropertyName) { - protected void updateUI() { + @Override protected void updateUI() { icon = null; super.updateUI(); } @@ -2227,6 +2227,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel } } + @Override public Object createValue(UIDefaults table) { if (icon == null) { Image image = (Image)ShellFolder.get(nativeImageName); @@ -2234,8 +2235,11 @@ public class WindowsLookAndFeel extends BasicLookAndFeel icon = new ImageIconUIResource(image); } } - if (icon == null && fallback != null) { - icon = fallback; + if (icon == null && fallbackName != null) { + UIDefaults.LazyValue fallback = (UIDefaults.LazyValue) + SwingUtilities2.makeIcon(WindowsLookAndFeel.class, + BasicLookAndFeel.class, fallbackName); + icon = (Icon) fallback.createValue(table); } return icon; } diff --git a/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java index 5409ab0567b..70cb15e0a40 100644 --- a/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/jdk/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -75,13 +75,6 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice /** * This is the device handle returned from native code */ - /* - * $$rratta Solaris 64 bit holds pointer must be long - * - * $$mp 2003-08-07: - * 'id' is a really bad name. The variable should - * be called nativePointer or something similar. - */ protected long id = 0; @@ -586,7 +579,6 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice private ArrayList transmitters = new ArrayList(); private MidiOutDevice.MidiOutReceiver midiOutReceiver; - private MixerSynth.SynthReceiver mixerSynthReceiver; // how many transmitters must be present for optimized // handling @@ -621,22 +613,14 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice if (midiOutReceiver == oldR) { midiOutReceiver = null; } - if (mixerSynthReceiver == oldR) { - mixerSynthReceiver = null; - } if (newR != null) { if ((newR instanceof MidiOutDevice.MidiOutReceiver) && (midiOutReceiver == null)) { midiOutReceiver = ((MidiOutDevice.MidiOutReceiver) newR); } - if ((newR instanceof MixerSynth.SynthReceiver) - && (mixerSynthReceiver == null)) { - mixerSynthReceiver = ((MixerSynth.SynthReceiver) newR); - } } optimizedReceiverCount = - ((midiOutReceiver!=null)?1:0) - + ((mixerSynthReceiver!=null)?1:0); + ((midiOutReceiver!=null)?1:0); } // more potential for optimization here } @@ -670,10 +654,6 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice if (TRACE_TRANSMITTER) Printer.println("Sending packed message to MidiOutReceiver"); midiOutReceiver.sendPackedMidiMessage(packedMessage, timeStamp); } - if (mixerSynthReceiver != null) { - if (TRACE_TRANSMITTER) Printer.println("Sending packed message to MixerSynthReceiver"); - mixerSynthReceiver.sendPackedMidiMessage(packedMessage, timeStamp); - } } else { if (TRACE_TRANSMITTER) Printer.println("Sending packed message to "+size+" transmitter's receivers"); for (int i = 0; i < size; i++) { @@ -682,9 +662,6 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice if (optimizedReceiverCount > 0) { if (receiver instanceof MidiOutDevice.MidiOutReceiver) { ((MidiOutDevice.MidiOutReceiver) receiver).sendPackedMidiMessage(packedMessage, timeStamp); - } - else if (receiver instanceof MixerSynth.SynthReceiver) { - ((MixerSynth.SynthReceiver) receiver).sendPackedMidiMessage(packedMessage, timeStamp); } else { receiver.send(new FastShortMessage(packedMessage), timeStamp); } @@ -739,10 +716,6 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to MidiOutReceiver"); midiOutReceiver.send(message, timeStamp); } - if (mixerSynthReceiver != null) { - if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to MixerSynthReceiver"); - mixerSynthReceiver.send(message, timeStamp); - } } else { if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to "+size+" transmitter's receivers"); for (int i = 0; i < size; i++) { diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java b/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java new file mode 100644 index 00000000000..7f4090d8d3e --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioFileSoundbankReader.java @@ -0,0 +1,131 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * Soundbank reader that uses audio files as soundbanks. + * + * @author Karl Helgason + */ +public class AudioFileSoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) + throws InvalidMidiDataException, IOException { + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(url); + Soundbank sbk = getSoundbank(ais); + ais.close(); + return sbk; + } catch (UnsupportedAudioFileException e) { + return null; + } catch (IOException e) { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + stream.mark(512); + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(stream); + Soundbank sbk = getSoundbank(ais); + if (sbk != null) + return sbk; + } catch (UnsupportedAudioFileException e) { + } catch (IOException e) { + } + stream.reset(); + return null; + } + + public Soundbank getSoundbank(AudioInputStream ais) + throws InvalidMidiDataException, IOException { + try { + byte[] buffer; + if (ais.getFrameLength() == -1) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buff = new byte[1024 + - (1024 % ais.getFormat().getFrameSize())]; + int ret; + while ((ret = ais.read(buff)) != -1) { + baos.write(buff, 0, ret); + } + ais.close(); + buffer = baos.toByteArray(); + } else { + buffer = new byte[(int) (ais.getFrameLength() + * ais.getFormat().getFrameSize())]; + new DataInputStream(ais).readFully(buffer); + } + ModelByteBufferWavetable osc = new ModelByteBufferWavetable( + new ModelByteBuffer(buffer), ais.getFormat(), -4800); + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(osc); + + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.add(performer); + sbk.addInstrument(ins); + return sbk; + } catch (Exception e) { + return null; + } + } + + public Soundbank getSoundbank(File file) + throws InvalidMidiDataException, IOException { + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(file); + ais.close(); + ModelByteBufferWavetable osc = new ModelByteBufferWavetable( + new ModelByteBuffer(file, 0, file.length()), -4800); + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(osc); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.add(performer); + sbk.addInstrument(ins); + return sbk; + } catch (UnsupportedAudioFileException e1) { + return null; + } catch (IOException e) { + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java b/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java new file mode 100644 index 00000000000..e8d9dbeb14d --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioFloatConverter.java @@ -0,0 +1,1058 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * This class is used to convert between 8,16,24,32,32+ bit signed/unsigned + * big/litle endian fixed/floating point byte buffers and float buffers. + * + * @author Karl Helgason + */ +public abstract class AudioFloatConverter { + + public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT"); + + /*************************************************************************** + * + * LSB Filter, used filter least significant byte in samples arrays. + * + * Is used filter out data in lsb byte when SampleSizeInBits is not + * dividable by 8. + * + **************************************************************************/ + + private static class AudioFloatLSBFilter extends AudioFloatConverter { + + private AudioFloatConverter converter; + + final private int offset; + + final private int stepsize; + + final private byte mask; + + private byte[] mask_buffer; + + public AudioFloatLSBFilter(AudioFloatConverter converter, + AudioFormat format) { + int bits = format.getSampleSizeInBits(); + boolean bigEndian = format.isBigEndian(); + this.converter = converter; + stepsize = (bits + 7) / 8; + offset = bigEndian ? (stepsize - 1) : 0; + int lsb_bits = bits % 8; + if (lsb_bits == 0) + mask = (byte) 0x00; + else if (lsb_bits == 1) + mask = (byte) 0x80; + else if (lsb_bits == 2) + mask = (byte) 0xC0; + else if (lsb_bits == 3) + mask = (byte) 0xE0; + else if (lsb_bits == 4) + mask = (byte) 0xF0; + else if (lsb_bits == 5) + mask = (byte) 0xF8; + else if (lsb_bits == 6) + mask = (byte) 0xFC; + else if (lsb_bits == 7) + mask = (byte) 0xFE; + else + mask = (byte) 0xFF; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + byte[] ret = converter.toByteArray(in_buff, in_offset, in_len, + out_buff, out_offset); + + int out_offset_end = in_len * stepsize; + for (int i = out_offset + offset; i < out_offset_end; i += stepsize) { + out_buff[i] = (byte) (out_buff[i] & mask); + } + + return ret; + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + if (mask_buffer == null || mask_buffer.length < in_buff.length) + mask_buffer = new byte[in_buff.length]; + System.arraycopy(in_buff, 0, mask_buffer, 0, in_buff.length); + int in_offset_end = out_len * stepsize; + for (int i = in_offset + offset; i < in_offset_end; i += stepsize) { + mask_buffer[i] = (byte) (mask_buffer[i] & mask); + } + float[] ret = converter.toFloatArray(mask_buffer, in_offset, + out_buff, out_offset, out_len); + return ret; + } + + } + + /*************************************************************************** + * + * 64 bit float, little/big-endian + * + **************************************************************************/ + + // PCM 64 bit float, little-endian + private static class AudioFloatConversion64L extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + DoubleBuffer floatbuffer = null; + + double[] double_buff = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 8; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asDoubleBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + if (double_buff == null + || double_buff.length < out_len + out_offset) + double_buff = new double[out_len + out_offset]; + floatbuffer.get(double_buff, out_offset, out_len); + int out_offset_end = out_offset + out_len; + for (int i = out_offset; i < out_offset_end; i++) { + out_buff[i] = (float) double_buff[i]; + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 8; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asDoubleBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + if (double_buff == null || double_buff.length < in_offset + in_len) + double_buff = new double[in_offset + in_len]; + int in_offset_end = in_offset + in_len; + for (int i = in_offset; i < in_offset_end; i++) { + double_buff[i] = in_buff[i]; + } + floatbuffer.put(double_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + // PCM 64 bit float, big-endian + private static class AudioFloatConversion64B extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + DoubleBuffer floatbuffer = null; + + double[] double_buff = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 8; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asDoubleBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + if (double_buff == null + || double_buff.length < out_len + out_offset) + double_buff = new double[out_len + out_offset]; + floatbuffer.get(double_buff, out_offset, out_len); + int out_offset_end = out_offset + out_len; + for (int i = out_offset; i < out_offset_end; i++) { + out_buff[i] = (float) double_buff[i]; + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 8; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asDoubleBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + if (double_buff == null || double_buff.length < in_offset + in_len) + double_buff = new double[in_offset + in_len]; + int in_offset_end = in_offset + in_len; + for (int i = in_offset; i < in_offset_end; i++) { + double_buff[i] = in_buff[i]; + } + floatbuffer.put(double_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + /*************************************************************************** + * + * 32 bit float, little/big-endian + * + **************************************************************************/ + + // PCM 32 bit float, little-endian + private static class AudioFloatConversion32L extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + FloatBuffer floatbuffer = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + floatbuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.LITTLE_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + floatbuffer.put(in_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + // PCM 32 bit float, big-endian + private static class AudioFloatConversion32B extends AudioFloatConverter { + ByteBuffer bytebuffer = null; + + FloatBuffer floatbuffer = null; + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int in_len = out_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < in_len) { + bytebuffer = ByteBuffer.allocate(in_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + bytebuffer.position(0); + floatbuffer.position(0); + bytebuffer.put(in_buff, in_offset, in_len); + floatbuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int out_len = in_len * 4; + if (bytebuffer == null || bytebuffer.capacity() < out_len) { + bytebuffer = ByteBuffer.allocate(out_len).order( + ByteOrder.BIG_ENDIAN); + floatbuffer = bytebuffer.asFloatBuffer(); + } + floatbuffer.position(0); + bytebuffer.position(0); + floatbuffer.put(in_buff, in_offset, in_len); + bytebuffer.get(out_buff, out_offset, out_len); + return out_buff; + } + } + + /*************************************************************************** + * + * 8 bit signed/unsigned + * + **************************************************************************/ + + // PCM 8 bit, signed + private static class AudioFloatConversion8S extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) + out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f); + return out_buff; + } + } + + // PCM 8 bit, unsigned + private static class AudioFloatConversion8U extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) + out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127) + * (1.0f / 127.0f); + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) + out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f); + return out_buff; + } + } + + /*************************************************************************** + * + * 16 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 16 bit, signed, little-endian + private static class AudioFloatConversion16SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int len = out_offset + out_len; + for (int ox = out_offset; ox < len; ox++) { + out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | + (in_buff[ix++] << 8))) * (1.0f / 32767.0f); + } + + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ox = out_offset; + int len = in_offset + in_len; + for (int ix = in_offset; ix < len; ix++) { + int x = (int) (in_buff[ix] * 32767.0); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + } + return out_buff; + } + } + + // PCM 16 bit, signed, big-endian + private static class AudioFloatConversion16SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | + (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 16 bit, unsigned, little-endian + private static class AudioFloatConversion16UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8); + out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = 32767 + (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + } + return out_buff; + } + } + + // PCM 16 bit, unsigned, big-endian + private static class AudioFloatConversion16UB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = 32767 + (int) (in_buff[ix++] * 32767.0); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + /*************************************************************************** + * + * 24 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 24 bit, signed, little-endian + private static class AudioFloatConversion24SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16); + if (x > 0x7FFFFF) + x -= 0x1000000; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + if (x < 0) + x += 0x1000000; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + } + return out_buff; + } + } + + // PCM 24 bit, signed, big-endian + private static class AudioFloatConversion24SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + if (x > 0x7FFFFF) + x -= 0x1000000; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + if (x < 0) + x += 0x1000000; + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 24 bit, unsigned, little-endian + private static class AudioFloatConversion24UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16); + x -= 0x7FFFFF; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + x += 0x7FFFFF; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + } + return out_buff; + } + } + + // PCM 24 bit, unsigned, big-endian + private static class AudioFloatConversion24UB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + x -= 0x7FFFFF; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + x += 0x7FFFFF; + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + /*************************************************************************** + * + * 32 bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 32 bit, signed, little-endian + private static class AudioFloatConversion32SL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | + ((in_buff[ix++] & 0xFF) << 16) | + ((in_buff[ix++] & 0xFF) << 24); + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32 bit, signed, big-endian + private static class AudioFloatConversion32SB extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) | + ((in_buff[ix++] & 0xFF) << 16) | + ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + // PCM 32 bit, unsigned, little-endian + private static class AudioFloatConversion32UL extends AudioFloatConverter { + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | + ((in_buff[ix++] & 0xFF) << 16) | + ((in_buff[ix++] & 0xFF) << 24); + x -= 0x7FFFFFFF; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + x += 0x7FFFFFFF; + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32 bit, unsigned, big-endian + private static class AudioFloatConversion32UB extends AudioFloatConverter { + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) | + ((in_buff[ix++] & 0xFF) << 16) | + ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + x -= 0x7FFFFFFF; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + x += 0x7FFFFFFF; + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + } + return out_buff; + } + } + + /*************************************************************************** + * + * 32+ bit signed/unsigned, little/big-endian + * + **************************************************************************/ + + // PCM 32+ bit, signed, little-endian + private static class AudioFloatConversion32xSL extends AudioFloatConverter { + + final int xbytes; + + public AudioFloatConversion32xSL(int xbytes) { + this.xbytes = xbytes; + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + ix += xbytes; + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 24); + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + for (int j = 0; j < xbytes; j++) { + out_buff[ox++] = 0; + } + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32+ bit, signed, big-endian + private static class AudioFloatConversion32xSB extends AudioFloatConverter { + + final int xbytes; + + public AudioFloatConversion32xSB(int xbytes) { + this.xbytes = xbytes; + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 8) + | (in_buff[ix++] & 0xFF); + ix += xbytes; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + for (int j = 0; j < xbytes; j++) { + out_buff[ox++] = 0; + } + } + return out_buff; + } + } + + // PCM 32+ bit, unsigned, little-endian + private static class AudioFloatConversion32xUL extends AudioFloatConverter { + + final int xbytes; + + public AudioFloatConversion32xUL(int xbytes) { + this.xbytes = xbytes; + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + ix += xbytes; + int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) + | ((in_buff[ix++] & 0xFF) << 16) + | ((in_buff[ix++] & 0xFF) << 24); + x -= 0x7FFFFFFF; + out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); + x += 0x7FFFFFFF; + for (int j = 0; j < xbytes; j++) { + out_buff[ox++] = 0; + } + out_buff[ox++] = (byte) x; + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 24); + } + return out_buff; + } + } + + // PCM 32+ bit, unsigned, big-endian + private static class AudioFloatConversion32xUB extends AudioFloatConverter { + + final int xbytes; + + public AudioFloatConversion32xUB(int xbytes) { + this.xbytes = xbytes; + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < out_len; i++) { + int x = ((in_buff[ix++] & 0xFF) << 24) | + ((in_buff[ix++] & 0xFF) << 16) | + ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); + ix += xbytes; + x -= 2147483647; + out_buff[ox++] = x * (1.0f / 2147483647.0f); + } + return out_buff; + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff, int out_offset) { + int ix = in_offset; + int ox = out_offset; + for (int i = 0; i < in_len; i++) { + int x = (int) (in_buff[ix++] * 2147483647.0); + x += 2147483647; + out_buff[ox++] = (byte) (x >>> 24); + out_buff[ox++] = (byte) (x >>> 16); + out_buff[ox++] = (byte) (x >>> 8); + out_buff[ox++] = (byte) x; + for (int j = 0; j < xbytes; j++) { + out_buff[ox++] = 0; + } + } + return out_buff; + } + } + + public static AudioFloatConverter getConverter(AudioFormat format) { + AudioFloatConverter conv = null; + if (format.getFrameSize() == 0) + return null; + if (format.getFrameSize() != + ((format.getSampleSizeInBits() + 7) / 8) * format.getChannels()) { + return null; + } + if (format.getEncoding().equals(Encoding.PCM_SIGNED)) { + if (format.isBigEndian()) { + if (format.getSampleSizeInBits() <= 8) { + conv = new AudioFloatConversion8S(); + } else if (format.getSampleSizeInBits() > 8 && + format.getSampleSizeInBits() <= 16) { + conv = new AudioFloatConversion16SB(); + } else if (format.getSampleSizeInBits() > 16 && + format.getSampleSizeInBits() <= 24) { + conv = new AudioFloatConversion24SB(); + } else if (format.getSampleSizeInBits() > 24 && + format.getSampleSizeInBits() <= 32) { + conv = new AudioFloatConversion32SB(); + } else if (format.getSampleSizeInBits() > 32) { + conv = new AudioFloatConversion32xSB(((format + .getSampleSizeInBits() + 7) / 8) - 4); + } + } else { + if (format.getSampleSizeInBits() <= 8) { + conv = new AudioFloatConversion8S(); + } else if (format.getSampleSizeInBits() > 8 && + format.getSampleSizeInBits() <= 16) { + conv = new AudioFloatConversion16SL(); + } else if (format.getSampleSizeInBits() > 16 && + format.getSampleSizeInBits() <= 24) { + conv = new AudioFloatConversion24SL(); + } else if (format.getSampleSizeInBits() > 24 && + format.getSampleSizeInBits() <= 32) { + conv = new AudioFloatConversion32SL(); + } else if (format.getSampleSizeInBits() > 32) { + conv = new AudioFloatConversion32xSL(((format + .getSampleSizeInBits() + 7) / 8) - 4); + } + } + } else if (format.getEncoding().equals(Encoding.PCM_UNSIGNED)) { + if (format.isBigEndian()) { + if (format.getSampleSizeInBits() <= 8) { + conv = new AudioFloatConversion8U(); + } else if (format.getSampleSizeInBits() > 8 && + format.getSampleSizeInBits() <= 16) { + conv = new AudioFloatConversion16UB(); + } else if (format.getSampleSizeInBits() > 16 && + format.getSampleSizeInBits() <= 24) { + conv = new AudioFloatConversion24UB(); + } else if (format.getSampleSizeInBits() > 24 && + format.getSampleSizeInBits() <= 32) { + conv = new AudioFloatConversion32UB(); + } else if (format.getSampleSizeInBits() > 32) { + conv = new AudioFloatConversion32xUB((( + format.getSampleSizeInBits() + 7) / 8) - 4); + } + } else { + if (format.getSampleSizeInBits() <= 8) { + conv = new AudioFloatConversion8U(); + } else if (format.getSampleSizeInBits() > 8 && + format.getSampleSizeInBits() <= 16) { + conv = new AudioFloatConversion16UL(); + } else if (format.getSampleSizeInBits() > 16 && + format.getSampleSizeInBits() <= 24) { + conv = new AudioFloatConversion24UL(); + } else if (format.getSampleSizeInBits() > 24 && + format.getSampleSizeInBits() <= 32) { + conv = new AudioFloatConversion32UL(); + } else if (format.getSampleSizeInBits() > 32) { + conv = new AudioFloatConversion32xUL((( + format.getSampleSizeInBits() + 7) / 8) - 4); + } + } + } else if (format.getEncoding().equals(PCM_FLOAT)) { + if (format.getSampleSizeInBits() == 32) { + if (format.isBigEndian()) + conv = new AudioFloatConversion32B(); + else + conv = new AudioFloatConversion32L(); + } else if (format.getSampleSizeInBits() == 64) { + if (format.isBigEndian()) + conv = new AudioFloatConversion64B(); + else + conv = new AudioFloatConversion64L(); + } + + } + + if ((format.getEncoding().equals(Encoding.PCM_SIGNED) || + format.getEncoding().equals(Encoding.PCM_UNSIGNED)) && + (format.getSampleSizeInBits() % 8 != 0)) { + conv = new AudioFloatLSBFilter(conv, format); + } + + if (conv != null) + conv.format = format; + return conv; + } + + private AudioFormat format; + + public AudioFormat getFormat() { + return format; + } + + public abstract float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_offset, int out_len); + + public float[] toFloatArray(byte[] in_buff, float[] out_buff, + int out_offset, int out_len) { + return toFloatArray(in_buff, 0, out_buff, out_offset, out_len); + } + + public float[] toFloatArray(byte[] in_buff, int in_offset, + float[] out_buff, int out_len) { + return toFloatArray(in_buff, in_offset, out_buff, 0, out_len); + } + + public float[] toFloatArray(byte[] in_buff, float[] out_buff, int out_len) { + return toFloatArray(in_buff, 0, out_buff, 0, out_len); + } + + public float[] toFloatArray(byte[] in_buff, float[] out_buff) { + return toFloatArray(in_buff, 0, out_buff, 0, out_buff.length); + } + + public abstract byte[] toByteArray(float[] in_buff, int in_offset, + int in_len, byte[] out_buff, int out_offset); + + public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff, + int out_offset) { + return toByteArray(in_buff, 0, in_len, out_buff, out_offset); + } + + public byte[] toByteArray(float[] in_buff, int in_offset, int in_len, + byte[] out_buff) { + return toByteArray(in_buff, in_offset, in_len, out_buff, 0); + } + + public byte[] toByteArray(float[] in_buff, int in_len, byte[] out_buff) { + return toByteArray(in_buff, 0, in_len, out_buff, 0); + } + + public byte[] toByteArray(float[] in_buff, byte[] out_buff) { + return toByteArray(in_buff, 0, in_buff.length, out_buff, 0); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java b/jdk/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java new file mode 100644 index 00000000000..4e835f4c192 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java @@ -0,0 +1,617 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.spi.FormatConversionProvider; + +/** + * This class is used to convert between 8,16,24,32 bit signed/unsigned + * big/litle endian fixed/floating stereo/mono/multi-channel audio streams and + * perform sample-rate conversion if needed. + * + * @author Karl Helgason + */ +public class AudioFloatFormatConverter extends FormatConversionProvider { + + private static class AudioFloatFormatConverterInputStream extends + InputStream { + private AudioFloatConverter converter; + + private AudioFloatInputStream stream; + + private float[] readfloatbuffer; + + private int fsize = 0; + + public AudioFloatFormatConverterInputStream(AudioFormat targetFormat, + AudioFloatInputStream stream) { + this.stream = stream; + converter = AudioFloatConverter.getConverter(targetFormat); + fsize = ((targetFormat.getSampleSizeInBits() + 7) / 8); + } + + public int read() throws IOException { + byte[] b = new byte[1]; + int ret = read(b); + if (ret < 0) + return ret; + return b[0] & 0xFF; + } + + public int read(byte[] b, int off, int len) throws IOException { + + int flen = len / fsize; + if (readfloatbuffer == null || readfloatbuffer.length < flen) + readfloatbuffer = new float[flen]; + int ret = stream.read(readfloatbuffer, 0, flen); + if (ret < 0) + return ret; + converter.toByteArray(readfloatbuffer, 0, ret, b, off); + return ret * fsize; + } + + public int available() throws IOException { + int ret = stream.available(); + if (ret < 0) + return ret; + return ret * fsize; + } + + public void close() throws IOException { + stream.close(); + } + + public synchronized void mark(int readlimit) { + stream.mark(readlimit * fsize); + } + + public boolean markSupported() { + return stream.markSupported(); + } + + public synchronized void reset() throws IOException { + stream.reset(); + } + + public long skip(long n) throws IOException { + long ret = stream.skip(n / fsize); + if (ret < 0) + return ret; + return ret * fsize; + } + + } + + private static class AudioFloatInputStreamChannelMixer extends + AudioFloatInputStream { + + private int targetChannels; + + private int sourceChannels; + + private AudioFloatInputStream ais; + + private AudioFormat targetFormat; + + private float[] conversion_buffer; + + public AudioFloatInputStreamChannelMixer(AudioFloatInputStream ais, + int targetChannels) { + this.sourceChannels = ais.getFormat().getChannels(); + this.targetChannels = targetChannels; + this.ais = ais; + AudioFormat format = ais.getFormat(); + targetFormat = new AudioFormat(format.getEncoding(), format + .getSampleRate(), format.getSampleSizeInBits(), + targetChannels, (format.getFrameSize() / sourceChannels) + * targetChannels, format.getFrameRate(), format + .isBigEndian()); + } + + public int available() throws IOException { + return (ais.available() / sourceChannels) * targetChannels; + } + + public void close() throws IOException { + ais.close(); + } + + public AudioFormat getFormat() { + return targetFormat; + } + + public long getFrameLength() { + return ais.getFrameLength(); + } + + public void mark(int readlimit) { + ais.mark((readlimit / targetChannels) * sourceChannels); + } + + public boolean markSupported() { + return ais.markSupported(); + } + + public int read(float[] b, int off, int len) throws IOException { + int len2 = (len / targetChannels) * sourceChannels; + if (conversion_buffer == null || conversion_buffer.length < len2) + conversion_buffer = new float[len2]; + int ret = ais.read(conversion_buffer, 0, len2); + if (ret < 0) + return ret; + if (sourceChannels == 1) { + int cs = targetChannels; + for (int c = 0; c < targetChannels; c++) { + for (int i = 0, ix = off + c; i < len2; i++, ix += cs) { + b[ix] = conversion_buffer[i]; + ; + } + } + } else if (targetChannels == 1) { + int cs = sourceChannels; + for (int i = 0, ix = off; i < len2; i += cs, ix++) { + b[ix] = conversion_buffer[i]; + } + for (int c = 1; c < sourceChannels; c++) { + for (int i = c, ix = off; i < len2; i += cs, ix++) { + b[ix] += conversion_buffer[i]; + ; + } + } + float vol = 1f / ((float) sourceChannels); + for (int i = 0, ix = off; i < len2; i += cs, ix++) { + b[ix] *= vol; + } + } else { + int minChannels = Math.min(sourceChannels, targetChannels); + int off_len = off + len; + int ct = targetChannels; + int cs = sourceChannels; + for (int c = 0; c < minChannels; c++) { + for (int i = off + c, ix = c; i < off_len; i += ct, ix += cs) { + b[i] = conversion_buffer[ix]; + } + } + for (int c = minChannels; c < targetChannels; c++) { + for (int i = off + c; i < off_len; i += ct) { + b[i] = 0; + } + } + } + return (ret / sourceChannels) * targetChannels; + } + + public void reset() throws IOException { + ais.reset(); + } + + public long skip(long len) throws IOException { + long ret = ais.skip((len / targetChannels) * sourceChannels); + if (ret < 0) + return ret; + return (ret / sourceChannels) * targetChannels; + } + + } + + private static class AudioFloatInputStreamResampler extends + AudioFloatInputStream { + + private AudioFloatInputStream ais; + + private AudioFormat targetFormat; + + private float[] skipbuffer; + + private SoftAbstractResampler resampler; + + private float[] pitch = new float[1]; + + private float[] ibuffer2; + + private float[][] ibuffer; + + private float ibuffer_index = 0; + + private int ibuffer_len = 0; + + private int nrofchannels = 0; + + private float[][] cbuffer; + + private int buffer_len = 512; + + private int pad; + + private int pad2; + + private float[] ix = new float[1]; + + private int[] ox = new int[1]; + + private float[][] mark_ibuffer = null; + + private float mark_ibuffer_index = 0; + + private int mark_ibuffer_len = 0; + + public AudioFloatInputStreamResampler(AudioFloatInputStream ais, + AudioFormat format) { + this.ais = ais; + AudioFormat sourceFormat = ais.getFormat(); + targetFormat = new AudioFormat(sourceFormat.getEncoding(), format + .getSampleRate(), sourceFormat.getSampleSizeInBits(), + sourceFormat.getChannels(), sourceFormat.getFrameSize(), + format.getSampleRate(), sourceFormat.isBigEndian()); + nrofchannels = targetFormat.getChannels(); + Object interpolation = format.getProperty("interpolation"); + if (interpolation != null && (interpolation instanceof String)) { + String resamplerType = (String) interpolation; + if (resamplerType.equalsIgnoreCase("point")) + this.resampler = new SoftPointResampler(); + if (resamplerType.equalsIgnoreCase("linear")) + this.resampler = new SoftLinearResampler2(); + if (resamplerType.equalsIgnoreCase("linear1")) + this.resampler = new SoftLinearResampler(); + if (resamplerType.equalsIgnoreCase("linear2")) + this.resampler = new SoftLinearResampler2(); + if (resamplerType.equalsIgnoreCase("cubic")) + this.resampler = new SoftCubicResampler(); + if (resamplerType.equalsIgnoreCase("lanczos")) + this.resampler = new SoftLanczosResampler(); + if (resamplerType.equalsIgnoreCase("sinc")) + this.resampler = new SoftSincResampler(); + } + if (resampler == null) + resampler = new SoftLinearResampler2(); // new + // SoftLinearResampler2(); + pitch[0] = sourceFormat.getSampleRate() / format.getSampleRate(); + pad = resampler.getPadding(); + pad2 = pad * 2; + ibuffer = new float[nrofchannels][buffer_len + pad2]; + ibuffer2 = new float[nrofchannels * buffer_len]; + ibuffer_index = buffer_len + pad; + ibuffer_len = buffer_len; + } + + public int available() throws IOException { + return 0; + } + + public void close() throws IOException { + ais.close(); + } + + public AudioFormat getFormat() { + return targetFormat; + } + + public long getFrameLength() { + return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength(); + } + + public void mark(int readlimit) { + ais.mark((int) (readlimit * pitch[0])); + mark_ibuffer_index = ibuffer_index; + mark_ibuffer_len = ibuffer_len; + if (mark_ibuffer == null) { + mark_ibuffer = new float[ibuffer.length][ibuffer[0].length]; + } + for (int c = 0; c < ibuffer.length; c++) { + float[] from = ibuffer[c]; + float[] to = mark_ibuffer[c]; + for (int i = 0; i < to.length; i++) { + to[i] = from[i]; + } + } + } + + public boolean markSupported() { + return ais.markSupported(); + } + + private void readNextBuffer() throws IOException { + + if (ibuffer_len == -1) + return; + + for (int c = 0; c < nrofchannels; c++) { + float[] buff = ibuffer[c]; + int buffer_len_pad = ibuffer_len + pad2; + for (int i = ibuffer_len, ix = 0; i < buffer_len_pad; i++, ix++) { + buff[ix] = buff[i]; + } + } + + ibuffer_index -= (ibuffer_len); + + ibuffer_len = ais.read(ibuffer2); + if (ibuffer_len >= 0) { + while (ibuffer_len < ibuffer2.length) { + int ret = ais.read(ibuffer2, ibuffer_len, ibuffer2.length + - ibuffer_len); + if (ret == -1) + break; + ibuffer_len += ret; + } + Arrays.fill(ibuffer2, ibuffer_len, ibuffer2.length, 0); + ibuffer_len /= nrofchannels; + } else { + Arrays.fill(ibuffer2, 0, ibuffer2.length, 0); + } + + int ibuffer2_len = ibuffer2.length; + for (int c = 0; c < nrofchannels; c++) { + float[] buff = ibuffer[c]; + for (int i = c, ix = pad2; i < ibuffer2_len; i += nrofchannels, ix++) { + buff[ix] = ibuffer2[i]; + } + } + + } + + public int read(float[] b, int off, int len) throws IOException { + + if (cbuffer == null || cbuffer[0].length < len / nrofchannels) { + cbuffer = new float[nrofchannels][len / nrofchannels]; + } + if (ibuffer_len == -1) + return -1; + if (len < 0) + return 0; + int remain = len / nrofchannels; + int destPos = 0; + int in_end = ibuffer_len; + while (remain > 0) { + if (ibuffer_len >= 0) { + if (ibuffer_index >= (ibuffer_len + pad)) + readNextBuffer(); + in_end = ibuffer_len + pad; + } + + if (ibuffer_len < 0) { + in_end = pad2; + if (ibuffer_index >= in_end) + break; + } + + if (ibuffer_index < 0) + break; + int preDestPos = destPos; + for (int c = 0; c < nrofchannels; c++) { + ix[0] = ibuffer_index; + ox[0] = destPos; + float[] buff = ibuffer[c]; + resampler.interpolate(buff, ix, in_end, pitch, 0, + cbuffer[c], ox, len / nrofchannels); + } + ibuffer_index = ix[0]; + destPos = ox[0]; + remain -= destPos - preDestPos; + } + for (int c = 0; c < nrofchannels; c++) { + int ix = 0; + float[] buff = cbuffer[c]; + for (int i = c; i < b.length; i += nrofchannels) { + b[i] = buff[ix++]; + } + } + return len - remain * nrofchannels; + } + + public void reset() throws IOException { + ais.reset(); + if (mark_ibuffer == null) + return; + ibuffer_index = mark_ibuffer_index; + ibuffer_len = mark_ibuffer_len; + for (int c = 0; c < ibuffer.length; c++) { + float[] from = mark_ibuffer[c]; + float[] to = ibuffer[c]; + for (int i = 0; i < to.length; i++) { + to[i] = from[i]; + } + } + + } + + public long skip(long len) throws IOException { + if (len > 0) + return 0; + if (skipbuffer == null) + skipbuffer = new float[1024 * targetFormat.getFrameSize()]; + float[] l_skipbuffer = skipbuffer; + long remain = len; + while (remain > 0) { + int ret = read(l_skipbuffer, 0, (int) Math.min(remain, + skipbuffer.length)); + if (ret < 0) { + if (remain == len) + return ret; + break; + } + remain -= ret; + } + return len - remain; + + } + + } + + private Encoding[] formats = { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED, + AudioFloatConverter.PCM_FLOAT }; + + public AudioInputStream getAudioInputStream(Encoding targetEncoding, + AudioInputStream sourceStream) { + if (sourceStream.getFormat().getEncoding().equals(targetEncoding)) + return sourceStream; + AudioFormat format = sourceStream.getFormat(); + int channels = format.getChannels(); + Encoding encoding = targetEncoding; + float samplerate = format.getSampleRate(); + int bits = format.getSampleSizeInBits(); + boolean bigendian = format.isBigEndian(); + if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT)) + bits = 32; + AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits, + channels, channels * bits / 8, samplerate, bigendian); + return getAudioInputStream(targetFormat, sourceStream); + } + + public AudioInputStream getAudioInputStream(AudioFormat targetFormat, + AudioInputStream sourceStream) { + if (!isConversionSupported(targetFormat, sourceStream.getFormat())) + throw new IllegalArgumentException("Unsupported conversion: " + + sourceStream.getFormat().toString() + " to " + + targetFormat.toString()); + return getAudioInputStream(targetFormat, AudioFloatInputStream + .getInputStream(sourceStream)); + } + + public AudioInputStream getAudioInputStream(AudioFormat targetFormat, + AudioFloatInputStream sourceStream) { + + if (!isConversionSupported(targetFormat, sourceStream.getFormat())) + throw new IllegalArgumentException("Unsupported conversion: " + + sourceStream.getFormat().toString() + " to " + + targetFormat.toString()); + if (targetFormat.getChannels() != sourceStream.getFormat() + .getChannels()) + sourceStream = new AudioFloatInputStreamChannelMixer(sourceStream, + targetFormat.getChannels()); + if (Math.abs(targetFormat.getSampleRate() + - sourceStream.getFormat().getSampleRate()) > 0.000001) + sourceStream = new AudioFloatInputStreamResampler(sourceStream, + targetFormat); + return new AudioInputStream(new AudioFloatFormatConverterInputStream( + targetFormat, sourceStream), targetFormat, sourceStream + .getFrameLength()); + } + + public Encoding[] getSourceEncodings() { + return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED, + AudioFloatConverter.PCM_FLOAT }; + } + + public Encoding[] getTargetEncodings() { + return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED, + AudioFloatConverter.PCM_FLOAT }; + } + + public Encoding[] getTargetEncodings(AudioFormat sourceFormat) { + if (AudioFloatConverter.getConverter(sourceFormat) == null) + return new Encoding[0]; + return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED, + AudioFloatConverter.PCM_FLOAT }; + } + + public AudioFormat[] getTargetFormats(Encoding targetEncoding, + AudioFormat sourceFormat) { + if (AudioFloatConverter.getConverter(sourceFormat) == null) + return new AudioFormat[0]; + int channels = sourceFormat.getChannels(); + + ArrayList formats = new ArrayList(); + + if (targetEncoding.equals(Encoding.PCM_SIGNED)) + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + if (targetEncoding.equals(Encoding.PCM_UNSIGNED)) + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + + for (int bits = 16; bits < 32; bits += 8) { + if (targetEncoding.equals(Encoding.PCM_SIGNED)) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + } + if (targetEncoding.equals(Encoding.PCM_UNSIGNED)) { + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + } + } + + if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT)) { + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, true)); + } + + return formats.toArray(new AudioFormat[formats.size()]); + } + + public boolean isConversionSupported(AudioFormat targetFormat, + AudioFormat sourceFormat) { + if (AudioFloatConverter.getConverter(sourceFormat) == null) + return false; + if (AudioFloatConverter.getConverter(targetFormat) == null) + return false; + if (sourceFormat.getChannels() <= 0) + return false; + if (targetFormat.getChannels() <= 0) + return false; + return true; + } + + public boolean isConversionSupported(Encoding targetEncoding, + AudioFormat sourceFormat) { + if (AudioFloatConverter.getConverter(sourceFormat) == null) + return false; + for (int i = 0; i < formats.length; i++) { + if (targetEncoding.equals(formats[i])) + return true; + } + return false; + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java b/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java new file mode 100644 index 00000000000..9c3673721c3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioFloatInputStream.java @@ -0,0 +1,281 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +/** + * This class is used to create AudioFloatInputStream from AudioInputStream and + * byte buffers. + * + * @author Karl Helgason + */ +public abstract class AudioFloatInputStream { + + private static class BytaArrayAudioFloatInputStream + extends AudioFloatInputStream { + + private int pos = 0; + private int markpos = 0; + private AudioFloatConverter converter; + private AudioFormat format; + private byte[] buffer; + private int buffer_offset; + private int buffer_len; + private int framesize_pc; + + public BytaArrayAudioFloatInputStream(AudioFloatConverter converter, + byte[] buffer, int offset, int len) { + this.converter = converter; + this.format = converter.getFormat(); + this.buffer = buffer; + this.buffer_offset = offset; + framesize_pc = format.getFrameSize() / format.getChannels(); + this.buffer_len = len / framesize_pc; + + } + + public AudioFormat getFormat() { + return format; + } + + public long getFrameLength() { + return buffer_len;// / format.getFrameSize(); + } + + public int read(float[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); + if (off < 0 || len < 0 || len > b.length - off) + throw new IndexOutOfBoundsException(); + if (pos >= buffer_len) + return -1; + if (len == 0) + return 0; + if (pos + len > buffer_len) + len = buffer_len - pos; + converter.toFloatArray(buffer, buffer_offset + pos * framesize_pc, + b, off, len); + pos += len; + return len; + } + + public long skip(long len) throws IOException { + if (pos >= buffer_len) + return -1; + if (len <= 0) + return 0; + if (pos + len > buffer_len) + len = buffer_len - pos; + pos += len; + return len; + } + + public int available() throws IOException { + return buffer_len - pos; + } + + public void close() throws IOException { + } + + public void mark(int readlimit) { + markpos = pos; + } + + public boolean markSupported() { + return true; + } + + public void reset() throws IOException { + pos = markpos; + } + } + + private static class DirectAudioFloatInputStream + extends AudioFloatInputStream { + + private AudioInputStream stream; + private AudioFloatConverter converter; + private int framesize_pc; // framesize / channels + private byte[] buffer; + + public DirectAudioFloatInputStream(AudioInputStream stream) { + converter = AudioFloatConverter.getConverter(stream.getFormat()); + if (converter == null) { + AudioFormat format = stream.getFormat(); + AudioFormat newformat; + + AudioFormat[] formats = AudioSystem.getTargetFormats( + AudioFormat.Encoding.PCM_SIGNED, format); + if (formats.length != 0) { + newformat = formats[0]; + } else { + float samplerate = format.getSampleRate(); + int samplesizeinbits = format.getSampleSizeInBits(); + int framesize = format.getFrameSize(); + float framerate = format.getFrameRate(); + samplesizeinbits = 16; + framesize = format.getChannels() * (samplesizeinbits / 8); + framerate = samplerate; + + newformat = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, samplerate, + samplesizeinbits, format.getChannels(), framesize, + framerate, false); + } + + stream = AudioSystem.getAudioInputStream(newformat, stream); + converter = AudioFloatConverter.getConverter(stream.getFormat()); + } + framesize_pc = stream.getFormat().getFrameSize() + / stream.getFormat().getChannels(); + this.stream = stream; + } + + public AudioFormat getFormat() { + return stream.getFormat(); + } + + public long getFrameLength() { + return stream.getFrameLength(); + } + + public int read(float[] b, int off, int len) throws IOException { + int b_len = len * framesize_pc; + if (buffer == null || buffer.length < b_len) + buffer = new byte[b_len]; + int ret = stream.read(buffer, 0, b_len); + if (ret == -1) + return -1; + converter.toFloatArray(buffer, b, off, ret / framesize_pc); + return ret / framesize_pc; + } + + public long skip(long len) throws IOException { + long b_len = len * framesize_pc; + long ret = stream.skip(b_len); + if (ret == -1) + return -1; + return ret / framesize_pc; + } + + public int available() throws IOException { + return stream.available() / framesize_pc; + } + + public void close() throws IOException { + stream.close(); + } + + public void mark(int readlimit) { + stream.mark(readlimit * framesize_pc); + } + + public boolean markSupported() { + return stream.markSupported(); + } + + public void reset() throws IOException { + stream.reset(); + } + } + + public static AudioFloatInputStream getInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(url)); + } + + public static AudioFloatInputStream getInputStream(File file) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(file)); + } + + public static AudioFloatInputStream getInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException { + return new DirectAudioFloatInputStream(AudioSystem + .getAudioInputStream(stream)); + } + + public static AudioFloatInputStream getInputStream( + AudioInputStream stream) { + return new DirectAudioFloatInputStream(stream); + } + + public static AudioFloatInputStream getInputStream(AudioFormat format, + byte[] buffer, int offset, int len) { + AudioFloatConverter converter = AudioFloatConverter + .getConverter(format); + if (converter != null) + return new BytaArrayAudioFloatInputStream(converter, buffer, + offset, len); + + InputStream stream = new ByteArrayInputStream(buffer, offset, len); + long aLen = format.getFrameSize() == AudioSystem.NOT_SPECIFIED + ? AudioSystem.NOT_SPECIFIED : len / format.getFrameSize(); + AudioInputStream astream = new AudioInputStream(stream, format, aLen); + return getInputStream(astream); + } + + public abstract AudioFormat getFormat(); + + public abstract long getFrameLength(); + + public abstract int read(float[] b, int off, int len) throws IOException; + + public int read(float[] b) throws IOException { + return read(b, 0, b.length); + } + + public float read() throws IOException { + float[] b = new float[1]; + int ret = read(b, 0, 1); + if (ret == -1 || ret == 0) + return 0; + return b[0]; + } + + public abstract long skip(long len) throws IOException; + + public abstract int available() throws IOException; + + public abstract void close() throws IOException; + + public abstract void mark(int readlimit); + + public abstract boolean markSupported(); + + public abstract void reset() throws IOException; +} diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java b/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java new file mode 100644 index 00000000000..247e03f04ab --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizer.java @@ -0,0 +1,128 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Map; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Synthesizer; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.SourceDataLine; + +/** + * AudioSynthesizer is a Synthesizer + * which renders it's output audio into SourceDataLine + * or AudioInputStream. + * + * @see MidiSystem#getSynthesizer + * @see Synthesizer + * + * @author Karl Helgason + */ +public interface AudioSynthesizer extends Synthesizer { + + /** + * Obtains the current format (encoding, sample rate, number of channels, + * etc.) of the synthesizer audio data. + * + *

If the synthesizer is not open and has never been opened, it returns + * the default format. + * + * @return current audio data format + * @see AudioFormat + */ + public AudioFormat getFormat(); + + /** + * Gets information about the possible properties for the synthesizer. + * + * @param info a proposed list of tag/value pairs that will be sent on open. + * @return an array of AudioSynthesizerPropertyInfo objects + * describing possible properties. This array may be an empty array if + * no properties are required. + */ + public AudioSynthesizerPropertyInfo[] getPropertyInfo( + Map info); + + /** + * Opens the synthesizer and starts rendering audio into + * SourceDataLine. + * + *

An application opening a synthesizer explicitly with this call + * has to close the synthesizer by calling {@link #close}. This is + * necessary to release system resources and allow applications to + * exit cleanly. + * + *

Note that some synthesizers, once closed, cannot be reopened. + * Attempts to reopen such a synthesizer will always result in + * a MidiUnavailableException. + * + * @param line which AudioSynthesizer writes output audio into. + * If line is null, then line from system default mixer is used. + * @param info a Map object containing + * properties for additional configuration supported by synthesizer. + * If info is null then default settings are used. + * + * @throws MidiUnavailableException thrown if the synthesizer cannot be + * opened due to resource restrictions. + * @throws SecurityException thrown if the synthesizer cannot be + * opened due to security restrictions. + * + * @see #close + * @see #isOpen + */ + public void open(SourceDataLine line, Map info) + throws MidiUnavailableException; + + /** + * Opens the synthesizer and renders audio into returned + * AudioInputStream. + * + *

An application opening a synthesizer explicitly with this call + * has to close the synthesizer by calling {@link #close}. This is + * necessary to release system resources and allow applications to + * exit cleanly. + * + *

Note that some synthesizers, once closed, cannot be reopened. + * Attempts to reopen such a synthesizer will always result in + * a MidiUnavailableException. + * + * @param targetFormat specifies the AudioFormat + * used in returned AudioInputStream. + * @param info a Map object containing + * properties for additional configuration supported by synthesizer. + * If info is null then default settings are used. + * + * @throws MidiUnavailableException thrown if the synthesizer cannot be + * opened due to resource restrictions. + * @throws SecurityException thrown if the synthesizer cannot be + * opened due to security restrictions. + * + * @see #close + * @see #isOpen + */ + public AudioInputStream openStream(AudioFormat targetFormat, + Map info) throws MidiUnavailableException; +} diff --git a/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java b/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java new file mode 100644 index 00000000000..cf40dda256a --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java @@ -0,0 +1,76 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Information about property used in opening AudioSynthesizer. + * + * @author Karl Helgason + */ +public class AudioSynthesizerPropertyInfo { + + /** + * Constructs a AudioSynthesizerPropertyInfo object with a given + * name and value. The description and choices + * are intialized by null values. + * + * @param name the name of the property + * @param value the current value or class used for values. + * + */ + public AudioSynthesizerPropertyInfo(String name, Object value) { + this.name = name; + this.value = value; + if (value instanceof Class) + valueClass = (Class)value; + else if (value != null) + valueClass = value.getClass(); + } + /** + * The name of the property. + */ + public String name; + /** + * A brief description of the property, which may be null. + */ + public String description = null; + /** + * The value field specifies the current value of + * the property. + */ + public Object value = null; + /** + * The valueClass field specifies class + * used in value field. + */ + public Class valueClass = null; + /** + * An array of possible values if the value for the field + * AudioSynthesizerPropertyInfo.value may be selected + * from a particular set of values; otherwise null. + */ + public Object[] choices = null; + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java b/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java new file mode 100644 index 00000000000..4e904216138 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSInfo.java @@ -0,0 +1,109 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class is used to store information to describe soundbanks, instruments + * and samples. It is stored inside a "INFO" List Chunk inside DLS files. + * + * @author Karl Helgason + */ +public class DLSInfo { + + /** + * (INAM) Title or subject. + */ + public String name = "untitled"; + /** + * (ICRD) Date of creation, the format is: YYYY-MM-DD. + * For example 2007-01-01 for 1. january of year 2007. + */ + public String creationDate = null; + /** + * (IENG) Name of engineer who created the object. + */ + public String engineers = null; + /** + * (IPRD) Name of the product which the object is intended for. + */ + public String product = null; + /** + * (ICOP) Copyright information. + */ + public String copyright = null; + /** + * (ICMT) General comments. Doesn't contain newline characters. + */ + public String comments = null; + /** + * (ISFT) Name of software package used to create the file. + */ + public String tools = null; + /** + * (IARL) Where content is archived. + */ + public String archival_location = null; + /** + * (IART) Artists of original content. + */ + public String artist = null; + /** + * (ICMS) Names of persons or orginizations who commissioned the file. + */ + public String commissioned = null; + /** + * (IGNR) Genre of the work. + * Example: jazz, classical, rock, etc. + */ + public String genre = null; + /** + * (IKEY) List of keyword that describe the content. + * Examples: FX, bird, piano, etc. + */ + public String keywords = null; + /** + * (IMED) Describes original medium of the data. + * For example: record, CD, etc. + */ + public String medium = null; + /** + * (ISBJ) Description of the content. + */ + public String subject = null; + /** + * (ISRC) Name of person or orginization who supplied + * orginal material for the file. + */ + public String source = null; + /** + * (ISRF) Source media for sample data is from. + * For example: CD, TV, etc. + */ + public String source_form = null; + /** + * (ITCH) Technician who sample the file/object. + */ + public String technician = null; +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java b/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java new file mode 100644 index 00000000000..c4912314abb --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSInstrument.java @@ -0,0 +1,448 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Patch; + +/** + * This class is used to store information to describe instrument. + * It contains list of regions and modulators. + * It is stored inside a "ins " List Chunk inside DLS files. + * In the DLS documentation a modulator is called articulator. + * + * @author Karl Helgason + */ +public class DLSInstrument extends ModelInstrument { + + protected int preset = 0; + protected int bank = 0; + protected boolean druminstrument = false; + protected byte[] guid = null; + protected DLSInfo info = new DLSInfo(); + protected List regions = new ArrayList(); + protected List modulators = new ArrayList(); + + public DLSInstrument() { + super(null, null, null, null); + } + + public DLSInstrument(DLSSoundbank soundbank) { + super(soundbank, null, null, null); + } + + public DLSInfo getInfo() { + return info; + } + + public String getName() { + return info.name; + } + + public void setName(String name) { + info.name = name; + } + + public ModelPatch getPatch() { + return new ModelPatch(bank, preset, druminstrument); + } + + public void setPatch(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) { + druminstrument = true; + bank = patch.getBank(); + preset = patch.getProgram(); + } else { + druminstrument = false; + bank = patch.getBank(); + preset = patch.getProgram(); + } + } + + public Object getData() { + return null; + } + + public List getRegions() { + return regions; + } + + public List getModulators() { + return modulators; + } + + public String toString() { + if (druminstrument) + return "Drumkit: " + info.name + + " bank #" + bank + " preset #" + preset; + else + return "Instrument: " + info.name + + " bank #" + bank + " preset #" + preset; + } + + private ModelIdentifier convertToModelDest(int dest) { + if (dest == DLSModulator.CONN_DST_NONE) + return null; + if (dest == DLSModulator.CONN_DST_GAIN) + return ModelDestination.DESTINATION_GAIN; + if (dest == DLSModulator.CONN_DST_PITCH) + return ModelDestination.DESTINATION_PITCH; + if (dest == DLSModulator.CONN_DST_PAN) + return ModelDestination.DESTINATION_PAN; + + if (dest == DLSModulator.CONN_DST_LFO_FREQUENCY) + return ModelDestination.DESTINATION_LFO1_FREQ; + if (dest == DLSModulator.CONN_DST_LFO_STARTDELAY) + return ModelDestination.DESTINATION_LFO1_DELAY; + + if (dest == DLSModulator.CONN_DST_EG1_ATTACKTIME) + return ModelDestination.DESTINATION_EG1_ATTACK; + if (dest == DLSModulator.CONN_DST_EG1_DECAYTIME) + return ModelDestination.DESTINATION_EG1_DECAY; + if (dest == DLSModulator.CONN_DST_EG1_RELEASETIME) + return ModelDestination.DESTINATION_EG1_RELEASE; + if (dest == DLSModulator.CONN_DST_EG1_SUSTAINLEVEL) + return ModelDestination.DESTINATION_EG1_SUSTAIN; + + if (dest == DLSModulator.CONN_DST_EG2_ATTACKTIME) + return ModelDestination.DESTINATION_EG2_ATTACK; + if (dest == DLSModulator.CONN_DST_EG2_DECAYTIME) + return ModelDestination.DESTINATION_EG2_DECAY; + if (dest == DLSModulator.CONN_DST_EG2_RELEASETIME) + return ModelDestination.DESTINATION_EG2_RELEASE; + if (dest == DLSModulator.CONN_DST_EG2_SUSTAINLEVEL) + return ModelDestination.DESTINATION_EG2_SUSTAIN; + + // DLS2 Destinations + if (dest == DLSModulator.CONN_DST_KEYNUMBER) + return ModelDestination.DESTINATION_KEYNUMBER; + + if (dest == DLSModulator.CONN_DST_CHORUS) + return ModelDestination.DESTINATION_CHORUS; + if (dest == DLSModulator.CONN_DST_REVERB) + return ModelDestination.DESTINATION_REVERB; + + if (dest == DLSModulator.CONN_DST_VIB_FREQUENCY) + return ModelDestination.DESTINATION_LFO2_FREQ; + if (dest == DLSModulator.CONN_DST_VIB_STARTDELAY) + return ModelDestination.DESTINATION_LFO2_DELAY; + + if (dest == DLSModulator.CONN_DST_EG1_DELAYTIME) + return ModelDestination.DESTINATION_EG1_DELAY; + if (dest == DLSModulator.CONN_DST_EG1_HOLDTIME) + return ModelDestination.DESTINATION_EG1_HOLD; + if (dest == DLSModulator.CONN_DST_EG1_SHUTDOWNTIME) + return ModelDestination.DESTINATION_EG1_SHUTDOWN; + + if (dest == DLSModulator.CONN_DST_EG2_DELAYTIME) + return ModelDestination.DESTINATION_EG2_DELAY; + if (dest == DLSModulator.CONN_DST_EG2_HOLDTIME) + return ModelDestination.DESTINATION_EG2_HOLD; + + if (dest == DLSModulator.CONN_DST_FILTER_CUTOFF) + return ModelDestination.DESTINATION_FILTER_FREQ; + if (dest == DLSModulator.CONN_DST_FILTER_Q) + return ModelDestination.DESTINATION_FILTER_Q; + + return null; + } + + private ModelIdentifier convertToModelSrc(int src) { + if (src == DLSModulator.CONN_SRC_NONE) + return null; + + if (src == DLSModulator.CONN_SRC_LFO) + return ModelSource.SOURCE_LFO1; + if (src == DLSModulator.CONN_SRC_KEYONVELOCITY) + return ModelSource.SOURCE_NOTEON_VELOCITY; + if (src == DLSModulator.CONN_SRC_KEYNUMBER) + return ModelSource.SOURCE_NOTEON_KEYNUMBER; + if (src == DLSModulator.CONN_SRC_EG1) + return ModelSource.SOURCE_EG1; + if (src == DLSModulator.CONN_SRC_EG2) + return ModelSource.SOURCE_EG2; + if (src == DLSModulator.CONN_SRC_PITCHWHEEL) + return ModelSource.SOURCE_MIDI_PITCH; + if (src == DLSModulator.CONN_SRC_CC1) + return new ModelIdentifier("midi_cc", "1", 0); + if (src == DLSModulator.CONN_SRC_CC7) + return new ModelIdentifier("midi_cc", "7", 0); + if (src == DLSModulator.CONN_SRC_CC10) + return new ModelIdentifier("midi_cc", "10", 0); + if (src == DLSModulator.CONN_SRC_CC11) + return new ModelIdentifier("midi_cc", "11", 0); + if (src == DLSModulator.CONN_SRC_RPN0) + return new ModelIdentifier("midi_rpn", "0", 0); + if (src == DLSModulator.CONN_SRC_RPN1) + return new ModelIdentifier("midi_rpn", "1", 0); + + if (src == DLSModulator.CONN_SRC_POLYPRESSURE) + return ModelSource.SOURCE_MIDI_POLY_PRESSURE; + if (src == DLSModulator.CONN_SRC_CHANNELPRESSURE) + return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + if (src == DLSModulator.CONN_SRC_VIBRATO) + return ModelSource.SOURCE_LFO2; + if (src == DLSModulator.CONN_SRC_MONOPRESSURE) + return ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + + if (src == DLSModulator.CONN_SRC_CC91) + return new ModelIdentifier("midi_cc", "91", 0); + if (src == DLSModulator.CONN_SRC_CC93) + return new ModelIdentifier("midi_cc", "93", 0); + + return null; + } + + private ModelConnectionBlock convertToModel(DLSModulator mod) { + ModelIdentifier source = convertToModelSrc(mod.getSource()); + ModelIdentifier control = convertToModelSrc(mod.getControl()); + ModelIdentifier destination_id = + convertToModelDest(mod.getDestination()); + + int scale = mod.getScale(); + double f_scale; + if (scale == Integer.MIN_VALUE) + f_scale = Double.NEGATIVE_INFINITY; + else + f_scale = scale / 65536.0; + + if (destination_id != null) { + ModelSource src = null; + ModelSource ctrl = null; + ModelConnectionBlock block = new ModelConnectionBlock(); + if (control != null) { + ModelSource s = new ModelSource(); + if (control == ModelSource.SOURCE_MIDI_PITCH) { + ((ModelStandardTransform)s.getTransform()).setPolarity( + ModelStandardTransform.POLARITY_BIPOLAR); + } else if (control == ModelSource.SOURCE_LFO1 + || control == ModelSource.SOURCE_LFO2) { + ((ModelStandardTransform)s.getTransform()).setPolarity( + ModelStandardTransform.POLARITY_BIPOLAR); + } + s.setIdentifier(control); + block.addSource(s); + ctrl = s; + } + if (source != null) { + ModelSource s = new ModelSource(); + if (source == ModelSource.SOURCE_MIDI_PITCH) { + ((ModelStandardTransform)s.getTransform()).setPolarity( + ModelStandardTransform.POLARITY_BIPOLAR); + } else if (source == ModelSource.SOURCE_LFO1 + || source == ModelSource.SOURCE_LFO2) { + ((ModelStandardTransform)s.getTransform()).setPolarity( + ModelStandardTransform.POLARITY_BIPOLAR); + } + s.setIdentifier(source); + block.addSource(s); + src = s; + } + ModelDestination destination = new ModelDestination(); + destination.setIdentifier(destination_id); + block.setDestination(destination); + + if (mod.getVersion() == 1) { + //if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { + // ((ModelStandardTransform)destination.getTransform()) + // .setTransform( + // ModelStandardTransform.TRANSFORM_CONCAVE); + //} + if (mod.getTransform() == DLSModulator.CONN_TRN_CONCAVE) { + if (src != null) { + ((ModelStandardTransform)src.getTransform()) + .setTransform( + ModelStandardTransform.TRANSFORM_CONCAVE); + ((ModelStandardTransform)src.getTransform()) + .setDirection( + ModelStandardTransform.DIRECTION_MAX2MIN); + } + if (ctrl != null) { + ((ModelStandardTransform)ctrl.getTransform()) + .setTransform( + ModelStandardTransform.TRANSFORM_CONCAVE); + ((ModelStandardTransform)ctrl.getTransform()) + .setDirection( + ModelStandardTransform.DIRECTION_MAX2MIN); + } + } + + } else if (mod.getVersion() == 2) { + int transform = mod.getTransform(); + int src_transform_invert = (transform >> 15) & 1; + int src_transform_bipolar = (transform >> 14) & 1; + int src_transform = (transform >> 10) & 8; + int ctr_transform_invert = (transform >> 9) & 1; + int ctr_transform_bipolar = (transform >> 8) & 1; + int ctr_transform = (transform >> 4) & 8; + + + if (src != null) { + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if (src_transform == DLSModulator.CONN_TRN_SWITCH) + trans = ModelStandardTransform.TRANSFORM_SWITCH; + if (src_transform == DLSModulator.CONN_TRN_CONCAVE) + trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if (src_transform == DLSModulator.CONN_TRN_CONVEX) + trans = ModelStandardTransform.TRANSFORM_CONVEX; + ((ModelStandardTransform)src.getTransform()) + .setTransform(trans); + ((ModelStandardTransform)src.getTransform()) + .setPolarity(src_transform_bipolar == 1); + ((ModelStandardTransform)src.getTransform()) + .setDirection(src_transform_invert == 1); + + } + + if (ctrl != null) { + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if (ctr_transform == DLSModulator.CONN_TRN_SWITCH) + trans = ModelStandardTransform.TRANSFORM_SWITCH; + if (ctr_transform == DLSModulator.CONN_TRN_CONCAVE) + trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if (ctr_transform == DLSModulator.CONN_TRN_CONVEX) + trans = ModelStandardTransform.TRANSFORM_CONVEX; + ((ModelStandardTransform)ctrl.getTransform()) + .setTransform(trans); + ((ModelStandardTransform)ctrl.getTransform()) + .setPolarity(ctr_transform_bipolar == 1); + ((ModelStandardTransform)ctrl.getTransform()) + .setDirection(ctr_transform_invert == 1); + } + + /* No output transforms are defined the DLS Level 2 + int out_transform = transform % 8; + int trans = ModelStandardTransform.TRANSFORM_LINEAR; + if (out_transform == DLSModulator.CONN_TRN_SWITCH) + trans = ModelStandardTransform.TRANSFORM_SWITCH; + if (out_transform == DLSModulator.CONN_TRN_CONCAVE) + trans = ModelStandardTransform.TRANSFORM_CONCAVE; + if (out_transform == DLSModulator.CONN_TRN_CONVEX) + trans = ModelStandardTransform.TRANSFORM_CONVEX; + if (ctrl != null) { + ((ModelStandardTransform)destination.getTransform()) + .setTransform(trans); + } + */ + + } + + block.setScale(f_scale); + + return block; + } + + return null; + } + + public ModelPerformer[] getPerformers() { + List performers = new ArrayList(); + + Map modmap = new HashMap(); + for (DLSModulator mod: getModulators()) { + modmap.put(mod.getSource() + "x" + mod.getControl() + "=" + + mod.getDestination(), mod); + } + + Map insmodmap = + new HashMap(); + + for (DLSRegion zone: regions) { + ModelPerformer performer = new ModelPerformer(); + performer.setName(zone.getSample().getName()); + performer.setSelfNonExclusive((zone.getFusoptions() & + DLSRegion.OPTION_SELFNONEXCLUSIVE) != 0); + performer.setExclusiveClass(zone.getExclusiveClass()); + performer.setKeyFrom(zone.getKeyfrom()); + performer.setKeyTo(zone.getKeyto()); + performer.setVelFrom(zone.getVelfrom()); + performer.setVelTo(zone.getVelto()); + + insmodmap.clear(); + insmodmap.putAll(modmap); + for (DLSModulator mod: zone.getModulators()) { + insmodmap.put(mod.getSource() + "x" + mod.getControl() + "=" + + mod.getDestination(), mod); + } + + List blocks = performer.getConnectionBlocks(); + for (DLSModulator mod: insmodmap.values()) { + ModelConnectionBlock p = convertToModel(mod); + if (p != null) + blocks.add(p); + } + + + DLSSample sample = zone.getSample(); + DLSSampleOptions sampleopt = zone.getSampleoptions(); + if (sampleopt == null) + sampleopt = sample.getSampleoptions(); + + ModelByteBuffer buff = sample.getDataBuffer(); + + float pitchcorrection = (-sampleopt.unitynote * 100) + + sampleopt.finetune; + + ModelByteBufferWavetable osc = new ModelByteBufferWavetable(buff, + sample.getFormat(), pitchcorrection); + osc.setAttenuation(osc.getAttenuation() / 65536f); + if (sampleopt.getLoops().size() != 0) { + DLSSampleLoop loop = sampleopt.getLoops().get(0); + osc.setLoopStart((int)loop.getStart()); + osc.setLoopLength((int)loop.getLength()); + if (loop.getType() == DLSSampleLoop.LOOP_TYPE_FORWARD) + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + if (loop.getType() == DLSSampleLoop.LOOP_TYPE_RELEASE) + osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); + else + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + } + + performer.getConnectionBlocks().add( + new ModelConnectionBlock(SoftFilter.FILTERTYPE_LP12, + new ModelDestination( + new ModelIdentifier("filter", "type", 1)))); + + performer.getOscillators().add(osc); + + performers.add(performer); + + } + + return performers.toArray(new ModelPerformer[performers.size()]); + } + + public byte[] getGuid() { + return guid; + } + + public void setGuid(byte[] guid) { + this.guid = guid; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java b/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java new file mode 100644 index 00000000000..082454ea980 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSModulator.java @@ -0,0 +1,351 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class is used to store modulator/artiuclation data. + * A modulator connects one synthesizer source to + * a destination. For example a note on velocity + * can be mapped to the gain of the synthesized voice. + * It is stored as a "art1" or "art2" chunk inside DLS files. + * + * @author Karl Helgason + */ +public class DLSModulator { + + // DLS1 Destinations + public static final int CONN_DST_NONE = 0x000; // 0 + public static final int CONN_DST_GAIN = 0x001; // cB + public static final int CONN_DST_PITCH = 0x003; // cent + public static final int CONN_DST_PAN = 0x004; // 0.1% + public static final int CONN_DST_LFO_FREQUENCY = 0x104; // cent (default 5 Hz) + public static final int CONN_DST_LFO_STARTDELAY = 0x105; // timecent + public static final int CONN_DST_EG1_ATTACKTIME = 0x206; // timecent + public static final int CONN_DST_EG1_DECAYTIME = 0x207; // timecent + public static final int CONN_DST_EG1_RELEASETIME = 0x209; // timecent + public static final int CONN_DST_EG1_SUSTAINLEVEL = 0x20A; // 0.1% + public static final int CONN_DST_EG2_ATTACKTIME = 0x30A; // timecent + public static final int CONN_DST_EG2_DECAYTIME = 0x30B; // timecent + public static final int CONN_DST_EG2_RELEASETIME = 0x30D; // timecent + public static final int CONN_DST_EG2_SUSTAINLEVEL = 0x30E; // 0.1% + // DLS2 Destinations + public static final int CONN_DST_KEYNUMBER = 0x005; + public static final int CONN_DST_LEFT = 0x010; // 0.1% + public static final int CONN_DST_RIGHT = 0x011; // 0.1% + public static final int CONN_DST_CENTER = 0x012; // 0.1% + public static final int CONN_DST_LEFTREAR = 0x013; // 0.1% + public static final int CONN_DST_RIGHTREAR = 0x014; // 0.1% + public static final int CONN_DST_LFE_CHANNEL = 0x015; // 0.1% + public static final int CONN_DST_CHORUS = 0x080; // 0.1% + public static final int CONN_DST_REVERB = 0x081; // 0.1% + public static final int CONN_DST_VIB_FREQUENCY = 0x114; // cent + public static final int CONN_DST_VIB_STARTDELAY = 0x115; // dB + public static final int CONN_DST_EG1_DELAYTIME = 0x20B; // timecent + public static final int CONN_DST_EG1_HOLDTIME = 0x20C; // timecent + public static final int CONN_DST_EG1_SHUTDOWNTIME = 0x20D; // timecent + public static final int CONN_DST_EG2_DELAYTIME = 0x30F; // timecent + public static final int CONN_DST_EG2_HOLDTIME = 0x310; // timecent + public static final int CONN_DST_FILTER_CUTOFF = 0x500; // cent + public static final int CONN_DST_FILTER_Q = 0x501; // dB + + // DLS1 Sources + public static final int CONN_SRC_NONE = 0x000; // 1 + public static final int CONN_SRC_LFO = 0x001; // linear (sine wave) + public static final int CONN_SRC_KEYONVELOCITY = 0x002; // ??db or velocity?? + public static final int CONN_SRC_KEYNUMBER = 0x003; // ??cent or keynumber?? + public static final int CONN_SRC_EG1 = 0x004; // linear direct from eg + public static final int CONN_SRC_EG2 = 0x005; // linear direct from eg + public static final int CONN_SRC_PITCHWHEEL = 0x006; // linear -1..1 + public static final int CONN_SRC_CC1 = 0x081; // linear 0..1 + public static final int CONN_SRC_CC7 = 0x087; // linear 0..1 + public static final int CONN_SRC_CC10 = 0x08A; // linear 0..1 + public static final int CONN_SRC_CC11 = 0x08B; // linear 0..1 + public static final int CONN_SRC_RPN0 = 0x100; // ?? // Pitch Bend Range + public static final int CONN_SRC_RPN1 = 0x101; // ?? // Fine Tune + public static final int CONN_SRC_RPN2 = 0x102; // ?? // Course Tune + // DLS2 Sources + public static final int CONN_SRC_POLYPRESSURE = 0x007; // linear 0..1 + public static final int CONN_SRC_CHANNELPRESSURE = 0x008; // linear 0..1 + public static final int CONN_SRC_VIBRATO = 0x009; // linear 0..1 + public static final int CONN_SRC_MONOPRESSURE = 0x00A; // linear 0..1 + public static final int CONN_SRC_CC91 = 0x0DB; // linear 0..1 + public static final int CONN_SRC_CC93 = 0x0DD; // linear 0..1 + // DLS1 Transforms + public static final int CONN_TRN_NONE = 0x000; + public static final int CONN_TRN_CONCAVE = 0x001; + // DLS2 Transforms + public static final int CONN_TRN_CONVEX = 0x002; + public static final int CONN_TRN_SWITCH = 0x003; + public static final int DST_FORMAT_CB = 1; + public static final int DST_FORMAT_CENT = 1; + public static final int DST_FORMAT_TIMECENT = 2; + public static final int DST_FORMAT_PERCENT = 3; + protected int source; + protected int control; + protected int destination; + protected int transform; + protected int scale; + protected int version = 1; + + public int getControl() { + return control; + } + + public void setControl(int control) { + this.control = control; + } + + public static int getDestinationFormat(int destination) { + + if (destination == CONN_DST_GAIN) + return DST_FORMAT_CB; + if (destination == CONN_DST_PITCH) + return DST_FORMAT_CENT; + if (destination == CONN_DST_PAN) + return DST_FORMAT_PERCENT; + + if (destination == CONN_DST_LFO_FREQUENCY) + return DST_FORMAT_CENT; + if (destination == CONN_DST_LFO_STARTDELAY) + return DST_FORMAT_TIMECENT; + + if (destination == CONN_DST_EG1_ATTACKTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG1_DECAYTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG1_RELEASETIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG1_SUSTAINLEVEL) + return DST_FORMAT_PERCENT; + + if (destination == CONN_DST_EG2_ATTACKTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG2_DECAYTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG2_RELEASETIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG2_SUSTAINLEVEL) + return DST_FORMAT_PERCENT; + + if (destination == CONN_DST_KEYNUMBER) + return DST_FORMAT_CENT; // NOT SURE WITHOUT DLS 2 SPEC + if (destination == CONN_DST_LEFT) + return DST_FORMAT_CB; + if (destination == CONN_DST_RIGHT) + return DST_FORMAT_CB; + if (destination == CONN_DST_CENTER) + return DST_FORMAT_CB; + if (destination == CONN_DST_LEFTREAR) + return DST_FORMAT_CB; + if (destination == CONN_DST_RIGHTREAR) + return DST_FORMAT_CB; + if (destination == CONN_DST_LFE_CHANNEL) + return DST_FORMAT_CB; + if (destination == CONN_DST_CHORUS) + return DST_FORMAT_PERCENT; + if (destination == CONN_DST_REVERB) + return DST_FORMAT_PERCENT; + + if (destination == CONN_DST_VIB_FREQUENCY) + return DST_FORMAT_CENT; + if (destination == CONN_DST_VIB_STARTDELAY) + return DST_FORMAT_TIMECENT; + + if (destination == CONN_DST_EG1_DELAYTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG1_HOLDTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG1_SHUTDOWNTIME) + return DST_FORMAT_TIMECENT; + + if (destination == CONN_DST_EG2_DELAYTIME) + return DST_FORMAT_TIMECENT; + if (destination == CONN_DST_EG2_HOLDTIME) + return DST_FORMAT_TIMECENT; + + if (destination == CONN_DST_FILTER_CUTOFF) + return DST_FORMAT_CENT; + if (destination == CONN_DST_FILTER_Q) + return DST_FORMAT_CB; + + return -1; + } + + public static String getDestinationName(int destination) { + + if (destination == CONN_DST_GAIN) + return "gain"; + if (destination == CONN_DST_PITCH) + return "pitch"; + if (destination == CONN_DST_PAN) + return "pan"; + + if (destination == CONN_DST_LFO_FREQUENCY) + return "lfo1.freq"; + if (destination == CONN_DST_LFO_STARTDELAY) + return "lfo1.delay"; + + if (destination == CONN_DST_EG1_ATTACKTIME) + return "eg1.attack"; + if (destination == CONN_DST_EG1_DECAYTIME) + return "eg1.decay"; + if (destination == CONN_DST_EG1_RELEASETIME) + return "eg1.release"; + if (destination == CONN_DST_EG1_SUSTAINLEVEL) + return "eg1.sustain"; + + if (destination == CONN_DST_EG2_ATTACKTIME) + return "eg2.attack"; + if (destination == CONN_DST_EG2_DECAYTIME) + return "eg2.decay"; + if (destination == CONN_DST_EG2_RELEASETIME) + return "eg2.release"; + if (destination == CONN_DST_EG2_SUSTAINLEVEL) + return "eg2.sustain"; + + if (destination == CONN_DST_KEYNUMBER) + return "keynumber"; + if (destination == CONN_DST_LEFT) + return "left"; + if (destination == CONN_DST_RIGHT) + return "right"; + if (destination == CONN_DST_CENTER) + return "center"; + if (destination == CONN_DST_LEFTREAR) + return "leftrear"; + if (destination == CONN_DST_RIGHTREAR) + return "rightrear"; + if (destination == CONN_DST_LFE_CHANNEL) + return "lfe_channel"; + if (destination == CONN_DST_CHORUS) + return "chorus"; + if (destination == CONN_DST_REVERB) + return "reverb"; + + if (destination == CONN_DST_VIB_FREQUENCY) + return "vib.freq"; + if (destination == CONN_DST_VIB_STARTDELAY) + return "vib.delay"; + + if (destination == CONN_DST_EG1_DELAYTIME) + return "eg1.delay"; + if (destination == CONN_DST_EG1_HOLDTIME) + return "eg1.hold"; + if (destination == CONN_DST_EG1_SHUTDOWNTIME) + return "eg1.shutdown"; + + if (destination == CONN_DST_EG2_DELAYTIME) + return "eg2.delay"; + if (destination == CONN_DST_EG2_HOLDTIME) + return "eg.2hold"; + + if (destination == CONN_DST_FILTER_CUTOFF) + return "filter.cutoff"; // NOT SURE WITHOUT DLS 2 SPEC + if (destination == CONN_DST_FILTER_Q) + return "filter.q"; // NOT SURE WITHOUT DLS 2 SPEC + + return null; + } + + public static String getSourceName(int source) { + + if (source == CONN_SRC_NONE) + return "none"; + if (source == CONN_SRC_LFO) + return "lfo"; + if (source == CONN_SRC_KEYONVELOCITY) + return "keyonvelocity"; + if (source == CONN_SRC_KEYNUMBER) + return "keynumber"; + if (source == CONN_SRC_EG1) + return "eg1"; + if (source == CONN_SRC_EG2) + return "eg2"; + if (source == CONN_SRC_PITCHWHEEL) + return "pitchweel"; + if (source == CONN_SRC_CC1) + return "cc1"; + if (source == CONN_SRC_CC7) + return "cc7"; + if (source == CONN_SRC_CC10) + return "c10"; + if (source == CONN_SRC_CC11) + return "cc11"; + + if (source == CONN_SRC_POLYPRESSURE) + return "polypressure"; + if (source == CONN_SRC_CHANNELPRESSURE) + return "channelpressure"; + if (source == CONN_SRC_VIBRATO) + return "vibrato"; + if (source == CONN_SRC_MONOPRESSURE) + return "monopressure"; + if (source == CONN_SRC_CC91) + return "cc91"; + if (source == CONN_SRC_CC93) + return "cc93"; + return null; + } + + public int getDestination() { + return destination; + } + + public void setDestination(int destination) { + this.destination = destination; + } + + public int getScale() { + return scale; + } + + public void setScale(int scale) { + this.scale = scale; + } + + public int getSource() { + return source; + } + + public void setSource(int source) { + this.source = source; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public int getTransform() { + return transform; + } + + public void setTransform(int transform) { + this.transform = transform; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java b/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java new file mode 100644 index 00000000000..17e57a3b3cf --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSRegion.java @@ -0,0 +1,150 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to store region parts for instrument. + * A region has a velocity and key range which it response to. + * And it has a list of modulators/articulators which + * is used how to synthesize a single voice. + * It is stored inside a "rgn " List Chunk inside DLS files. + * + * @author Karl Helgason + */ +public class DLSRegion { + + public final static int OPTION_SELFNONEXCLUSIVE = 0x0001; + protected List modulators = new ArrayList(); + protected int keyfrom; + protected int keyto; + protected int velfrom; + protected int velto; + protected int options; + protected int exclusiveClass; + protected int fusoptions; + protected int phasegroup; + protected long channel; + protected DLSSample sample = null; + protected DLSSampleOptions sampleoptions; + + public List getModulators() { + return modulators; + } + + public long getChannel() { + return channel; + } + + public void setChannel(long channel) { + this.channel = channel; + } + + public int getExclusiveClass() { + return exclusiveClass; + } + + public void setExclusiveClass(int exclusiveClass) { + this.exclusiveClass = exclusiveClass; + } + + public int getFusoptions() { + return fusoptions; + } + + public void setFusoptions(int fusoptions) { + this.fusoptions = fusoptions; + } + + public int getKeyfrom() { + return keyfrom; + } + + public void setKeyfrom(int keyfrom) { + this.keyfrom = keyfrom; + } + + public int getKeyto() { + return keyto; + } + + public void setKeyto(int keyto) { + this.keyto = keyto; + } + + public int getOptions() { + return options; + } + + public void setOptions(int options) { + this.options = options; + } + + public int getPhasegroup() { + return phasegroup; + } + + public void setPhasegroup(int phasegroup) { + this.phasegroup = phasegroup; + } + + public DLSSample getSample() { + return sample; + } + + public void setSample(DLSSample sample) { + this.sample = sample; + } + + public int getVelfrom() { + return velfrom; + } + + public void setVelfrom(int velfrom) { + this.velfrom = velfrom; + } + + public int getVelto() { + return velto; + } + + public void setVelto(int velto) { + this.velto = velto; + } + + public void setModulators(List modulators) { + this.modulators = modulators; + } + + public DLSSampleOptions getSampleoptions() { + return sampleoptions; + } + + public void setSampleoptions(DLSSampleOptions sampleOptions) { + this.sampleoptions = sampleOptions; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSSample.java b/jdk/src/share/classes/com/sun/media/sound/DLSSample.java new file mode 100644 index 00000000000..b75b2a9a94c --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSSample.java @@ -0,0 +1,122 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.InputStream; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * This class is used to store the sample data itself. + * A sample is encoded as PCM audio stream + * and in DLS Level 1 files it is always a mono 8/16 bit stream. + * They are stored just like RIFF WAVE files are stored. + * It is stored inside a "wave" List Chunk inside DLS files. + * + * @author Karl Helgason + */ +public class DLSSample extends SoundbankResource { + + protected byte[] guid = null; + protected DLSInfo info = new DLSInfo(); + protected DLSSampleOptions sampleoptions; + protected ModelByteBuffer data; + protected AudioFormat format; + + public DLSSample(Soundbank soundBank) { + super(soundBank, null, AudioInputStream.class); + } + + public DLSSample() { + super(null, null, AudioInputStream.class); + } + + public DLSInfo getInfo() { + return info; + } + + public Object getData() { + AudioFormat format = getFormat(); + + InputStream is = data.getInputStream(); + if (is == null) + return null; + return new AudioInputStream(is, format, data.capacity()); + } + + public ModelByteBuffer getDataBuffer() { + return data; + } + + public AudioFormat getFormat() { + return format; + } + + public void setFormat(AudioFormat format) { + this.format = format; + } + + public void setData(ModelByteBuffer data) { + this.data = data; + } + + public void setData(byte[] data) { + this.data = new ModelByteBuffer(data); + } + + public void setData(byte[] data, int offset, int length) { + this.data = new ModelByteBuffer(data, offset, length); + } + + public String getName() { + return info.name; + } + + public void setName(String name) { + info.name = name; + } + + public DLSSampleOptions getSampleoptions() { + return sampleoptions; + } + + public void setSampleoptions(DLSSampleOptions sampleOptions) { + this.sampleoptions = sampleOptions; + } + + public String toString() { + return "Sample: " + info.name; + } + + public byte[] getGuid() { + return guid; + } + + public void setGuid(byte[] guid) { + this.guid = guid; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java b/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java new file mode 100644 index 00000000000..ee78d64fce0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSSampleLoop.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class is used to store loop points inside DLSSampleOptions class. + * + * @author Karl Helgason + */ +public class DLSSampleLoop { + + public final static int LOOP_TYPE_FORWARD = 0; + public final static int LOOP_TYPE_RELEASE = 1; + protected long type; + protected long start; + protected long length; + + public long getLength() { + return length; + } + + public void setLength(long length) { + this.length = length; + } + + public long getStart() { + return start; + } + + public void setStart(long start) { + this.start = start; + } + + public long getType() { + return type; + } + + public void setType(long type) { + this.type = type; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java b/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java new file mode 100644 index 00000000000..849644b6cc7 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSSampleOptions.java @@ -0,0 +1,80 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class stores options how to playback sampled data like pitch/tuning, + * attenuation and loops. + * It is stored as a "wsmp" chunk inside DLS files. + * + * @author Karl Helgason + */ +public class DLSSampleOptions { + + protected int unitynote; + protected short finetune; + protected int attenuation; + protected long options; + protected List loops = new ArrayList(); + + public int getAttenuation() { + return attenuation; + } + + public void setAttenuation(int attenuation) { + this.attenuation = attenuation; + } + + public short getFinetune() { + return finetune; + } + + public void setFinetune(short finetune) { + this.finetune = finetune; + } + + public List getLoops() { + return loops; + } + + public long getOptions() { + return options; + } + + public void setOptions(long options) { + this.options = options; + } + + public int getUnitynote() { + return unitynote; + } + + public void setUnitynote(int unitynote) { + this.unitynote = unitynote; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java b/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java new file mode 100644 index 00000000000..027fa75b472 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java @@ -0,0 +1,1287 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * A DLS Level 1 and Level 2 soundbank reader (from files/url/streams). + * + * @author Karl Helgason + */ +public class DLSSoundbank implements Soundbank { + + static private class DLSID { + long i1; + int s1; + int s2; + int x1; + int x2; + int x3; + int x4; + int x5; + int x6; + int x7; + int x8; + + private DLSID() { + } + + public DLSID(long i1, int s1, int s2, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, int x8) { + this.i1 = i1; + this.s1 = s1; + this.s2 = s2; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + this.x4 = x4; + this.x5 = x5; + this.x6 = x6; + this.x7 = x7; + this.x8 = x8; + } + + public static DLSID read(RIFFReader riff) throws IOException { + DLSID d = new DLSID(); + d.i1 = riff.readUnsignedInt(); + d.s1 = riff.readUnsignedShort(); + d.s2 = riff.readUnsignedShort(); + d.x1 = riff.readUnsignedByte(); + d.x2 = riff.readUnsignedByte(); + d.x3 = riff.readUnsignedByte(); + d.x4 = riff.readUnsignedByte(); + d.x5 = riff.readUnsignedByte(); + d.x6 = riff.readUnsignedByte(); + d.x7 = riff.readUnsignedByte(); + d.x8 = riff.readUnsignedByte(); + return d; + } + + public int hashCode() { + return (int)i1; + } + + public boolean equals(Object obj) { + if (!(obj instanceof DLSID)) { + return false; + } + DLSID t = (DLSID) obj; + return i1 == t.i1 && s1 == t.s1 && s2 == t.s2 + && x1 == t.x1 && x2 == t.x2 && x3 == t.x3 && x4 == t.x4 + && x5 == t.x5 && x6 == t.x6 && x7 == t.x7 && x8 == t.x8; + } + } + + /** X = X & Y */ + private static final int DLS_CDL_AND = 0x0001; + /** X = X | Y */ + private static final int DLS_CDL_OR = 0x0002; + /** X = X ^ Y */ + private static final int DLS_CDL_XOR = 0x0003; + /** X = X + Y */ + private static final int DLS_CDL_ADD = 0x0004; + /** X = X - Y */ + private static final int DLS_CDL_SUBTRACT = 0x0005; + /** X = X * Y */ + private static final int DLS_CDL_MULTIPLY = 0x0006; + /** X = X / Y */ + private static final int DLS_CDL_DIVIDE = 0x0007; + /** X = X && Y */ + private static final int DLS_CDL_LOGICAL_AND = 0x0008; + /** X = X || Y */ + private static final int DLS_CDL_LOGICAL_OR = 0x0009; + /** X = (X < Y) */ + private static final int DLS_CDL_LT = 0x000A; + /** X = (X <= Y) */ + private static final int DLS_CDL_LE = 0x000B; + /** X = (X > Y) */ + private static final int DLS_CDL_GT = 0x000C; + /** X = (X >= Y) */ + private static final int DLS_CDL_GE = 0x000D; + /** X = (X == Y) */ + private static final int DLS_CDL_EQ = 0x000E; + /** X = !X */ + private static final int DLS_CDL_NOT = 0x000F; + /** 32-bit constant */ + private static final int DLS_CDL_CONST = 0x0010; + /** 32-bit value returned from query */ + private static final int DLS_CDL_QUERY = 0x0011; + /** 32-bit value returned from query */ + private static final int DLS_CDL_QUERYSUPPORTED = 0x0012; + + private static final DLSID DLSID_GMInHardware = new DLSID(0x178f2f24, + 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_GSInHardware = new DLSID(0x178f2f25, + 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_XGInHardware = new DLSID(0x178f2f26, + 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_SupportsDLS1 = new DLSID(0x178f2f27, + 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_SupportsDLS2 = new DLSID(0xf14599e5, + 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6); + private static final DLSID DLSID_SampleMemorySize = new DLSID(0x178f2f28, + 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); + private static final DLSID DLSID_ManufacturersID = new DLSID(0xb03e1181, + 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + private static final DLSID DLSID_ProductID = new DLSID(0xb03e1182, + 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713, + 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); + + private long major = -1; + private long minor = -1; + + private DLSInfo info = new DLSInfo(); + + private List instruments = new ArrayList(); + private List samples = new ArrayList(); + + private boolean largeFormat = false; + private File sampleFile; + + public DLSSoundbank() { + } + + public DLSSoundbank(URL url) throws IOException { + InputStream is = url.openStream(); + try { + readSoundbank(is); + } finally { + is.close(); + } + } + + public DLSSoundbank(File file) throws IOException { + largeFormat = true; + sampleFile = file; + InputStream is = new FileInputStream(file); + try { + readSoundbank(is); + } finally { + is.close(); + } + } + + public DLSSoundbank(InputStream inputstream) throws IOException { + readSoundbank(inputstream); + } + + private void readSoundbank(InputStream inputstream) throws IOException { + RIFFReader riff = new RIFFReader(inputstream); + if (!riff.getFormat().equals("RIFF")) { + throw new RIFFInvalidFormatException( + "Input stream is not a valid RIFF stream!"); + } + if (!riff.getType().equals("DLS ")) { + throw new RIFFInvalidFormatException( + "Input stream is not a valid DLS soundbank!"); + } + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("INFO")) + readInfoChunk(chunk); + if (chunk.getType().equals("lins")) + readLinsChunk(chunk); + if (chunk.getType().equals("wvpl")) + readWvplChunk(chunk); + } else { + if (chunk.getFormat().equals("cdl ")) { + if (!readCdlChunk(chunk)) { + throw new RIFFInvalidFormatException( + "DLS file isn't supported!"); + } + } + if (chunk.getFormat().equals("colh")) { + // skipped because we will load the entire bank into memory + // long instrumentcount = chunk.readUnsignedInt(); + // System.out.println("instrumentcount = "+ instrumentcount); + } + if (chunk.getFormat().equals("ptbl")) { + // Pool Table Chunk + // skipped because we will load the entire bank into memory + } + if (chunk.getFormat().equals("vers")) { + major = chunk.readUnsignedInt(); + minor = chunk.readUnsignedInt(); + } + } + } + + for (Map.Entry entry : temp_rgnassign.entrySet()) { + entry.getKey().sample = samples.get((int)entry.getValue().longValue()); + } + + temp_rgnassign = null; + } + + private boolean cdlIsQuerySupported(DLSID uuid) { + return uuid.equals(DLSID_GMInHardware) + || uuid.equals(DLSID_GSInHardware) + || uuid.equals(DLSID_XGInHardware) + || uuid.equals(DLSID_SupportsDLS1) + || uuid.equals(DLSID_SupportsDLS2) + || uuid.equals(DLSID_SampleMemorySize) + || uuid.equals(DLSID_ManufacturersID) + || uuid.equals(DLSID_ProductID) + || uuid.equals(DLSID_SamplePlaybackRate); + } + + private long cdlQuery(DLSID uuid) { + if (uuid.equals(DLSID_GMInHardware)) + return 1; + if (uuid.equals(DLSID_GSInHardware)) + return 0; + if (uuid.equals(DLSID_XGInHardware)) + return 0; + if (uuid.equals(DLSID_SupportsDLS1)) + return 1; + if (uuid.equals(DLSID_SupportsDLS2)) + return 1; + if (uuid.equals(DLSID_SampleMemorySize)) + return Runtime.getRuntime().totalMemory(); + if (uuid.equals(DLSID_ManufacturersID)) + return 0; + if (uuid.equals(DLSID_ProductID)) + return 0; + if (uuid.equals(DLSID_SamplePlaybackRate)) + return 44100; + return 0; + } + + + // Reading cdl-ck Chunk + // "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2 + private boolean readCdlChunk(RIFFReader riff) throws IOException { + + DLSID uuid; + long x; + long y; + Stack stack = new Stack(); + + while (riff.available() != 0) { + int opcode = riff.readUnsignedShort(); + switch (opcode) { + case DLS_CDL_AND: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0)); + break; + case DLS_CDL_OR: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0)); + break; + case DLS_CDL_XOR: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(((x != 0) ^ (y != 0)) ? 1 : 0)); + break; + case DLS_CDL_ADD: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(x + y)); + break; + case DLS_CDL_SUBTRACT: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(x - y)); + break; + case DLS_CDL_MULTIPLY: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(x * y)); + break; + case DLS_CDL_DIVIDE: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(x / y)); + break; + case DLS_CDL_LOGICAL_AND: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0)); + break; + case DLS_CDL_LOGICAL_OR: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0)); + break; + case DLS_CDL_LT: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x < y) ? 1 : 0)); + break; + case DLS_CDL_LE: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x <= y) ? 1 : 0)); + break; + case DLS_CDL_GT: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x > y) ? 1 : 0)); + break; + case DLS_CDL_GE: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x >= y) ? 1 : 0)); + break; + case DLS_CDL_EQ: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x == y) ? 1 : 0)); + break; + case DLS_CDL_NOT: + x = stack.pop(); + y = stack.pop(); + stack.push(Long.valueOf((x == 0) ? 1 : 0)); + break; + case DLS_CDL_CONST: + stack.push(Long.valueOf(riff.readUnsignedInt())); + break; + case DLS_CDL_QUERY: + uuid = DLSID.read(riff); + stack.push(cdlQuery(uuid)); + break; + case DLS_CDL_QUERYSUPPORTED: + uuid = DLSID.read(riff); + stack.push(Long.valueOf(cdlIsQuerySupported(uuid) ? 1 : 0)); + break; + default: + break; + } + } + if (stack.isEmpty()) + return false; + + return stack.pop() == 1; + } + + private void readInfoChunk(RIFFReader riff) throws IOException { + info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("INAM")) + info.name = chunk.readString(chunk.available()); + else if (format.equals("ICRD")) + info.creationDate = chunk.readString(chunk.available()); + else if (format.equals("IENG")) + info.engineers = chunk.readString(chunk.available()); + else if (format.equals("IPRD")) + info.product = chunk.readString(chunk.available()); + else if (format.equals("ICOP")) + info.copyright = chunk.readString(chunk.available()); + else if (format.equals("ICMT")) + info.comments = chunk.readString(chunk.available()); + else if (format.equals("ISFT")) + info.tools = chunk.readString(chunk.available()); + else if (format.equals("IARL")) + info.archival_location = chunk.readString(chunk.available()); + else if (format.equals("IART")) + info.artist = chunk.readString(chunk.available()); + else if (format.equals("ICMS")) + info.commissioned = chunk.readString(chunk.available()); + else if (format.equals("IGNR")) + info.genre = chunk.readString(chunk.available()); + else if (format.equals("IKEY")) + info.keywords = chunk.readString(chunk.available()); + else if (format.equals("IMED")) + info.medium = chunk.readString(chunk.available()); + else if (format.equals("ISBJ")) + info.subject = chunk.readString(chunk.available()); + else if (format.equals("ISRC")) + info.source = chunk.readString(chunk.available()); + else if (format.equals("ISRF")) + info.source_form = chunk.readString(chunk.available()); + else if (format.equals("ITCH")) + info.technician = chunk.readString(chunk.available()); + } + } + + private void readLinsChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("ins ")) + readInsChunk(chunk); + } + } + } + + private void readInsChunk(RIFFReader riff) throws IOException { + DLSInstrument instrument = new DLSInstrument(this); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("LIST")) { + if (chunk.getType().equals("INFO")) { + readInsInfoChunk(instrument, chunk); + } + if (chunk.getType().equals("lrgn")) { + while (chunk.hasNextChunk()) { + RIFFReader subchunk = chunk.nextChunk(); + if (subchunk.getFormat().equals("LIST")) { + if (subchunk.getType().equals("rgn ")) { + DLSRegion split = new DLSRegion(); + if (readRgnChunk(split, subchunk)) + instrument.getRegions().add(split); + } + if (subchunk.getType().equals("rgn2")) { + // support for DLS level 2 regions + DLSRegion split = new DLSRegion(); + if (readRgnChunk(split, subchunk)) + instrument.getRegions().add(split); + } + } + } + } + if (chunk.getType().equals("lart")) { + List modlist = new ArrayList(); + while (chunk.hasNextChunk()) { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) { + if (!readCdlChunk(chunk)) { + modlist.clear(); + break; + } + } + if (subchunk.getFormat().equals("art1")) + readArt1Chunk(modlist, subchunk); + } + instrument.getModulators().addAll(modlist); + } + if (chunk.getType().equals("lar2")) { + // support for DLS level 2 ART + List modlist = new ArrayList(); + while (chunk.hasNextChunk()) { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) { + if (!readCdlChunk(chunk)) { + modlist.clear(); + break; + } + } + if (subchunk.getFormat().equals("art2")) + readArt2Chunk(modlist, subchunk); + } + instrument.getModulators().addAll(modlist); + } + } else { + if (format.equals("dlid")) { + instrument.guid = new byte[16]; + chunk.readFully(instrument.guid); + } + if (format.equals("insh")) { + chunk.readUnsignedInt(); // Read Region Count - ignored + + int bank = chunk.read(); // LSB + bank += (chunk.read() & 127) << 7; // MSB + chunk.read(); // Read Reserved byte + int drumins = chunk.read(); // Drum Instrument + + int id = chunk.read() & 127; // Read only first 7 bits + chunk.read(); // Read Reserved byte + chunk.read(); // Read Reserved byte + chunk.read(); // Read Reserved byte + + instrument.bank = bank; + instrument.preset = (int) id; + instrument.druminstrument = (drumins & 128) > 0; + //System.out.println("bank="+bank+" drumkit="+drumkit + // +" id="+id); + } + + } + } + instruments.add(instrument); + } + + private void readArt1Chunk(List modulators, RIFFReader riff) + throws IOException { + long size = riff.readUnsignedInt(); + long count = riff.readUnsignedInt(); + + if (size - 8 != 0) + riff.skipBytes(size - 8); + + for (int i = 0; i < count; i++) { + DLSModulator modulator = new DLSModulator(); + modulator.version = 1; + modulator.source = riff.readUnsignedShort(); + modulator.control = riff.readUnsignedShort(); + modulator.destination = riff.readUnsignedShort(); + modulator.transform = riff.readUnsignedShort(); + modulator.scale = riff.readInt(); + modulators.add(modulator); + } + } + + private void readArt2Chunk(List modulators, RIFFReader riff) + throws IOException { + long size = riff.readUnsignedInt(); + long count = riff.readUnsignedInt(); + + if (size - 8 != 0) + riff.skipBytes(size - 8); + + for (int i = 0; i < count; i++) { + DLSModulator modulator = new DLSModulator(); + modulator.version = 2; + modulator.source = riff.readUnsignedShort(); + modulator.control = riff.readUnsignedShort(); + modulator.destination = riff.readUnsignedShort(); + modulator.transform = riff.readUnsignedShort(); + modulator.scale = riff.readInt(); + modulators.add(modulator); + } + } + + private Map temp_rgnassign = new HashMap(); + + private boolean readRgnChunk(DLSRegion split, RIFFReader riff) + throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("LIST")) { + if (chunk.getType().equals("lart")) { + List modlist = new ArrayList(); + while (chunk.hasNextChunk()) { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) { + if (!readCdlChunk(chunk)) { + modlist.clear(); + break; + } + } + if (subchunk.getFormat().equals("art1")) + readArt1Chunk(modlist, subchunk); + } + split.getModulators().addAll(modlist); + } + if (chunk.getType().equals("lar2")) { + // support for DLS level 2 ART + List modlist = new ArrayList(); + while (chunk.hasNextChunk()) { + RIFFReader subchunk = chunk.nextChunk(); + if (chunk.getFormat().equals("cdl ")) { + if (!readCdlChunk(chunk)) { + modlist.clear(); + break; + } + } + if (subchunk.getFormat().equals("art2")) + readArt2Chunk(modlist, subchunk); + } + split.getModulators().addAll(modlist); + } + } else { + + if (format.equals("cdl ")) { + if (!readCdlChunk(chunk)) + return false; + } + if (format.equals("rgnh")) { + split.keyfrom = chunk.readUnsignedShort(); + split.keyto = chunk.readUnsignedShort(); + split.velfrom = chunk.readUnsignedShort(); + split.velto = chunk.readUnsignedShort(); + split.options = chunk.readUnsignedShort(); + split.exclusiveClass = chunk.readUnsignedShort(); + } + if (format.equals("wlnk")) { + split.fusoptions = chunk.readUnsignedShort(); + split.phasegroup = chunk.readUnsignedShort(); + split.channel = chunk.readUnsignedInt(); + long sampleid = chunk.readUnsignedInt(); + temp_rgnassign.put(split, sampleid); + } + if (format.equals("wsmp")) { + split.sampleoptions = new DLSSampleOptions(); + readWsmpChunk(split.sampleoptions, chunk); + } + } + } + return true; + } + + private void readWsmpChunk(DLSSampleOptions sampleOptions, RIFFReader riff) + throws IOException { + long size = riff.readUnsignedInt(); + sampleOptions.unitynote = riff.readUnsignedShort(); + sampleOptions.finetune = riff.readShort(); + sampleOptions.attenuation = riff.readInt(); + sampleOptions.options = riff.readUnsignedInt(); + long loops = riff.readInt(); + + if (size > 20) + riff.skipBytes(size - 20); + + for (int i = 0; i < loops; i++) { + DLSSampleLoop loop = new DLSSampleLoop(); + long size2 = riff.readUnsignedInt(); + loop.type = riff.readUnsignedInt(); + loop.start = riff.readUnsignedInt(); + loop.length = riff.readUnsignedInt(); + sampleOptions.loops.add(loop); + if (size2 > 16) + riff.skipBytes(size2 - 16); + } + } + + private void readInsInfoChunk(DLSInstrument dlsinstrument, RIFFReader riff) + throws IOException { + dlsinstrument.info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("INAM")) { + dlsinstrument.info.name = chunk.readString(chunk.available()); + } else if (format.equals("ICRD")) { + dlsinstrument.info.creationDate = + chunk.readString(chunk.available()); + } else if (format.equals("IENG")) { + dlsinstrument.info.engineers = + chunk.readString(chunk.available()); + } else if (format.equals("IPRD")) { + dlsinstrument.info.product = chunk.readString(chunk.available()); + } else if (format.equals("ICOP")) { + dlsinstrument.info.copyright = + chunk.readString(chunk.available()); + } else if (format.equals("ICMT")) { + dlsinstrument.info.comments = + chunk.readString(chunk.available()); + } else if (format.equals("ISFT")) { + dlsinstrument.info.tools = chunk.readString(chunk.available()); + } else if (format.equals("IARL")) { + dlsinstrument.info.archival_location = + chunk.readString(chunk.available()); + } else if (format.equals("IART")) { + dlsinstrument.info.artist = chunk.readString(chunk.available()); + } else if (format.equals("ICMS")) { + dlsinstrument.info.commissioned = + chunk.readString(chunk.available()); + } else if (format.equals("IGNR")) { + dlsinstrument.info.genre = chunk.readString(chunk.available()); + } else if (format.equals("IKEY")) { + dlsinstrument.info.keywords = + chunk.readString(chunk.available()); + } else if (format.equals("IMED")) { + dlsinstrument.info.medium = chunk.readString(chunk.available()); + } else if (format.equals("ISBJ")) { + dlsinstrument.info.subject = chunk.readString(chunk.available()); + } else if (format.equals("ISRC")) { + dlsinstrument.info.source = chunk.readString(chunk.available()); + } else if (format.equals("ISRF")) { + dlsinstrument.info.source_form = + chunk.readString(chunk.available()); + } else if (format.equals("ITCH")) { + dlsinstrument.info.technician = + chunk.readString(chunk.available()); + } + } + } + + private void readWvplChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("wave")) + readWaveChunk(chunk); + } + } + } + + private void readWaveChunk(RIFFReader riff) throws IOException { + DLSSample sample = new DLSSample(this); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("LIST")) { + if (chunk.getType().equals("INFO")) { + readWaveInfoChunk(sample, chunk); + } + } else { + if (format.equals("dlid")) { + sample.guid = new byte[16]; + chunk.readFully(sample.guid); + } + + if (format.equals("fmt ")) { + int sampleformat = chunk.readUnsignedShort(); + if (sampleformat != 1 && sampleformat != 3) { + throw new RIFFInvalidDataException( + "Only PCM samples are supported!"); + } + int channels = chunk.readUnsignedShort(); + long samplerate = chunk.readUnsignedInt(); + // bytes per sec + /* long framerate = */ chunk.readUnsignedInt(); + // block align, framesize + int framesize = chunk.readUnsignedShort(); + int bits = chunk.readUnsignedShort(); + AudioFormat audioformat = null; + if (sampleformat == 1) { + if (bits == 8) { + audioformat = new AudioFormat( + Encoding.PCM_UNSIGNED, samplerate, bits, + channels, framesize, samplerate, false); + } else { + audioformat = new AudioFormat( + Encoding.PCM_SIGNED, samplerate, bits, + channels, framesize, samplerate, false); + } + } + if (sampleformat == 3) { + audioformat = new AudioFormat( + AudioFloatConverter.PCM_FLOAT, samplerate, bits, + channels, framesize, samplerate, false); + } + + sample.format = audioformat; + } + + if (format.equals("data")) { + if (largeFormat) { + sample.setData(new ModelByteBuffer(sampleFile, + chunk.getFilePointer(), chunk.available())); + } else { + byte[] buffer = new byte[chunk.available()]; + // chunk.read(buffer); + sample.setData(buffer); + + int read = 0; + int avail = chunk.available(); + while (read != avail) { + if (avail - read > 65536) { + chunk.readFully(buffer, read, 65536); + read += 65536; + } else { + chunk.readFully(buffer, read, avail - read); + read = avail; + } + } + } + } + + if (format.equals("wsmp")) { + sample.sampleoptions = new DLSSampleOptions(); + readWsmpChunk(sample.sampleoptions, chunk); + } + } + } + + samples.add(sample); + + } + + private void readWaveInfoChunk(DLSSample dlssample, RIFFReader riff) + throws IOException { + dlssample.info.name = null; + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("INAM")) { + dlssample.info.name = chunk.readString(chunk.available()); + } else if (format.equals("ICRD")) { + dlssample.info.creationDate = + chunk.readString(chunk.available()); + } else if (format.equals("IENG")) { + dlssample.info.engineers = chunk.readString(chunk.available()); + } else if (format.equals("IPRD")) { + dlssample.info.product = chunk.readString(chunk.available()); + } else if (format.equals("ICOP")) { + dlssample.info.copyright = chunk.readString(chunk.available()); + } else if (format.equals("ICMT")) { + dlssample.info.comments = chunk.readString(chunk.available()); + } else if (format.equals("ISFT")) { + dlssample.info.tools = chunk.readString(chunk.available()); + } else if (format.equals("IARL")) { + dlssample.info.archival_location = + chunk.readString(chunk.available()); + } else if (format.equals("IART")) { + dlssample.info.artist = chunk.readString(chunk.available()); + } else if (format.equals("ICMS")) { + dlssample.info.commissioned = + chunk.readString(chunk.available()); + } else if (format.equals("IGNR")) { + dlssample.info.genre = chunk.readString(chunk.available()); + } else if (format.equals("IKEY")) { + dlssample.info.keywords = chunk.readString(chunk.available()); + } else if (format.equals("IMED")) { + dlssample.info.medium = chunk.readString(chunk.available()); + } else if (format.equals("ISBJ")) { + dlssample.info.subject = chunk.readString(chunk.available()); + } else if (format.equals("ISRC")) { + dlssample.info.source = chunk.readString(chunk.available()); + } else if (format.equals("ISRF")) { + dlssample.info.source_form = chunk.readString(chunk.available()); + } else if (format.equals("ITCH")) { + dlssample.info.technician = chunk.readString(chunk.available()); + } + } + } + + public void save(String name) throws IOException { + writeSoundbank(new RIFFWriter(name, "DLS ")); + } + + public void save(File file) throws IOException { + writeSoundbank(new RIFFWriter(file, "DLS ")); + } + + public void save(OutputStream out) throws IOException { + writeSoundbank(new RIFFWriter(out, "DLS ")); + } + + private void writeSoundbank(RIFFWriter writer) throws IOException { + RIFFWriter colh_chunk = writer.writeChunk("colh"); + colh_chunk.writeUnsignedInt(instruments.size()); + + if (major != -1 && minor != -1) { + RIFFWriter vers_chunk = writer.writeChunk("vers"); + vers_chunk.writeUnsignedInt(major); + vers_chunk.writeUnsignedInt(minor); + } + + writeInstruments(writer.writeList("lins")); + + RIFFWriter ptbl = writer.writeChunk("ptbl"); + ptbl.writeUnsignedInt(8); + ptbl.writeUnsignedInt(samples.size()); + long ptbl_offset = writer.getFilePointer(); + for (int i = 0; i < samples.size(); i++) + ptbl.writeUnsignedInt(0); + + RIFFWriter wvpl = writer.writeList("wvpl"); + long off = wvpl.getFilePointer(); + List offsettable = new ArrayList(); + for (DLSSample sample : samples) { + offsettable.add(Long.valueOf(wvpl.getFilePointer() - off)); + writeSample(wvpl.writeList("wave"), sample); + } + + // small cheat, we are going to rewrite data back in wvpl + long bak = writer.getFilePointer(); + writer.seek(ptbl_offset); + writer.setWriteOverride(true); + for (Long offset : offsettable) + writer.writeUnsignedInt(offset.longValue()); + writer.setWriteOverride(false); + writer.seek(bak); + + writeInfo(writer.writeList("INFO"), info); + + writer.close(); + } + + private void writeSample(RIFFWriter writer, DLSSample sample) + throws IOException { + + AudioFormat audioformat = sample.getFormat(); + + Encoding encoding = audioformat.getEncoding(); + float sampleRate = audioformat.getSampleRate(); + int sampleSizeInBits = audioformat.getSampleSizeInBits(); + int channels = audioformat.getChannels(); + int frameSize = audioformat.getFrameSize(); + float frameRate = audioformat.getFrameRate(); + boolean bigEndian = audioformat.isBigEndian(); + + boolean convert_needed = false; + + if (audioformat.getSampleSizeInBits() == 8) { + if (!encoding.equals(Encoding.PCM_UNSIGNED)) { + encoding = Encoding.PCM_UNSIGNED; + convert_needed = true; + } + } else { + if (!encoding.equals(Encoding.PCM_SIGNED)) { + encoding = Encoding.PCM_SIGNED; + convert_needed = true; + } + if (bigEndian) { + bigEndian = false; + convert_needed = true; + } + } + + if (convert_needed) { + audioformat = new AudioFormat(encoding, sampleRate, + sampleSizeInBits, channels, frameSize, frameRate, bigEndian); + } + + // fmt + RIFFWriter fmt_chunk = writer.writeChunk("fmt "); + int sampleformat = 0; + if (audioformat.getEncoding().equals(Encoding.PCM_UNSIGNED)) + sampleformat = 1; + else if (audioformat.getEncoding().equals(Encoding.PCM_SIGNED)) + sampleformat = 1; + else if (audioformat.getEncoding().equals(AudioFloatConverter.PCM_FLOAT)) + sampleformat = 3; + + fmt_chunk.writeUnsignedShort(sampleformat); + fmt_chunk.writeUnsignedShort(audioformat.getChannels()); + fmt_chunk.writeUnsignedInt((long) audioformat.getSampleRate()); + long srate = ((long)audioformat.getFrameRate())*audioformat.getFrameSize(); + fmt_chunk.writeUnsignedInt(srate); + fmt_chunk.writeUnsignedShort(audioformat.getFrameSize()); + fmt_chunk.writeUnsignedShort(audioformat.getSampleSizeInBits()); + fmt_chunk.write(0); + fmt_chunk.write(0); + + writeSampleOptions(writer.writeChunk("wsmp"), sample.sampleoptions); + + if (convert_needed) { + RIFFWriter data_chunk = writer.writeChunk("data"); + AudioInputStream stream = AudioSystem.getAudioInputStream( + audioformat, (AudioInputStream)sample.getData()); + byte[] buff = new byte[1024]; + int ret; + while ((ret = stream.read(buff)) != -1) { + data_chunk.write(buff, 0, ret); + } + } else { + RIFFWriter data_chunk = writer.writeChunk("data"); + ModelByteBuffer databuff = sample.getDataBuffer(); + databuff.writeTo(data_chunk); + /* + data_chunk.write(databuff.array(), + databuff.arrayOffset(), + databuff.capacity()); + */ + } + + writeInfo(writer.writeList("INFO"), sample.info); + } + + private void writeInstruments(RIFFWriter writer) throws IOException { + for (DLSInstrument instrument : instruments) { + writeInstrument(writer.writeList("ins "), instrument); + } + } + + private void writeInstrument(RIFFWriter writer, DLSInstrument instrument) + throws IOException { + + int art1_count = 0; + int art2_count = 0; + for (DLSModulator modulator : instrument.getModulators()) { + if (modulator.version == 1) + art1_count++; + if (modulator.version == 2) + art2_count++; + } + for (DLSRegion region : instrument.regions) { + for (DLSModulator modulator : region.getModulators()) { + if (modulator.version == 1) + art1_count++; + if (modulator.version == 2) + art2_count++; + } + } + + int version = 1; + if (art2_count > 0) + version = 2; + + RIFFWriter insh_chunk = writer.writeChunk("insh"); + insh_chunk.writeUnsignedInt(instrument.getRegions().size()); + insh_chunk.writeUnsignedInt(instrument.bank + + (instrument.druminstrument ? 2147483648L : 0)); + insh_chunk.writeUnsignedInt(instrument.preset); + + RIFFWriter lrgn = writer.writeList("lrgn"); + for (DLSRegion region: instrument.regions) + writeRegion(lrgn, region, version); + + writeArticulators(writer, instrument.getModulators()); + + writeInfo(writer.writeList("INFO"), instrument.info); + + } + + private void writeArticulators(RIFFWriter writer, + List modulators) throws IOException { + int art1_count = 0; + int art2_count = 0; + for (DLSModulator modulator : modulators) { + if (modulator.version == 1) + art1_count++; + if (modulator.version == 2) + art2_count++; + } + if (art1_count > 0) { + RIFFWriter lar1 = writer.writeList("lart"); + RIFFWriter art1 = lar1.writeChunk("art1"); + art1.writeUnsignedInt(8); + art1.writeUnsignedInt(art1_count); + for (DLSModulator modulator : modulators) { + if (modulator.version == 1) { + art1.writeUnsignedShort(modulator.source); + art1.writeUnsignedShort(modulator.control); + art1.writeUnsignedShort(modulator.destination); + art1.writeUnsignedShort(modulator.transform); + art1.writeInt(modulator.scale); + } + } + } + if (art2_count > 0) { + RIFFWriter lar2 = writer.writeList("lar2"); + RIFFWriter art2 = lar2.writeChunk("art2"); + art2.writeUnsignedInt(8); + art2.writeUnsignedInt(art2_count); + for (DLSModulator modulator : modulators) { + if (modulator.version == 2) { + art2.writeUnsignedShort(modulator.source); + art2.writeUnsignedShort(modulator.control); + art2.writeUnsignedShort(modulator.destination); + art2.writeUnsignedShort(modulator.transform); + art2.writeInt(modulator.scale); + } + } + } + } + + private void writeRegion(RIFFWriter writer, DLSRegion region, int version) + throws IOException { + RIFFWriter rgns = null; + if (version == 1) + rgns = writer.writeList("rgn "); + if (version == 2) + rgns = writer.writeList("rgn2"); + if (rgns == null) + return; + + RIFFWriter rgnh = rgns.writeChunk("rgnh"); + rgnh.writeUnsignedShort(region.keyfrom); + rgnh.writeUnsignedShort(region.keyto); + rgnh.writeUnsignedShort(region.velfrom); + rgnh.writeUnsignedShort(region.velto); + rgnh.writeUnsignedShort(region.options); + rgnh.writeUnsignedShort(region.exclusiveClass); + + if (region.sampleoptions != null) + writeSampleOptions(rgns.writeChunk("wsmp"), region.sampleoptions); + + if (region.sample != null) { + if (samples.indexOf(region.sample) != -1) { + RIFFWriter wlnk = rgns.writeChunk("wlnk"); + wlnk.writeUnsignedShort(region.fusoptions); + wlnk.writeUnsignedShort(region.phasegroup); + wlnk.writeUnsignedInt(region.channel); + wlnk.writeUnsignedInt(samples.indexOf(region.sample)); + } + } + writeArticulators(rgns, region.getModulators()); + rgns.close(); + } + + private void writeSampleOptions(RIFFWriter wsmp, + DLSSampleOptions sampleoptions) throws IOException { + wsmp.writeUnsignedInt(20); + wsmp.writeUnsignedShort(sampleoptions.unitynote); + wsmp.writeShort(sampleoptions.finetune); + wsmp.writeInt(sampleoptions.attenuation); + wsmp.writeUnsignedInt(sampleoptions.options); + wsmp.writeInt(sampleoptions.loops.size()); + + for (DLSSampleLoop loop : sampleoptions.loops) { + wsmp.writeUnsignedInt(16); + wsmp.writeUnsignedInt(loop.type); + wsmp.writeUnsignedInt(loop.start); + wsmp.writeUnsignedInt(loop.length); + } + } + + private void writeInfoStringChunk(RIFFWriter writer, + String name, String value) throws IOException { + if (value == null) + return; + RIFFWriter chunk = writer.writeChunk(name); + chunk.writeString(value); + int len = value.getBytes("ascii").length; + chunk.write(0); + len++; + if (len % 2 != 0) + chunk.write(0); + } + + private void writeInfo(RIFFWriter writer, DLSInfo info) throws IOException { + writeInfoStringChunk(writer, "INAM", info.name); + writeInfoStringChunk(writer, "ICRD", info.creationDate); + writeInfoStringChunk(writer, "IENG", info.engineers); + writeInfoStringChunk(writer, "IPRD", info.product); + writeInfoStringChunk(writer, "ICOP", info.copyright); + writeInfoStringChunk(writer, "ICMT", info.comments); + writeInfoStringChunk(writer, "ISFT", info.tools); + writeInfoStringChunk(writer, "IARL", info.archival_location); + writeInfoStringChunk(writer, "IART", info.artist); + writeInfoStringChunk(writer, "ICMS", info.commissioned); + writeInfoStringChunk(writer, "IGNR", info.genre); + writeInfoStringChunk(writer, "IKEY", info.keywords); + writeInfoStringChunk(writer, "IMED", info.medium); + writeInfoStringChunk(writer, "ISBJ", info.subject); + writeInfoStringChunk(writer, "ISRC", info.source); + writeInfoStringChunk(writer, "ISRF", info.source_form); + writeInfoStringChunk(writer, "ITCH", info.technician); + } + + public DLSInfo getInfo() { + return info; + } + + public String getName() { + return info.name; + } + + public String getVersion() { + return major + "." + minor; + } + + public String getVendor() { + return info.engineers; + } + + public String getDescription() { + return info.comments; + } + + public void setName(String s) { + info.name = s; + } + + public void setVendor(String s) { + info.engineers = s; + } + + public void setDescription(String s) { + info.comments = s; + } + + public SoundbankResource[] getResources() { + SoundbankResource[] resources = new SoundbankResource[samples.size()]; + int j = 0; + for (int i = 0; i < samples.size(); i++) + resources[j++] = samples.get(i); + return resources; + } + + public DLSInstrument[] getInstruments() { + DLSInstrument[] inslist_array = + instruments.toArray(new DLSInstrument[instruments.size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public DLSSample[] getSamples() { + return samples.toArray(new DLSSample[samples.size()]); + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch) patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch) patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public void addResource(SoundbankResource resource) { + if (resource instanceof DLSInstrument) + instruments.add((DLSInstrument) resource); + if (resource instanceof DLSSample) + samples.add((DLSSample) resource); + } + + public void removeResource(SoundbankResource resource) { + if (resource instanceof DLSInstrument) + instruments.remove((DLSInstrument) resource); + if (resource instanceof DLSSample) + samples.remove((DLSSample) resource); + } + + public void addInstrument(DLSInstrument resource) { + instruments.add(resource); + } + + public void removeInstrument(DLSInstrument resource) { + instruments.remove(resource); + } + + public long getMajor() { + return major; + } + + public void setMajor(long major) { + this.major = major; + } + + public long getMinor() { + return minor; + } + + public void setMinor(long minor) { + this.minor = minor; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java b/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java new file mode 100644 index 00000000000..294384976af --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/DLSSoundbankReader.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * This class is used to connect the DLSSoundBank class + * to the SoundbankReader SPI interface. + * + * @author Karl Helgason + */ +public class DLSSoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) + throws InvalidMidiDataException, IOException { + try { + return new DLSSoundbank(url); + } catch (RIFFInvalidFormatException e) { + return null; + } catch(IOException ioe) { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + try { + stream.mark(512); + return new DLSSoundbank(stream); + } catch (RIFFInvalidFormatException e) { + stream.reset(); + return null; + } + } + + public Soundbank getSoundbank(File file) + throws InvalidMidiDataException, IOException { + try { + return new DLSSoundbank(file); + } catch (RIFFInvalidFormatException e) { + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/DirectAudioDevice.java b/jdk/src/share/classes/com/sun/media/sound/DirectAudioDevice.java index 754aebf6a44..7a4289b1a30 100644 --- a/jdk/src/share/classes/com/sun/media/sound/DirectAudioDevice.java +++ b/jdk/src/share/classes/com/sun/media/sound/DirectAudioDevice.java @@ -394,7 +394,12 @@ class DirectAudioDevice extends AbstractMixer { private float leftGain, rightGain; protected volatile boolean noService = false; // do not run the nService method + // Guards all native calls. protected Object lockNative = new Object(); + // Guards the lastOpened static variable in implOpen and implClose. + protected static Object lockLast = new Object(); + // Keeps track of last opened line, see implOpen "trick". + protected static DirectDL lastOpened; // CONSTRUCTOR protected DirectDL(DataLine.Info info, @@ -496,20 +501,50 @@ class DirectAudioDevice extends AbstractMixer { // align buffer to full frames bufferSize = ((int) bufferSize / format.getFrameSize()) * format.getFrameSize(); - id = nOpen(mixerIndex, deviceID, isSource, - encoding, - hardwareFormat.getSampleRate(), - hardwareFormat.getSampleSizeInBits(), - hardwareFormat.getFrameSize(), - hardwareFormat.getChannels(), - hardwareFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED), - hardwareFormat.isBigEndian(), - bufferSize); + synchronized(lockLast) { + id = nOpen(mixerIndex, deviceID, isSource, + encoding, + hardwareFormat.getSampleRate(), + hardwareFormat.getSampleSizeInBits(), + hardwareFormat.getFrameSize(), + hardwareFormat.getChannels(), + hardwareFormat.getEncoding().equals( + AudioFormat.Encoding.PCM_SIGNED), + hardwareFormat.isBigEndian(), + bufferSize); - if (id == 0) { - // TODO: nicer error messages... - throw new LineUnavailableException("line with format "+format+" not supported."); + if (id == 0) { + // Bah... Dirty trick. The most likely cause is an application + // already having a line open for this particular hardware + // format and forgetting about it. If so, silently close that + // implementation and try again. Unfortuantely we can only + // open one line per hardware format currently. + if (lastOpened != null + && hardwareFormat.matches(lastOpened.hardwareFormat)) { + lastOpened.implClose(); + lastOpened = null; + + id = nOpen(mixerIndex, deviceID, isSource, + encoding, + hardwareFormat.getSampleRate(), + hardwareFormat.getSampleSizeInBits(), + hardwareFormat.getFrameSize(), + hardwareFormat.getChannels(), + hardwareFormat.getEncoding().equals( + AudioFormat.Encoding.PCM_SIGNED), + hardwareFormat.isBigEndian(), + bufferSize); + } + + if (id == 0) { + // TODO: nicer error messages... + throw new LineUnavailableException( + "line with format "+format+" not supported."); + } + } + lastOpened = this; } + this.bufferSize = nGetBufferSize(id, isSource); if (this.bufferSize < 1) { // this is an error! @@ -580,12 +615,12 @@ class DirectAudioDevice extends AbstractMixer { } synchronized (lockNative) { nStop(id, isSource); - } - // need to set doIO to false before notifying the - // read/write thread, that's why isStartedRunning() - // cannot be used - doIO = false; + // need to set doIO to false before notifying the + // read/write thread, that's why isStartedRunning() + // cannot be used + doIO = false; + } // wake up any waiting threads synchronized(lock) { lock.notifyAll(); @@ -614,8 +649,12 @@ class DirectAudioDevice extends AbstractMixer { doIO = false; long oldID = id; id = 0; - synchronized (lockNative) { - nClose(oldID, isSource); + synchronized (lockLast) { + synchronized (lockNative) { + nClose(oldID, isSource); + if (lastOpened == this) + lastOpened = null; + } } bytePosition = 0; softwareConversionSize = 0; @@ -630,7 +669,8 @@ class DirectAudioDevice extends AbstractMixer { } int a = 0; synchronized (lockNative) { - a = nAvailable(id, isSource); + if (doIO) + a = nAvailable(id, isSource); } return a; } @@ -644,9 +684,9 @@ class DirectAudioDevice extends AbstractMixer { int counter = 0; long startPos = getLongFramePosition(); boolean posChanged = false; - while (!drained && doIO) { + while (!drained) { synchronized (lockNative) { - if ((id == 0) || !nIsStillDraining(id, isSource)) + if ((id == 0) || (!doIO) || !nIsStillDraining(id, isSource)) break; } // check every now and then for a new position @@ -686,7 +726,7 @@ class DirectAudioDevice extends AbstractMixer { lock.notifyAll(); } synchronized (lockNative) { - if (id != 0) { + if (id != 0 && doIO) { // then flush native buffers nFlush(id, isSource); } @@ -697,9 +737,10 @@ class DirectAudioDevice extends AbstractMixer { // replacement for getFramePosition (see AbstractDataLine) public long getLongFramePosition() { - long pos; + long pos = 0; synchronized (lockNative) { - pos = nGetBytePosition(id, isSource, bytePosition); + if (doIO) + pos = nGetBytePosition(id, isSource, bytePosition); } // hack because ALSA sometimes reports wrong framepos if (pos < 0) { @@ -745,11 +786,12 @@ class DirectAudioDevice extends AbstractMixer { } int written = 0; while (!flushing) { - int thisWritten; + int thisWritten = 0; synchronized (lockNative) { - thisWritten = nWrite(id, b, off, len, - softwareConversionSize, - leftGain, rightGain); + if (doIO) + thisWritten = nWrite(id, b, off, len, + softwareConversionSize, + leftGain, rightGain); if (thisWritten < 0) { // error in native layer break; @@ -972,9 +1014,10 @@ class DirectAudioDevice extends AbstractMixer { } int read = 0; while (doIO && !flushing) { - int thisRead; + int thisRead = 0; synchronized (lockNative) { - thisRead = nRead(id, b, off, len, softwareConversionSize); + if (doIO) + thisRead = nRead(id, b, off, len, softwareConversionSize); if (thisRead < 0) { // error in native layer break; @@ -1209,7 +1252,8 @@ class DirectAudioDevice extends AbstractMixer { // set new native position (if necessary) // this must come after the flush! synchronized (lockNative) { - nSetBytePosition(id, isSource, frames * frameSize); + if (doIO) + nSetBytePosition(id, isSource, frames * frameSize); } if (Printer.debug) Printer.debug(" DirectClip.setFramePosition: " diff --git a/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java b/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java new file mode 100644 index 00000000000..9e248641c05 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/EmergencySoundbank.java @@ -0,0 +1,2695 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Random; + +import javax.sound.midi.Patch; +import javax.sound.sampled.AudioFormat; + +/** + * Emergency Soundbank generator. + * Used when no other default soundbank can be found. + * + * @author Karl Helgason + */ +public class EmergencySoundbank { + + private final static String[] general_midi_instruments = { + "Acoustic Grand Piano", + "Bright Acoustic Piano", + "Electric Grand Piano", + "Honky-tonk Piano", + "Electric Piano 1", + "Electric Piano 2", + "Harpsichord", + "Clavi", + "Celesta", + "Glockenspiel", + "Music Box", + "Vibraphone", + "Marimba", + "Xylophone", + "Tubular Bells", + "Dulcimer", + "Drawbar Organ", + "Percussive Organ", + "Rock Organ", + "Church Organ", + "Reed Organ", + "Accordion", + "Harmonica", + "Tango Accordion", + "Acoustic Guitar (nylon)", + "Acoustic Guitar (steel)", + "Electric Guitar (jazz)", + "Electric Guitar (clean)", + "Electric Guitar (muted)", + "Overdriven Guitar", + "Distortion Guitar", + "Guitar harmonics", + "Acoustic Bass", + "Electric Bass (finger)", + "Electric Bass (pick)", + "Fretless Bass", + "Slap Bass 1", + "Slap Bass 2", + "Synth Bass 1", + "Synth Bass 2", + "Violin", + "Viola", + "Cello", + "Contrabass", + "Tremolo Strings", + "Pizzicato Strings", + "Orchestral Harp", + "Timpani", + "String Ensemble 1", + "String Ensemble 2", + "SynthStrings 1", + "SynthStrings 2", + "Choir Aahs", + "Voice Oohs", + "Synth Voice", + "Orchestra Hit", + "Trumpet", + "Trombone", + "Tuba", + "Muted Trumpet", + "French Horn", + "Brass Section", + "SynthBrass 1", + "SynthBrass 2", + "Soprano Sax", + "Alto Sax", + "Tenor Sax", + "Baritone Sax", + "Oboe", + "English Horn", + "Bassoon", + "Clarinet", + "Piccolo", + "Flute", + "Recorder", + "Pan Flute", + "Blown Bottle", + "Shakuhachi", + "Whistle", + "Ocarina", + "Lead 1 (square)", + "Lead 2 (sawtooth)", + "Lead 3 (calliope)", + "Lead 4 (chiff)", + "Lead 5 (charang)", + "Lead 6 (voice)", + "Lead 7 (fifths)", + "Lead 8 (bass + lead)", + "Pad 1 (new age)", + "Pad 2 (warm)", + "Pad 3 (polysynth)", + "Pad 4 (choir)", + "Pad 5 (bowed)", + "Pad 6 (metallic)", + "Pad 7 (halo)", + "Pad 8 (sweep)", + "FX 1 (rain)", + "FX 2 (soundtrack)", + "FX 3 (crystal)", + "FX 4 (atmosphere)", + "FX 5 (brightness)", + "FX 6 (goblins)", + "FX 7 (echoes)", + "FX 8 (sci-fi)", + "Sitar", + "Banjo", + "Shamisen", + "Koto", + "Kalimba", + "Bag pipe", + "Fiddle", + "Shanai", + "Tinkle Bell", + "Agogo", + "Steel Drums", + "Woodblock", + "Taiko Drum", + "Melodic Tom", + "Synth Drum", + "Reverse Cymbal", + "Guitar Fret Noise", + "Breath Noise", + "Seashore", + "Bird Tweet", + "Telephone Ring", + "Helicopter", + "Applause", + "Gunshot" + }; + + public static SF2Soundbank createSoundbank() throws Exception { + SF2Soundbank sf2 = new SF2Soundbank(); + sf2.setName("Emergency GM sound set"); + sf2.setVendor("Generated"); + sf2.setDescription("Emergency generated soundbank"); + + /* + * percussion instruments + */ + + SF2Layer bass_drum = new_bass_drum(sf2); + SF2Layer snare_drum = new_snare_drum(sf2); + SF2Layer tom = new_tom(sf2); + SF2Layer open_hihat = new_open_hihat(sf2); + SF2Layer closed_hihat = new_closed_hihat(sf2); + SF2Layer crash_cymbal = new_crash_cymbal(sf2); + SF2Layer side_stick = new_side_stick(sf2); + + SF2Layer[] drums = new SF2Layer[128]; + drums[35] = bass_drum; + drums[36] = bass_drum; + drums[38] = snare_drum; + drums[40] = snare_drum; + drums[41] = tom; + drums[43] = tom; + drums[45] = tom; + drums[47] = tom; + drums[48] = tom; + drums[50] = tom; + drums[42] = closed_hihat; + drums[44] = closed_hihat; + drums[46] = open_hihat; + drums[49] = crash_cymbal; + drums[51] = crash_cymbal; + drums[52] = crash_cymbal; + drums[55] = crash_cymbal; + drums[57] = crash_cymbal; + drums[59] = crash_cymbal; + + // Use side_stick for missing drums: + drums[37] = side_stick; + drums[39] = side_stick; + drums[53] = side_stick; + drums[54] = side_stick; + drums[56] = side_stick; + drums[58] = side_stick; + drums[69] = side_stick; + drums[70] = side_stick; + drums[75] = side_stick; + drums[60] = side_stick; + drums[61] = side_stick; + drums[62] = side_stick; + drums[63] = side_stick; + drums[64] = side_stick; + drums[65] = side_stick; + drums[66] = side_stick; + drums[67] = side_stick; + drums[68] = side_stick; + drums[71] = side_stick; + drums[72] = side_stick; + drums[73] = side_stick; + drums[74] = side_stick; + drums[76] = side_stick; + drums[77] = side_stick; + drums[78] = side_stick; + drums[79] = side_stick; + drums[80] = side_stick; + drums[81] = side_stick; + + + SF2Instrument drum_instrument = new SF2Instrument(sf2); + drum_instrument.setName("Standard Kit"); + drum_instrument.setPatch(new ModelPatch(0, 0, true)); + sf2.addInstrument(drum_instrument); + for (int i = 0; i < drums.length; i++) { + if (drums[i] != null) { + SF2InstrumentRegion region = new SF2InstrumentRegion(); + region.setLayer(drums[i]); + region.putBytes(SF2InstrumentRegion.GENERATOR_KEYRANGE, + new byte[]{(byte) i, (byte) i}); + drum_instrument.getRegions().add(region); + } + } + + + /* + * melodic instruments + */ + + SF2Layer gpiano = new_gpiano(sf2); + SF2Layer gpiano2 = new_gpiano2(sf2); + SF2Layer gpiano_hammer = new_piano_hammer(sf2); + SF2Layer piano1 = new_piano1(sf2); + SF2Layer epiano1 = new_epiano1(sf2); + SF2Layer epiano2 = new_epiano2(sf2); + + SF2Layer guitar = new_guitar1(sf2); + SF2Layer guitar_pick = new_guitar_pick(sf2); + SF2Layer guitar_dist = new_guitar_dist(sf2); + SF2Layer bass1 = new_bass1(sf2); + SF2Layer bass2 = new_bass2(sf2); + SF2Layer synthbass = new_synthbass(sf2); + SF2Layer string2 = new_string2(sf2); + SF2Layer orchhit = new_orchhit(sf2); + SF2Layer choir = new_choir(sf2); + SF2Layer solostring = new_solostring(sf2); + SF2Layer organ = new_organ(sf2); + SF2Layer ch_organ = new_ch_organ(sf2); + SF2Layer bell = new_bell(sf2); + SF2Layer flute = new_flute(sf2); + + SF2Layer timpani = new_timpani(sf2); + SF2Layer melodic_toms = new_melodic_toms(sf2); + SF2Layer trumpet = new_trumpet(sf2); + SF2Layer trombone = new_trombone(sf2); + SF2Layer brass_section = new_brass_section(sf2); + SF2Layer horn = new_horn(sf2); + SF2Layer sax = new_sax(sf2); + SF2Layer oboe = new_oboe(sf2); + SF2Layer bassoon = new_bassoon(sf2); + SF2Layer clarinet = new_clarinet(sf2); + SF2Layer reverse_cymbal = new_reverse_cymbal(sf2); + + SF2Layer defaultsound = piano1; + + newInstrument(sf2, "Piano", new Patch(0, 0), gpiano, gpiano_hammer); + newInstrument(sf2, "Piano", new Patch(0, 1), gpiano2, gpiano_hammer); + newInstrument(sf2, "Piano", new Patch(0, 2), piano1); + { + SF2Instrument ins = newInstrument(sf2, "Honky-tonk Piano", + new Patch(0, 3), piano1, piano1); + SF2InstrumentRegion region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 80); + region.putInteger(SF2Region.GENERATOR_FINETUNE, 30); + region = ins.getRegions().get(1); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 30); + } + newInstrument(sf2, "Rhodes", new Patch(0, 4), epiano2); + newInstrument(sf2, "Rhodes", new Patch(0, 5), epiano2); + newInstrument(sf2, "Clavinet", new Patch(0, 6), epiano1); + newInstrument(sf2, "Clavinet", new Patch(0, 7), epiano1); + newInstrument(sf2, "Rhodes", new Patch(0, 8), epiano2); + newInstrument(sf2, "Bell", new Patch(0, 9), bell); + newInstrument(sf2, "Bell", new Patch(0, 10), bell); + newInstrument(sf2, "Vibraphone", new Patch(0, 11), bell); + newInstrument(sf2, "Marimba", new Patch(0, 12), bell); + newInstrument(sf2, "Marimba", new Patch(0, 13), bell); + newInstrument(sf2, "Bell", new Patch(0, 14), bell); + newInstrument(sf2, "Rock Organ", new Patch(0, 15), organ); + newInstrument(sf2, "Rock Organ", new Patch(0, 16), organ); + newInstrument(sf2, "Perc Organ", new Patch(0, 17), organ); + newInstrument(sf2, "Rock Organ", new Patch(0, 18), organ); + newInstrument(sf2, "Church Organ", new Patch(0, 19), ch_organ); + newInstrument(sf2, "Accordion", new Patch(0, 20), organ); + newInstrument(sf2, "Accordion", new Patch(0, 21), organ); + newInstrument(sf2, "Accordion", new Patch(0, 22), organ); + newInstrument(sf2, "Accordion", new Patch(0, 23), organ); + newInstrument(sf2, "Guitar", new Patch(0, 24), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 25), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 26), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 27), guitar, guitar_pick); + newInstrument(sf2, "Guitar", new Patch(0, 28), guitar, guitar_pick); + newInstrument(sf2, "Distorted Guitar", new Patch(0, 29), guitar_dist); + newInstrument(sf2, "Distorted Guitar", new Patch(0, 30), guitar_dist); + newInstrument(sf2, "Guitar", new Patch(0, 31), guitar, guitar_pick); + newInstrument(sf2, "Finger Bass", new Patch(0, 32), bass1); + newInstrument(sf2, "Finger Bass", new Patch(0, 33), bass1); + newInstrument(sf2, "Finger Bass", new Patch(0, 34), bass1); + newInstrument(sf2, "Frettless Bass", new Patch(0, 35), bass2); + newInstrument(sf2, "Frettless Bass", new Patch(0, 36), bass2); + newInstrument(sf2, "Frettless Bass", new Patch(0, 37), bass2); + newInstrument(sf2, "Synth Bass1", new Patch(0, 38), synthbass); + newInstrument(sf2, "Synth Bass2", new Patch(0, 39), synthbass); + newInstrument(sf2, "Solo String", new Patch(0, 40), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 41), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 42), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 43), string2, solostring); + newInstrument(sf2, "Solo String", new Patch(0, 44), string2, solostring); + newInstrument(sf2, "Def", new Patch(0, 45), defaultsound); + newInstrument(sf2, "Harp", new Patch(0, 46), bell); + newInstrument(sf2, "Timpani", new Patch(0, 47), timpani); + newInstrument(sf2, "Strings", new Patch(0, 48), string2); + SF2Instrument slow_strings = + newInstrument(sf2, "Slow Strings", new Patch(0, 49), string2); + SF2InstrumentRegion region = slow_strings.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, 2500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 2000); + newInstrument(sf2, "Synth Strings", new Patch(0, 50), string2); + newInstrument(sf2, "Synth Strings", new Patch(0, 51), string2); + + + newInstrument(sf2, "Choir", new Patch(0, 52), choir); + newInstrument(sf2, "Choir", new Patch(0, 53), choir); + newInstrument(sf2, "Choir", new Patch(0, 54), choir); + { + SF2Instrument ins = newInstrument(sf2, "Orch Hit", + new Patch(0, 55), orchhit, orchhit, timpani); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_COARSETUNE, -12); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + } + newInstrument(sf2, "Trumpet", new Patch(0, 56), trumpet); + newInstrument(sf2, "Trombone", new Patch(0, 57), trombone); + newInstrument(sf2, "Trombone", new Patch(0, 58), trombone); + newInstrument(sf2, "Trumpet", new Patch(0, 59), trumpet); + newInstrument(sf2, "Horn", new Patch(0, 60), horn); + newInstrument(sf2, "Brass Section", new Patch(0, 61), brass_section); + newInstrument(sf2, "Brass Section", new Patch(0, 62), brass_section); + newInstrument(sf2, "Brass Section", new Patch(0, 63), brass_section); + newInstrument(sf2, "Sax", new Patch(0, 64), sax); + newInstrument(sf2, "Sax", new Patch(0, 65), sax); + newInstrument(sf2, "Sax", new Patch(0, 66), sax); + newInstrument(sf2, "Sax", new Patch(0, 67), sax); + newInstrument(sf2, "Oboe", new Patch(0, 68), oboe); + newInstrument(sf2, "Horn", new Patch(0, 69), horn); + newInstrument(sf2, "Bassoon", new Patch(0, 70), bassoon); + newInstrument(sf2, "Clarinet", new Patch(0, 71), clarinet); + newInstrument(sf2, "Flute", new Patch(0, 72), flute); + newInstrument(sf2, "Flute", new Patch(0, 73), flute); + newInstrument(sf2, "Flute", new Patch(0, 74), flute); + newInstrument(sf2, "Flute", new Patch(0, 75), flute); + newInstrument(sf2, "Flute", new Patch(0, 76), flute); + newInstrument(sf2, "Flute", new Patch(0, 77), flute); + newInstrument(sf2, "Flute", new Patch(0, 78), flute); + newInstrument(sf2, "Flute", new Patch(0, 79), flute); + newInstrument(sf2, "Organ", new Patch(0, 80), organ); + newInstrument(sf2, "Organ", new Patch(0, 81), organ); + newInstrument(sf2, "Flute", new Patch(0, 82), flute); + newInstrument(sf2, "Organ", new Patch(0, 83), organ); + newInstrument(sf2, "Organ", new Patch(0, 84), organ); + newInstrument(sf2, "Choir", new Patch(0, 85), choir); + newInstrument(sf2, "Organ", new Patch(0, 86), organ); + newInstrument(sf2, "Organ", new Patch(0, 87), organ); + newInstrument(sf2, "Synth Strings", new Patch(0, 88), string2); + newInstrument(sf2, "Organ", new Patch(0, 89), organ); + newInstrument(sf2, "Def", new Patch(0, 90), defaultsound); + newInstrument(sf2, "Choir", new Patch(0, 91), choir); + newInstrument(sf2, "Organ", new Patch(0, 92), organ); + newInstrument(sf2, "Organ", new Patch(0, 93), organ); + newInstrument(sf2, "Organ", new Patch(0, 94), organ); + newInstrument(sf2, "Organ", new Patch(0, 95), organ); + newInstrument(sf2, "Organ", new Patch(0, 96), organ); + newInstrument(sf2, "Organ", new Patch(0, 97), organ); + newInstrument(sf2, "Bell", new Patch(0, 98), bell); + newInstrument(sf2, "Organ", new Patch(0, 99), organ); + newInstrument(sf2, "Organ", new Patch(0, 100), organ); + newInstrument(sf2, "Organ", new Patch(0, 101), organ); + newInstrument(sf2, "Def", new Patch(0, 102), defaultsound); + newInstrument(sf2, "Synth Strings", new Patch(0, 103), string2); + newInstrument(sf2, "Def", new Patch(0, 104), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 105), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 106), defaultsound); + newInstrument(sf2, "Def", new Patch(0, 107), defaultsound); + newInstrument(sf2, "Marimba", new Patch(0, 108), bell); + newInstrument(sf2, "Sax", new Patch(0, 109), sax); + newInstrument(sf2, "Solo String", new Patch(0, 110), string2, solostring); + newInstrument(sf2, "Oboe", new Patch(0, 111), oboe); + newInstrument(sf2, "Bell", new Patch(0, 112), bell); + newInstrument(sf2, "Melodic Toms", new Patch(0, 113), melodic_toms); + newInstrument(sf2, "Marimba", new Patch(0, 114), bell); + newInstrument(sf2, "Melodic Toms", new Patch(0, 115), melodic_toms); + newInstrument(sf2, "Melodic Toms", new Patch(0, 116), melodic_toms); + newInstrument(sf2, "Melodic Toms", new Patch(0, 117), melodic_toms); + newInstrument(sf2, "Reverse Cymbal", new Patch(0, 118), reverse_cymbal); + newInstrument(sf2, "Reverse Cymbal", new Patch(0, 119), reverse_cymbal); + newInstrument(sf2, "Guitar", new Patch(0, 120), guitar); + newInstrument(sf2, "Def", new Patch(0, 121), defaultsound); + { + SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", + new Patch(0, 122), reverse_cymbal); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500); + } + { + SF2Instrument ins = newInstrument(sf2, "Bird/Flute", + new Patch(0, 123), flute); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_COARSETUNE, 24); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -3000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + } + newInstrument(sf2, "Def", new Patch(0, 124), side_stick); + { + SF2Instrument ins = newInstrument(sf2, "Seashore/Reverse Cymbal", + new Patch(0, 125), reverse_cymbal); + region = ins.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 18500); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, -4500); + } + newInstrument(sf2, "Applause/crash_cymbal", + new Patch(0, 126), crash_cymbal); + newInstrument(sf2, "Gunshot/side_stick", new Patch(0, 127), side_stick); + + for (SF2Instrument instrument : sf2.getInstruments()) { + Patch patch = instrument.getPatch(); + if (patch instanceof ModelPatch) { + if (((ModelPatch) patch).isPercussion()) + continue; + } + instrument.setName(general_midi_instruments[patch.getProgram()]); + } + + return sf2; + + } + + public static SF2Layer new_bell(SF2Soundbank sf2) { + Random random = new Random(102030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble() * 2 - 1) * 0.01; + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1) * detune, w, a); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + public static SF2Layer new_guitar1(SF2Soundbank sf2) { + + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 2; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + + double[] aa = new double[40]; + for (int i = 0; i < 40; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] = 2; + aa[1] = 0.5; + aa[2] = 0.45; + aa[3] = 0.2; + aa[4] = 1; + aa[5] = 0.5; + aa[6] = 2; + aa[7] = 1; + aa[8] = 0.5; + aa[9] = 1; + aa[9] = 0.5; + aa[10] = 0.2; + aa[11] = 1; + aa[12] = 0.7; + aa[13] = 0.5; + aa[14] = 1; + + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Guitar", data, base); + SF2Layer layer = newLayer(sf2, "Guitar", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -6000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20); + return layer; + } + + public static SF2Layer new_guitar_dist(SF2Soundbank sf2) { + + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 2; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + + double[] aa = new double[40]; + for (int i = 0; i < 40; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] = 5; + aa[1] = 2; + aa[2] = 0.45; + aa[3] = 0.2; + aa[4] = 1; + aa[5] = 0.5; + aa[6] = 2; + aa[7] = 1; + aa[8] = 0.5; + aa[9] = 1; + aa[9] = 0.5; + aa[10] = 0.2; + aa[11] = 1; + aa[12] = 0.7; + aa[13] = 0.5; + aa[14] = 1; + + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + + + SF2Sample sample = newSimpleFFTSample_dist(sf2, "Distorted Guitar", + data, base, 10000.0); + + + SF2Layer layer = newLayer(sf2, "Distorted Guitar", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + //region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 2400); + //region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 200); + + //region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -100); + //region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + //region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -1000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000); + //region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -20); + return layer; + } + + public static SF2Layer new_guitar_pick(SF2Soundbank sf2) { + + double datab[]; + + // Make treble part + { + int m = 2; + int fftlen = 4096 * m; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)); + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 2048 * m; i++) { + data[i] *= Math.exp(-Math.abs((i - 23) / ((double) m)) * 1.2) + + Math.exp(-Math.abs((i - 40) / ((double) m)) * 0.9); + } + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9994; + } + datab = data; + + fadeUp(data, 80); + } + + SF2Sample sample = newSimpleDrumSample(sf2, "Guitar Noise", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Guitar Noise"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); +// region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); +/* + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0); + region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000); + */ + + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_gpiano(SF2Soundbank sf2) { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 15.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 2; + //aa[2] *= 0.1; + aa[4] *= 2; + + + aa[12] *= 0.9; + aa[13] *= 0.7; + for (int i = 14; i < 30; i++) { + aa[i] *= 0.5; + } + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if (i > 10) { + w = 5; + ai *= 10; + } + int adjust = 0; + if (i > 5) { + adjust = (i - 5) * 7; + } + complexGaussianDist(data, base * (i + 1) + adjust, w, ai); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200); + SF2Layer layer = newLayer(sf2, "Grand Piano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000); + return layer; + } + + public static SF2Layer new_gpiano2(SF2Soundbank sf2) { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 20.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 1; + //aa[2] *= 0.1; + aa[4] *= 2; + + + aa[12] *= 0.9; + aa[13] *= 0.7; + for (int i = 14; i < 30; i++) { + aa[i] *= 0.5; + } + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if (i > 10) { + w = 5; + ai *= 10; + } + int adjust = 0; + if (i > 5) { + adjust = (i - 5) * 7; + } + complexGaussianDist(data, base * (i + 1) + adjust, w, ai); + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Grand Piano", data, base, 200); + SF2Layer layer = newLayer(sf2, "Grand Piano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -7000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 18000); + return layer; + } + + public static SF2Layer new_piano_hammer(SF2Soundbank sf2) { + + double datab[]; + + // Make treble part + { + int m = 2; + int fftlen = 4096 * m; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)); + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 2048 * m; i++) + data[i] *= Math.exp(-Math.abs((i - 37) / ((double) m)) * 0.05); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.6); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9997; + } + datab = data; + + fadeUp(data, 80); + } + + SF2Sample sample = newSimpleDrumSample(sf2, "Piano Hammer", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Piano Hammer"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); +/* + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 0); + region.putInteger(SF2Region.GENERATOR_SUSTAINMODENV, 1000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -11000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 12000); + */ + + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_piano1(SF2Soundbank sf2) { + //Random random = new Random(302030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_a = 0.2; + double end_a = 0.0001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 5; + aa[2] *= 0.1; + aa[7] *= 5; + + + for (int i = 0; i < 30; i++) { + //double detune = 1 + (random.nextDouble()*2 - 1)*0.0001; + double w = 0.2; + double ai = aa[i]; + if (i > 12) { + w = 5; + ai *= 10; + } + int adjust = 0; + if (i > 5) { + adjust = (i - 5) * 7; + } + complexGaussianDist(data, base * (i + 1) + adjust, w, ai); + } + + complexGaussianDist(data, base * (15.5), 1, 0.1); + complexGaussianDist(data, base * (17.5), 1, 0.01); + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base, 200); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + public static SF2Layer new_epiano1(SF2Soundbank sf2) { + Random random = new Random(302030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.0001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble() * 2 - 1) * 0.0001; + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1) * detune, w, a); + a *= a_step; + } + + + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 1200); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + return layer; + } + + public static SF2Layer new_epiano2(SF2Soundbank sf2) { + Random random = new Random(302030201); + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.01; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + double detune = 1 + (random.nextDouble() * 2 - 1) * 0.0001; + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1) * detune, w, a); + a *= a_step; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "EPiano", data, base); + SF2Layer layer = newLayer(sf2, "EPiano", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 8000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, 2400); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -9000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 16000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_bass1(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.02; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 8; + aa[1] *= 4; + aa[3] *= 8; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base); + SF2Layer layer = newLayer(sf2, "Bass", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 11000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_synthbass(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.02; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 16; + aa[1] *= 4; + aa[3] *= 16; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass", data, base); + SF2Layer layer = newLayer(sf2, "Bass", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, -3000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 8000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_bass2(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 0.05; + double end_w = 0.05; + double start_a = 0.2; + double end_a = 0.002; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 25.0); + + double[] aa = new double[25]; + for (int i = 0; i < 25; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 8; + aa[1] *= 4; + aa[3] *= 8; + aa[5] *= 8; + + for (int i = 0; i < 25; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + + + SF2Sample sample = newSimpleFFTSample(sf2, "Bass2", data, base); + SF2Layer layer = newLayer(sf2, "Bass2", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + return layer; + } + + public static SF2Layer new_solostring(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 2; + double end_w = 2; + double start_a = 0.2; + double end_a = 0.01; + + double[] aa = new double[18]; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[0] *= 5; + aa[1] *= 5; + aa[2] *= 5; + aa[3] *= 4; + aa[4] *= 4; + aa[5] *= 3; + aa[6] *= 3; + aa[7] *= 2; + + for (int i = 0; i < aa.length; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, a); + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + region.putInteger(SF2Region.GENERATOR_FREQVIBLFO, -1000); + region.putInteger(SF2Region.GENERATOR_VIBLFOTOPITCH, 15); + return layer; + + } + + public static SF2Layer new_orchhit(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, a); + a *= a_step; + } + complexGaussianDist(data, base * 4, 300, 1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Och Strings", data, base); + SF2Layer layer = newLayer(sf2, "Och Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 200); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 200); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_string2(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, a); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_choir(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 25; + double start_w = 2; + double end_w = 80; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + double[] aa = new double[40]; + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[5] *= 0.1; + aa[6] *= 0.01; + aa[7] *= 0.1; + aa[8] *= 0.1; + + for (int i = 0; i < aa.length; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + } + SF2Sample sample = newSimpleFFTSample(sf2, "Strings", data, base); + SF2Layer layer = newLayer(sf2, "Strings", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -5000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_organ(SF2Soundbank sf2) { + Random random = new Random(102030201); + int x = 1; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + + for (int i = 0; i < 12; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, + a * (0.5 + 3 * (random.nextDouble()))); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base); + SF2Layer layer = newLayer(sf2, "Organ", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_ch_organ(SF2Soundbank sf2) { + int x = 1; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + double start_w = 0.01; + double end_w = 0.01; + double start_a = 0.2; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 60.0); + + double[] aa = new double[60]; + for (int i = 0; i < aa.length; i++) { + a *= a_step; + aa[i] = a; + } + + aa[0] *= 5; + aa[1] *= 2; + aa[2] = 0; + aa[4] = 0; + aa[5] = 0; + aa[7] *= 7; + aa[9] = 0; + aa[10] = 0; + aa[12] = 0; + aa[15] *= 7; + aa[18] = 0; + aa[20] = 0; + aa[24] = 0; + aa[27] *= 5; + aa[29] = 0; + aa[30] = 0; + aa[33] = 0; + aa[36] *= 4; + aa[37] = 0; + aa[39] = 0; + aa[42] = 0; + aa[43] = 0; + aa[47] = 0; + aa[50] *= 4; + aa[52] = 0; + aa[55] = 0; + aa[57] = 0; + + + aa[10] *= 0.1; + aa[11] *= 0.1; + aa[12] *= 0.1; + aa[13] *= 0.1; + + aa[17] *= 0.1; + aa[18] *= 0.1; + aa[19] *= 0.1; + aa[20] *= 0.1; + + for (int i = 0; i < 60; i++) { + double w = start_w + (end_w - start_w) * (i / 40.0); + complexGaussianDist(data, base * (i + 1), w, aa[i]); + a *= a_step; + } + SF2Sample sample = newSimpleFFTSample(sf2, "Organ", data, base); + SF2Layer layer = newLayer(sf2, "Organ", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + return layer; + + } + + public static SF2Layer new_flute(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + complexGaussianDist(data, base * 1, 0.001, 0.5); + complexGaussianDist(data, base * 2, 0.001, 0.5); + complexGaussianDist(data, base * 3, 0.001, 0.5); + complexGaussianDist(data, base * 4, 0.01, 0.5); + + complexGaussianDist(data, base * 4, 100, 120); + complexGaussianDist(data, base * 6, 100, 40); + complexGaussianDist(data, base * 8, 100, 80); + + complexGaussianDist(data, base * 5, 0.001, 0.05); + complexGaussianDist(data, base * 6, 0.001, 0.06); + complexGaussianDist(data, base * 7, 0.001, 0.04); + complexGaussianDist(data, base * 8, 0.005, 0.06); + complexGaussianDist(data, base * 9, 0.005, 0.06); + complexGaussianDist(data, base * 10, 0.01, 0.1); + complexGaussianDist(data, base * 11, 0.08, 0.7); + complexGaussianDist(data, base * 12, 0.08, 0.6); + complexGaussianDist(data, base * 13, 0.08, 0.6); + complexGaussianDist(data, base * 14, 0.08, 0.6); + complexGaussianDist(data, base * 15, 0.08, 0.5); + complexGaussianDist(data, base * 16, 0.08, 0.5); + complexGaussianDist(data, base * 17, 0.08, 0.2); + + + complexGaussianDist(data, base * 1, 10, 8); + complexGaussianDist(data, base * 2, 10, 8); + complexGaussianDist(data, base * 3, 10, 8); + complexGaussianDist(data, base * 4, 10, 8); + complexGaussianDist(data, base * 5, 10, 8); + complexGaussianDist(data, base * 6, 20, 9); + complexGaussianDist(data, base * 7, 20, 9); + complexGaussianDist(data, base * 8, 20, 9); + complexGaussianDist(data, base * 9, 20, 8); + complexGaussianDist(data, base * 10, 30, 8); + complexGaussianDist(data, base * 11, 30, 9); + complexGaussianDist(data, base * 12, 30, 9); + complexGaussianDist(data, base * 13, 30, 8); + complexGaussianDist(data, base * 14, 30, 8); + complexGaussianDist(data, base * 15, 30, 7); + complexGaussianDist(data, base * 16, 30, 7); + complexGaussianDist(data, base * 17, 30, 6); + + SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base); + SF2Layer layer = newLayer(sf2, "Flute", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_horn(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.00000000001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + if (i == 0) + complexGaussianDist(data, base * (i + 1), 0.1, a * 0.2); + else + complexGaussianDist(data, base * (i + 1), 0.1, a); + a *= a_step; + } + + complexGaussianDist(data, base * 2, 100, 1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Horn", data, base); + SF2Layer layer = newLayer(sf2, "Horn", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -500); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + public static SF2Layer new_trumpet(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.00001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 80.0); + double[] aa = new double[80]; + for (int i = 0; i < 80; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.05; + aa[1] *= 0.2; + aa[2] *= 0.5; + aa[3] *= 0.85; + + for (int i = 0; i < 80; i++) { + complexGaussianDist(data, base * (i + 1), 0.1, aa[i]); + } + + complexGaussianDist(data, base * 5, 300, 3); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Trumpet", data, base); + SF2Layer layer = newLayer(sf2, "Trumpet", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -10000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 0); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -4000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, -2500); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10); + return layer; + + } + + public static SF2Layer new_brass_section(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.005; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 30.0); + double[] aa = new double[30]; + for (int i = 0; i < 30; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.8; + aa[1] *= 0.9; + + double w = 5; + for (int i = 0; i < 30; i++) { + complexGaussianDist(data, base * (i + 1), 0.1 * w, aa[i] * w); + w += 6; //*= w_step; + } + + complexGaussianDist(data, base * 6, 300, 2); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Brass Section", data, base); + SF2Layer layer = newLayer(sf2, "Brass Section", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -9200); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + public static SF2Layer new_trombone(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.001; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 80.0); + double[] aa = new double[80]; + for (int i = 0; i < 80; i++) { + aa[i] = a; + a *= a_step; + } + + aa[0] *= 0.3; + aa[1] *= 0.7; + + for (int i = 0; i < 80; i++) { + complexGaussianDist(data, base * (i + 1), 0.1, aa[i]); + } + + complexGaussianDist(data, base * 6, 300, 2); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Trombone", data, base); + SF2Layer layer = newLayer(sf2, "Trombone", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -8000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -2000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERQ, 10); + return layer; + + } + + public static SF2Layer new_sax(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + double start_a = 0.5; + double end_a = 0.01; + double a = start_a; + double a_step = Math.pow(end_a / start_a, 1.0 / 40.0); + for (int i = 0; i < 40; i++) { + if (i == 0 || i == 2) + complexGaussianDist(data, base * (i + 1), 0.1, a * 4); + else + complexGaussianDist(data, base * (i + 1), 0.1, a); + a *= a_step; + } + + complexGaussianDist(data, base * 4, 200, 1); + + SF2Sample sample = newSimpleFFTSample(sf2, "Sax", data, base); + SF2Layer layer = newLayer(sf2, "Sax", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + + region.putInteger(SF2Region.GENERATOR_ATTACKMODENV, -3000); + region.putInteger(SF2Region.GENERATOR_RELEASEMODENV, 12000); + region.putInteger(SF2Region.GENERATOR_MODENVTOFILTERFC, 5000); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 4500); + return layer; + + } + + public static SF2Layer new_oboe(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + complexGaussianDist(data, base * 5, 100, 80); + + + complexGaussianDist(data, base * 1, 0.01, 0.53); + complexGaussianDist(data, base * 2, 0.01, 0.51); + complexGaussianDist(data, base * 3, 0.01, 0.48); + complexGaussianDist(data, base * 4, 0.01, 0.49); + complexGaussianDist(data, base * 5, 0.01, 5); + complexGaussianDist(data, base * 6, 0.01, 0.51); + complexGaussianDist(data, base * 7, 0.01, 0.50); + complexGaussianDist(data, base * 8, 0.01, 0.59); + complexGaussianDist(data, base * 9, 0.01, 0.61); + complexGaussianDist(data, base * 10, 0.01, 0.52); + complexGaussianDist(data, base * 11, 0.01, 0.49); + complexGaussianDist(data, base * 12, 0.01, 0.51); + complexGaussianDist(data, base * 13, 0.01, 0.48); + complexGaussianDist(data, base * 14, 0.01, 0.51); + complexGaussianDist(data, base * 15, 0.01, 0.46); + complexGaussianDist(data, base * 16, 0.01, 0.35); + complexGaussianDist(data, base * 17, 0.01, 0.20); + complexGaussianDist(data, base * 18, 0.01, 0.10); + complexGaussianDist(data, base * 19, 0.01, 0.5); + complexGaussianDist(data, base * 20, 0.01, 0.1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Oboe", data, base); + SF2Layer layer = newLayer(sf2, "Oboe", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_bassoon(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + complexGaussianDist(data, base * 2, 100, 40); + complexGaussianDist(data, base * 4, 100, 20); + + complexGaussianDist(data, base * 1, 0.01, 0.53); + complexGaussianDist(data, base * 2, 0.01, 5); + complexGaussianDist(data, base * 3, 0.01, 0.51); + complexGaussianDist(data, base * 4, 0.01, 0.48); + complexGaussianDist(data, base * 5, 0.01, 1.49); + complexGaussianDist(data, base * 6, 0.01, 0.51); + complexGaussianDist(data, base * 7, 0.01, 0.50); + complexGaussianDist(data, base * 8, 0.01, 0.59); + complexGaussianDist(data, base * 9, 0.01, 0.61); + complexGaussianDist(data, base * 10, 0.01, 0.52); + complexGaussianDist(data, base * 11, 0.01, 0.49); + complexGaussianDist(data, base * 12, 0.01, 0.51); + complexGaussianDist(data, base * 13, 0.01, 0.48); + complexGaussianDist(data, base * 14, 0.01, 0.51); + complexGaussianDist(data, base * 15, 0.01, 0.46); + complexGaussianDist(data, base * 16, 0.01, 0.35); + complexGaussianDist(data, base * 17, 0.01, 0.20); + complexGaussianDist(data, base * 18, 0.01, 0.10); + complexGaussianDist(data, base * 19, 0.01, 0.5); + complexGaussianDist(data, base * 20, 0.01, 0.1); + + + SF2Sample sample = newSimpleFFTSample(sf2, "Flute", data, base); + SF2Layer layer = newLayer(sf2, "Flute", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_clarinet(SF2Soundbank sf2) { + int x = 8; + int fftsize = 4096 * x; + double[] data = new double[fftsize * 2]; + double base = x * 15; + + complexGaussianDist(data, base * 1, 0.001, 0.5); + complexGaussianDist(data, base * 2, 0.001, 0.02); + complexGaussianDist(data, base * 3, 0.001, 0.2); + complexGaussianDist(data, base * 4, 0.01, 0.1); + + complexGaussianDist(data, base * 4, 100, 60); + complexGaussianDist(data, base * 6, 100, 20); + complexGaussianDist(data, base * 8, 100, 20); + + complexGaussianDist(data, base * 5, 0.001, 0.1); + complexGaussianDist(data, base * 6, 0.001, 0.09); + complexGaussianDist(data, base * 7, 0.001, 0.02); + complexGaussianDist(data, base * 8, 0.005, 0.16); + complexGaussianDist(data, base * 9, 0.005, 0.96); + complexGaussianDist(data, base * 10, 0.01, 0.9); + complexGaussianDist(data, base * 11, 0.08, 1.2); + complexGaussianDist(data, base * 12, 0.08, 1.8); + complexGaussianDist(data, base * 13, 0.08, 1.6); + complexGaussianDist(data, base * 14, 0.08, 1.2); + complexGaussianDist(data, base * 15, 0.08, 0.9); + complexGaussianDist(data, base * 16, 0.08, 0.5); + complexGaussianDist(data, base * 17, 0.08, 0.2); + + + complexGaussianDist(data, base * 1, 10, 8); + complexGaussianDist(data, base * 2, 10, 8); + complexGaussianDist(data, base * 3, 10, 8); + complexGaussianDist(data, base * 4, 10, 8); + complexGaussianDist(data, base * 5, 10, 8); + complexGaussianDist(data, base * 6, 20, 9); + complexGaussianDist(data, base * 7, 20, 9); + complexGaussianDist(data, base * 8, 20, 9); + complexGaussianDist(data, base * 9, 20, 8); + complexGaussianDist(data, base * 10, 30, 8); + complexGaussianDist(data, base * 11, 30, 9); + complexGaussianDist(data, base * 12, 30, 9); + complexGaussianDist(data, base * 13, 30, 8); + complexGaussianDist(data, base * 14, 30, 8); + complexGaussianDist(data, base * 15, 30, 7); + complexGaussianDist(data, base * 16, 30, 7); + complexGaussianDist(data, base * 17, 30, 6); + + SF2Sample sample = newSimpleFFTSample(sf2, "Clarinet", data, base); + SF2Layer layer = newLayer(sf2, "Clarinet", sample); + SF2Region region = layer.getRegions().get(0); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -6000); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 4000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, -100); + region.putInteger(SF2Region.GENERATOR_INITIALFILTERFC, 9500); + return layer; + + } + + public static SF2Layer new_timpani(SF2Soundbank sf2) { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096 * 8; + double[] data = new double[2 * fftlen]; + double base = 48; + complexGaussianDist(data, base * 2, 0.2, 1); + complexGaussianDist(data, base * 3, 0.2, 0.7); + complexGaussianDist(data, base * 5, 10, 1); + complexGaussianDist(data, base * 6, 9, 1); + complexGaussianDist(data, base * 8, 15, 1); + complexGaussianDist(data, base * 9, 18, 0.8); + complexGaussianDist(data, base * 11, 21, 0.5); + complexGaussianDist(data, base * 13, 28, 0.3); + complexGaussianDist(data, base * 14, 22, 0.1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.5); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) { + double g = (1.0 - (i / d_len)); + data[i] *= g * g; + } + fadeUp(data, 40); + datab = data; + } + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) { + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + } + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 300; i++) { + double g = (1.0 - (i / 300.0)); + data[i] *= 1.0 + 20 * g * g; + } + for (int i = 0; i < 24; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9998; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i] * 0.02; + + normalize(datab, 0.9); + + SF2Sample sample = newSimpleDrumSample(sf2, "Timpani", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Timpani"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_melodic_toms(SF2Soundbank sf2) { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + complexGaussianDist(data, 30, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i / d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 200; i++) { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20 * g * g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i] * 0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i / 5.0; + + normalize(datab, 0.99); + + SF2Sample sample = newSimpleDrumSample(sf2, "Melodic Toms", datab); + sample.setOriginalPitch(63); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Melodic Toms"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_reverse_cymbal(SF2Soundbank sf2) { + double datah[]; + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)); + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 100; i++) + data[i] = 0; + + for (int i = 0; i < 512 * 2; i++) { + double gain = (i / (512.0 * 2.0)); + data[i] = 1 - gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Reverse Cymbal", + datah, 100, 20); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Reverse Cymbal"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_ATTACKVOLENV, -200); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, -12000); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, -1000); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_snare_drum(SF2Soundbank sf2) { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + complexGaussianDist(data, 24, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.5); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i / d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 300; i++) { + double g = (1.0 - (i / 300.0)); + data[i] *= 1.0 + 20 * g * g; + } + for (int i = 0; i < 24; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9998; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i]; + for (int i = 0; i < 5; i++) + datab[i] *= i / 5.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Snare Drum", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Snare Drum"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_bass_drum(SF2Soundbank sf2) { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + complexGaussianDist(data, 1.8 * 5 + 1, 2, 1); + complexGaussianDist(data, 1.8 * 9 + 1, 2, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i / d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024; i < 2048; i++) + data[i] = 1.0 - (i - 1024) / 1024.0; + for (int i = 0; i < 512; i++) + data[i] = 10 * i / 512.0; + for (int i = 0; i < 10; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.999; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i] * 0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i / 5.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Bass Drum", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Bass Drum"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_tom(SF2Soundbank sf2) { + + double datab[]; + double datah[]; + + // Make Bass Part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + complexGaussianDist(data, 30, 0.5, 1); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.8); + data = realPart(data); + + double d_len = data.length; + for (int i = 0; i < data.length; i++) + data[i] *= (1.0 - (i / d_len)); + datab = data; + } + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 200; i++) { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20 * g * g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < datah.length; i++) + datab[i] += datah[i] * 0.5; + for (int i = 0; i < 5; i++) + datab[i] *= i / 5.0; + + normalize(datab, 0.99); + + SF2Sample sample = newSimpleDrumSample(sf2, "Tom", datab); + sample.setOriginalPitch(50); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Tom"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + //region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -100); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_closed_hihat(SF2Soundbank sf2) { + double datah[]; + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 2048; i++) + data[i] = 0.2 + 0.8 * (i / 2048.0); + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datah = data; + } + + for (int i = 0; i < 5; i++) + datah[i] *= i / 5.0; + SF2Sample sample = newSimpleDrumSample(sf2, "Closed Hi-Hat", datah); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Closed Hi-Hat"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_open_hihat(SF2Soundbank sf2) { + double datah[]; + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)); + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 200; i++) + data[i] = 0; + for (int i = 0; i < 2048 * 4; i++) { + double gain = (i / (2048.0 * 4.0)); + data[i] = gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Open Hi-Hat", datah, 1000, 5); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Open Hi-Hat"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1500); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1500); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_EXCLUSIVECLASS, 1); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_crash_cymbal(SF2Soundbank sf2) { + double datah[]; + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)); + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 0; i < 100; i++) + data[i] = 0; + for (int i = 0; i < 512 * 2; i++) { + double gain = (i / (512.0 * 2.0)); + data[i] = gain; + } + datah = data; + } + + SF2Sample sample = newSimpleFFTSample(sf2, "Crash Cymbal", datah, 1000, 5); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Crash Cymbal"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_DECAYVOLENV, 1800); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 1800); + region.putInteger(SF2Region.GENERATOR_SUSTAINVOLENV, 1000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + } + + public static SF2Layer new_side_stick(SF2Soundbank sf2) { + double datab[]; + + // Make treble part + { + int fftlen = 4096 * 4; + double[] data = new double[2 * fftlen]; + Random random = new Random(3049912); + for (int i = 0; i < data.length; i += 2) + data[i] = (2.0 * (random.nextDouble() - 0.5)) * 0.1; + fft(data); + // Remove all negative frequency + for (int i = fftlen / 2; i < data.length; i++) + data[i] = 0; + for (int i = 1024 * 4; i < 2048 * 4; i++) + data[i] = 1.0 - (i - 4096) / 4096.0; + for (int i = 0; i < 200; i++) { + double g = (1.0 - (i / 200.0)); + data[i] *= 1.0 + 20 * g * g; + } + for (int i = 0; i < 30; i++) + data[i] = 0; + randomPhase(data, new Random(3049912)); + ifft(data); + normalize(data, 0.9); + data = realPart(data); + double gain = 1.0; + for (int i = 0; i < data.length; i++) { + data[i] *= gain; + gain *= 0.9996; + } + datab = data; + } + + for (int i = 0; i < 10; i++) + datab[i] *= i / 10.0; + + SF2Sample sample = newSimpleDrumSample(sf2, "Side Stick", datab); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Side Stick"); + + SF2GlobalRegion global = new SF2GlobalRegion(); + layer.setGlobalZone(global); + sf2.addResource(layer); + + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_RELEASEVOLENV, 12000); + region.putInteger(SF2Region.GENERATOR_SCALETUNING, 0); + region.putInteger(SF2Region.GENERATOR_INITIALATTENUATION, -50); + region.setSample(sample); + layer.getRegions().add(region); + + return layer; + + } + + public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, + double[] data, double base) { + return newSimpleFFTSample(sf2, name, data, base, 10); + } + + public static SF2Sample newSimpleFFTSample(SF2Soundbank sf2, String name, + double[] data, double base, int fadeuptime) { + + int fftsize = data.length / 2; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + double basefreq = (base / fftsize) * format.getSampleRate() * 0.5; + + randomPhase(data); + ifft(data); + data = realPart(data); + normalize(data, 0.9); + float[] fdata = toFloat(data); + fdata = loopExtend(fdata, fdata.length + 512); + fadeUp(fdata, fadeuptime); + byte[] bdata = toBytes(fdata, format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize + 256); + sample.setSampleRate((long) format.getSampleRate()); + double orgnote = (69 + 12) + + (12 * Math.log(basefreq / 440.0) / Math.log(2)); + sample.setOriginalPitch((int) orgnote); + sample.setPitchCorrection((byte) (-(orgnote - (int) orgnote) * 100.0)); + sf2.addResource(sample); + + return sample; + } + + public static SF2Sample newSimpleFFTSample_dist(SF2Soundbank sf2, + String name, double[] data, double base, double preamp) { + + int fftsize = data.length / 2; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + double basefreq = (base / fftsize) * format.getSampleRate() * 0.5; + + randomPhase(data); + ifft(data); + data = realPart(data); + + for (int i = 0; i < data.length; i++) { + data[i] = (1 - Math.exp(-Math.abs(data[i] * preamp))) + * Math.signum(data[i]); + } + + normalize(data, 0.9); + float[] fdata = toFloat(data); + fdata = loopExtend(fdata, fdata.length + 512); + fadeUp(fdata, 80); + byte[] bdata = toBytes(fdata, format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize + 256); + sample.setSampleRate((long) format.getSampleRate()); + double orgnote = (69 + 12) + + (12 * Math.log(basefreq / 440.0) / Math.log(2)); + sample.setOriginalPitch((int) orgnote); + sample.setPitchCorrection((byte) (-(orgnote - (int) orgnote) * 100.0)); + sf2.addResource(sample); + + return sample; + } + + public static SF2Sample newSimpleDrumSample(SF2Soundbank sf2, String name, + double[] data) { + + int fftsize = data.length; + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + byte[] bdata = toBytes(toFloat(realPart(data)), format); + + /* + * Create SoundFont2 sample. + */ + SF2Sample sample = new SF2Sample(sf2); + sample.setName(name); + sample.setData(bdata); + sample.setStartLoop(256); + sample.setEndLoop(fftsize + 256); + sample.setSampleRate((long) format.getSampleRate()); + sample.setOriginalPitch(60); + sf2.addResource(sample); + + return sample; + } + + public static SF2Layer newLayer(SF2Soundbank sf2, String name, SF2Sample sample) { + SF2LayerRegion region = new SF2LayerRegion(); + region.setSample(sample); + + SF2Layer layer = new SF2Layer(sf2); + layer.setName(name); + layer.getRegions().add(region); + sf2.addResource(layer); + + return layer; + } + + public static SF2Instrument newInstrument(SF2Soundbank sf2, String name, + Patch patch, SF2Layer... layers) { + + /* + * Create SoundFont2 instrument. + */ + SF2Instrument ins = new SF2Instrument(sf2); + ins.setPatch(patch); + ins.setName(name); + sf2.addInstrument(ins); + + /* + * Create region for instrument. + */ + for (int i = 0; i < layers.length; i++) { + SF2InstrumentRegion insregion = new SF2InstrumentRegion(); + insregion.setLayer(layers[i]); + ins.getRegions().add(insregion); + } + + return ins; + } + + static public void ifft(double[] data) { + new FFT(data.length / 2, 1).transform(data); + } + + static public void fft(double[] data) { + new FFT(data.length / 2, -1).transform(data); + } + + public static void complexGaussianDist(double[] cdata, double m, + double s, double v) { + for (int x = 0; x < cdata.length / 4; x++) { + cdata[x * 2] += v * (1.0 / (s * Math.sqrt(2 * Math.PI)) + * Math.exp((-1.0 / 2.0) * Math.pow((x - m) / s, 2.0))); + } + } + + static public void randomPhase(double[] data) { + for (int i = 0; i < data.length; i += 2) { + double phase = Math.random() * 2 * Math.PI; + double d = data[i]; + data[i] = Math.sin(phase) * d; + data[i + 1] = Math.cos(phase) * d; + } + } + + static public void randomPhase(double[] data, Random random) { + for (int i = 0; i < data.length; i += 2) { + double phase = random.nextDouble() * 2 * Math.PI; + double d = data[i]; + data[i] = Math.sin(phase) * d; + data[i + 1] = Math.cos(phase) * d; + } + } + + static public void normalize(double[] data, double target) { + double maxvalue = 0; + for (int i = 0; i < data.length; i++) { + if (data[i] > maxvalue) + maxvalue = data[i]; + if (-data[i] > maxvalue) + maxvalue = -data[i]; + } + if (maxvalue == 0) + return; + double gain = target / maxvalue; + for (int i = 0; i < data.length; i++) + data[i] *= gain; + } + + static public void normalize(float[] data, double target) { + double maxvalue = 0.5; + for (int i = 0; i < data.length; i++) { + if (data[i * 2] > maxvalue) + maxvalue = data[i * 2]; + if (-data[i * 2] > maxvalue) + maxvalue = -data[i * 2]; + } + double gain = target / maxvalue; + for (int i = 0; i < data.length; i++) + data[i * 2] *= gain; + } + + static public double[] realPart(double[] in) { + double[] out = new double[in.length / 2]; + for (int i = 0; i < out.length; i++) { + out[i] = in[i * 2]; + } + return out; + } + + static public double[] imgPart(double[] in) { + double[] out = new double[in.length / 2]; + for (int i = 0; i < out.length; i++) { + out[i] = in[i * 2]; + } + return out; + } + + static public float[] toFloat(double[] in) { + float[] out = new float[in.length]; + for (int i = 0; i < out.length; i++) { + out[i] = (float) in[i]; + } + return out; + } + + static public byte[] toBytes(float[] in, AudioFormat format) { + byte[] out = new byte[in.length * format.getFrameSize()]; + return AudioFloatConverter.getConverter(format).toByteArray(in, out); + } + + static public void fadeUp(double[] data, int samples) { + double dsamples = samples; + for (int i = 0; i < samples; i++) + data[i] *= i / dsamples; + } + + static public void fadeUp(float[] data, int samples) { + double dsamples = samples; + for (int i = 0; i < samples; i++) + data[i] *= i / dsamples; + } + + static public double[] loopExtend(double[] data, int newsize) { + double[] outdata = new double[newsize]; + int p_len = data.length; + int p_ps = 0; + for (int i = 0; i < outdata.length; i++) { + outdata[i] = data[p_ps]; + p_ps++; + if (p_ps == p_len) + p_ps = 0; + } + return outdata; + } + + static public float[] loopExtend(float[] data, int newsize) { + float[] outdata = new float[newsize]; + int p_len = data.length; + int p_ps = 0; + for (int i = 0; i < outdata.length; i++) { + outdata[i] = data[p_ps]; + p_ps++; + if (p_ps == p_len) + p_ps = 0; + } + return outdata; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/FFT.java b/jdk/src/share/classes/com/sun/media/sound/FFT.java new file mode 100644 index 00000000000..2e297e127d7 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/FFT.java @@ -0,0 +1,748 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Fast Fourier Transformer. + * + * @author Karl Helgason + */ +public final class FFT { + + private double[] w; + private int fftFrameSize; + private int sign; + private int[] bitm_array; + private int fftFrameSize2; + + // Sign = -1 is FFT, 1 is IFFT (inverse FFT) + // Data = Interlaced double array to be transformed. + // The order is: real (sin), complex (cos) + // Framesize must be power of 2 + public FFT(int fftFrameSize, int sign) { + w = computeTwiddleFactors(fftFrameSize, sign); + + this.fftFrameSize = fftFrameSize; + this.sign = sign; + fftFrameSize2 = fftFrameSize << 1; + + // Pre-process Bit-Reversal + bitm_array = new int[fftFrameSize2]; + for (int i = 2; i < fftFrameSize2; i += 2) { + int j; + int bitm; + for (bitm = 2, j = 0; bitm < fftFrameSize2; bitm <<= 1) { + if ((i & bitm) != 0) + j++; + j <<= 1; + } + bitm_array[i] = j; + } + + } + + public void transform(double[] data) { + bitreversal(data); + calc(fftFrameSize, data, sign, w); + } + + private final static double[] computeTwiddleFactors(int fftFrameSize, + int sign) { + + int imax = (int) (Math.log(fftFrameSize) / Math.log(2.)); + + double[] warray = new double[(fftFrameSize - 1) * 4]; + int w_index = 0; + + for (int i = 0, nstep = 2; i < imax; i++) { + int jmax = nstep; + nstep <<= 1; + + double wr = 1.0; + double wi = 0.0; + + double arg = Math.PI / (jmax >> 1); + double wfr = Math.cos(arg); + double wfi = sign * Math.sin(arg); + + for (int j = 0; j < jmax; j += 2) { + warray[w_index++] = wr; + warray[w_index++] = wi; + + double tempr = wr; + wr = tempr * wfr - wi * wfi; + wi = tempr * wfi + wi * wfr; + } + } + + // PRECOMPUTATION of wwr1, wwi1 for factor 4 Decomposition (3 * complex + // operators and 8 +/- complex operators) + { + w_index = 0; + int w_index2 = warray.length >> 1; + for (int i = 0, nstep = 2; i < (imax - 1); i++) { + int jmax = nstep; + nstep *= 2; + + int ii = w_index + jmax; + for (int j = 0; j < jmax; j += 2) { + double wr = warray[w_index++]; + double wi = warray[w_index++]; + double wr1 = warray[ii++]; + double wi1 = warray[ii++]; + warray[w_index2++] = wr * wr1 - wi * wi1; + warray[w_index2++] = wr * wi1 + wi * wr1; + } + } + + } + + return warray; + } + + private final static void calc(int fftFrameSize, double[] data, int sign, + double[] w) { + + final int fftFrameSize2 = fftFrameSize << 1; + + int nstep = 2; + + if (nstep >= fftFrameSize2) + return; + int i = nstep - 2; + if (sign == -1) + calcF4F(fftFrameSize, data, i, nstep, w); + else + calcF4I(fftFrameSize, data, i, nstep, w); + + } + + private final static void calcF2E(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + int jmax = nstep; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + int m = n + jmax; + double datam_r = data[m]; + double datam_i = data[m + 1]; + double datan_r = data[n]; + double datan_i = data[n + 1]; + double tempr = datam_r * wr - datam_i * wi; + double tempi = datam_r * wi + datam_i * wr; + data[m] = datan_r - tempr; + data[m + 1] = datan_i - tempi; + data[n] = datan_r + tempr; + data[n + 1] = datan_i + tempi; + } + return; + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + private final static void calcF4F(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + if (nstep << 2 == fftFrameSize2) { + // Goto Factor-4 Final Decomposition + // calcF4E(data, i, nstep, -1, w); + calcF4FE(fftFrameSize, data, i, nstep, w); + return; + } + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + + { + i += 2; + ii += 2; + iii += 2; + + for (int n = 0; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r; + double tempi = datam1_i; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r; + double n2w1i = datan2_i; + double m2ww1r = datam2_r; + double m2ww1i = datam2_i; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + } + + for (int j = 2; j < jmax; j += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + for (int n = j; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + } + } + + i += jmax << 1; + + } + + calcF2E(fftFrameSize, data, i, nstep, w); + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + private final static void calcF4I(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + if (nstep << 2 == fftFrameSize2) { + // Goto Factor-4 Final Decomposition + // calcF4E(data, i, nstep, 1, w); + calcF4IE(fftFrameSize, data, i, nstep, w); + return; + } + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + { + i += 2; + ii += 2; + iii += 2; + + for (int n = 0; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r; + double tempi = datam1_i; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r; + double n2w1i = datan2_i; + double m2ww1r = datam2_r; + double m2ww1i = datam2_i; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + } + for (int j = 2; j < jmax; j += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + for (int n = j; n < fftFrameSize2; n += nstep) { + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + } + + i += jmax << 1; + + } + + calcF2E(fftFrameSize, data, i, nstep, w); + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + private final static void calcF4FE(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = m2ww1r - n2w1r; + tempi = m2ww1i - n2w1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + i += jmax << 1; + + } + + } + + // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- + // complex operators + private final static void calcF4IE(int fftFrameSize, double[] data, int i, + int nstep, double[] w) { + final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; + // Factor-4 Decomposition + + int w_len = w.length >> 1; + while (nstep < fftFrameSize2) { + + int jmax = nstep; + int nnstep = nstep << 1; + if (nnstep == fftFrameSize2) { + // Factor-4 Decomposition not possible + calcF2E(fftFrameSize, data, i, nstep, w); + return; + } + nstep <<= 2; + int ii = i + jmax; + int iii = i + w_len; + for (int n = 0; n < jmax; n += 2) { + double wr = w[i++]; + double wi = w[i++]; + double wr1 = w[ii++]; + double wi1 = w[ii++]; + double wwr1 = w[iii++]; + double wwi1 = w[iii++]; + // double wwr1 = wr * wr1 - wi * wi1; // these numbers can be + // precomputed!!! + // double wwi1 = wr * wi1 + wi * wr1; + + int m = n + jmax; + + double datam1_r = data[m]; + double datam1_i = data[m + 1]; + double datan1_r = data[n]; + double datan1_i = data[n + 1]; + + n += nnstep; + m += nnstep; + double datam2_r = data[m]; + double datam2_i = data[m + 1]; + double datan2_r = data[n]; + double datan2_i = data[n + 1]; + + double tempr = datam1_r * wr - datam1_i * wi; + double tempi = datam1_r * wi + datam1_i * wr; + + datam1_r = datan1_r - tempr; + datam1_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + double n2w1r = datan2_r * wr1 - datan2_i * wi1; + double n2w1i = datan2_r * wi1 + datan2_i * wr1; + double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1; + double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1; + + tempr = n2w1r - m2ww1r; + tempi = n2w1i - m2ww1i; + + datam2_r = datam1_r + tempi; + datam2_i = datam1_i - tempr; + datam1_r = datam1_r - tempi; + datam1_i = datam1_i + tempr; + + tempr = n2w1r + m2ww1r; + tempi = n2w1i + m2ww1i; + + datan2_r = datan1_r - tempr; + datan2_i = datan1_i - tempi; + datan1_r = datan1_r + tempr; + datan1_i = datan1_i + tempi; + + data[m] = datam2_r; + data[m + 1] = datam2_i; + data[n] = datan2_r; + data[n + 1] = datan2_i; + + n -= nnstep; + m -= nnstep; + data[m] = datam1_r; + data[m + 1] = datam1_i; + data[n] = datan1_r; + data[n + 1] = datan1_i; + + } + + i += jmax << 1; + + } + + } + + private final void bitreversal(double[] data) { + if (fftFrameSize < 4) + return; + + int inverse = fftFrameSize2 - 2; + for (int i = 0; i < fftFrameSize; i += 4) { + int j = bitm_array[i]; + + // Performing Bit-Reversal, even v.s. even, O(2N) + if (i < j) { + + int n = i; + int m = j; + + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + double tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + double tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + + n = inverse - i; + m = inverse - j; + + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + } + + // Performing Bit-Reversal, odd v.s. even, O(N) + + int m = j + fftFrameSize; // bitm_array[i+2]; + // COMPLEX: SWAP(data[n], data[m]) + // Real Part + int n = i + 2; + double tempr = data[n]; + data[n] = data[m]; + data[m] = tempr; + // Imagery Part + n++; + m++; + double tempi = data[n]; + data[n] = data[m]; + data[m] = tempi; + } + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java b/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java new file mode 100644 index 00000000000..ab46ef370d5 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/InvalidDataException.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; + +/** + * This exception is used when a file contains illegal or unexpected data. + * + * @author Karl Helgason + */ +public class InvalidDataException extends IOException { + + private static final long serialVersionUID = 1L; + + public InvalidDataException() { + super("Invalid Data!"); + } + + public InvalidDataException(String s) { + super(s); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java b/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java new file mode 100644 index 00000000000..96aaa02250e --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/InvalidFormatException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This exception is used when a reader is used to read file of a format + * it doesn't unterstand or support. + * + * @author Karl Helgason + */ +public class InvalidFormatException extends InvalidDataException { + + private static final long serialVersionUID = 1L; + + public InvalidFormatException() { + super("Invalid format!"); + } + + public InvalidFormatException(String s) { + super(s); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java b/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java new file mode 100644 index 00000000000..442fe72c31a --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/JARSoundbankReader.java @@ -0,0 +1,120 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * JarSoundbankReader is used to read sounbank object from jar files. + * + * @author Karl Helgason + */ +public class JARSoundbankReader extends SoundbankReader { + + public boolean isZIP(URL url) { + boolean ok = false; + try { + InputStream stream = url.openStream(); + try { + byte[] buff = new byte[4]; + ok = stream.read(buff) == 4; + if (ok) { + ok = (buff[0] == 0x50 + && buff[1] == 0x4b + && buff[2] == 0x03 + && buff[3] == 0x04); + } + } finally { + stream.close(); + } + } catch (IOException e) { + } + return ok; + } + + public Soundbank getSoundbank(URL url) + throws InvalidMidiDataException, IOException { + if (!isZIP(url)) + return null; + ArrayList soundbanks = new ArrayList(); + URLClassLoader ucl = URLClassLoader.newInstance(new URL[]{url}); + InputStream stream = ucl.getResourceAsStream( + "META-INF/services/javax.sound.midi.Soundbank"); + if (stream == null) + return null; + try + { + BufferedReader r = new BufferedReader(new InputStreamReader(stream)); + String line = r.readLine(); + while (line != null) { + if (!line.startsWith("#")) { + try { + Class c = Class.forName(line.trim(), true, ucl); + Object o = c.newInstance(); + if (o instanceof Soundbank) { + soundbanks.add((Soundbank) o); + } + } catch (ClassNotFoundException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } + } + line = r.readLine(); + } + } + finally + { + stream.close(); + } + if (soundbanks.size() == 0) + return null; + if (soundbanks.size() == 1) + return soundbanks.get(0); + SimpleSoundbank sbk = new SimpleSoundbank(); + for (Soundbank soundbank : soundbanks) + sbk.addAllInstruments(soundbank); + return sbk; + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + return null; + } + + public Soundbank getSoundbank(File file) + throws InvalidMidiDataException, IOException { + return getSoundbank(file.toURI().toURL()); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java b/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java new file mode 100644 index 00000000000..37b14fe1a74 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelAbstractChannelMixer.java @@ -0,0 +1,126 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * ModelAbstractChannelMixer is ready for use class to implement + * ModelChannelMixer interface. + * + * @author Karl Helgason + */ +public abstract class ModelAbstractChannelMixer implements ModelChannelMixer { + + public abstract boolean process(float[][] buffer, int offset, int len); + + public abstract void stop(); + + public void allNotesOff() { + } + + public void allSoundOff() { + } + + public void controlChange(int controller, int value) { + } + + public int getChannelPressure() { + return 0; + } + + public int getController(int controller) { + return 0; + } + + public boolean getMono() { + return false; + } + + public boolean getMute() { + return false; + } + + public boolean getOmni() { + return false; + } + + public int getPitchBend() { + return 0; + } + + public int getPolyPressure(int noteNumber) { + return 0; + } + + public int getProgram() { + return 0; + } + + public boolean getSolo() { + return false; + } + + public boolean localControl(boolean on) { + return false; + } + + public void noteOff(int noteNumber) { + } + + public void noteOff(int noteNumber, int velocity) { + } + + public void noteOn(int noteNumber, int velocity) { + } + + public void programChange(int program) { + } + + public void programChange(int bank, int program) { + } + + public void resetAllControllers() { + } + + public void setChannelPressure(int pressure) { + } + + public void setMono(boolean on) { + } + + public void setMute(boolean mute) { + } + + public void setOmni(boolean on) { + } + + public void setPitchBend(int bend) { + } + + public void setPolyPressure(int noteNumber, int pressure) { + } + + public void setSolo(boolean soloState) { + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java b/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java new file mode 100644 index 00000000000..5d5c7e937af --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelAbstractOscillator.java @@ -0,0 +1,200 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.midi.VoiceStatus; + +/** + * A abstract class used to simplify creating custom ModelOscillator. + * + * @author Karl Helgason + */ +public abstract class ModelAbstractOscillator + implements ModelOscillator, ModelOscillatorStream, Soundbank { + + protected float pitch = 6000; + protected float samplerate; + protected MidiChannel channel; + protected VoiceStatus voice; + protected int noteNumber; + protected int velocity; + protected boolean on = false; + + public void init() { + } + + public void close() throws IOException { + } + + public void noteOff(int velocity) { + on = false; + } + + public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, + int velocity) { + this.channel = channel; + this.voice = voice; + this.noteNumber = noteNumber; + this.velocity = velocity; + on = true; + } + + public int read(float[][] buffer, int offset, int len) throws IOException { + return -1; + } + + public MidiChannel getChannel() { + return channel; + } + + public VoiceStatus getVoice() { + return voice; + } + + public int getNoteNumber() { + return noteNumber; + } + + public int getVelocity() { + return velocity; + } + + public boolean isOn() { + return on; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public float getPitch() { + return pitch; + } + + public void setSampleRate(float samplerate) { + this.samplerate = samplerate; + } + + public float getSampleRate() { + return samplerate; + } + + public float getAttenuation() { + return 0; + } + + public int getChannels() { + return 1; + } + + public String getName() { + return getClass().getName(); + } + + public Patch getPatch() { + return new Patch(0, 0); + } + + public ModelOscillatorStream open(float samplerate) { + ModelAbstractOscillator oscs; + try { + oscs = this.getClass().newInstance(); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + oscs.setSampleRate(samplerate); + oscs.init(); + return oscs; + } + + public ModelPerformer getPerformer() { + // Create performer for my custom oscillirator + ModelPerformer performer = new ModelPerformer(); + performer.getOscillators().add(this); + return performer; + + } + + public ModelInstrument getInstrument() { + // Create Instrument object around my performer + SimpleInstrument ins = new SimpleInstrument(); + ins.setName(getName()); + ins.add(getPerformer()); + ins.setPatch(getPatch()); + return ins; + + } + + public Soundbank getSoundBank() { + // Create Soundbank object around the instrument + SimpleSoundbank sbk = new SimpleSoundbank(); + sbk.addInstrument(getInstrument()); + return sbk; + } + + public String getDescription() { + return getName(); + } + + public Instrument getInstrument(Patch patch) { + Instrument ins = getInstrument(); + Patch p = ins.getPatch(); + if (p.getBank() != patch.getBank()) + return null; + if (p.getProgram() != patch.getProgram()) + return null; + if (p instanceof ModelPatch && patch instanceof ModelPatch) { + if (((ModelPatch)p).isPercussion() + != ((ModelPatch)patch).isPercussion()) { + return null; + } + } + return ins; + } + + public Instrument[] getInstruments() { + return new Instrument[]{getInstrument()}; + } + + public SoundbankResource[] getResources() { + return new SoundbankResource[0]; + } + + public String getVendor() { + return null; + } + + public String getVersion() { + return null; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java b/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java new file mode 100644 index 00000000000..16c1125fb61 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelByteBuffer.java @@ -0,0 +1,329 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.util.Collection; + +/** + * This class is a pointer to a binary array either in memory or on disk. + * + * @author Karl Helgason + */ +public class ModelByteBuffer { + + private ModelByteBuffer root = this; + private File file; + private long fileoffset; + private byte[] buffer; + private long offset; + private final long len; + + private class RandomFileInputStream extends InputStream { + + private RandomAccessFile raf; + private long left; + private long mark = 0; + private long markleft = 0; + + public RandomFileInputStream() throws IOException { + raf = new RandomAccessFile(root.file, "r"); + raf.seek(root.fileoffset + arrayOffset()); + left = capacity(); + } + + public int available() throws IOException { + if (left > Integer.MAX_VALUE) + return Integer.MAX_VALUE; + return (int)left; + } + + public synchronized void mark(int readlimit) { + try { + mark = raf.getFilePointer(); + markleft = left; + } catch (IOException e) { + //e.printStackTrace(); + } + } + + public boolean markSupported() { + return true; + } + + public synchronized void reset() throws IOException { + raf.seek(mark); + left = markleft; + } + + public long skip(long n) throws IOException { + if( n < 0) + return 0; + if (n > left) + n = left; + long p = raf.getFilePointer(); + raf.seek(p + n); + left -= n; + return n; + } + + public int read(byte b[], int off, int len) throws IOException { + if (len > left) + len = (int)left; + if (left == 0) + return -1; + len = raf.read(b, off, len); + if (len == -1) + return -1; + left -= len; + return len; + } + + public int read(byte[] b) throws IOException { + int len = b.length; + if (len > left) + len = (int)left; + if (left == 0) + return -1; + len = raf.read(b, 0, len); + if (len == -1) + return -1; + left -= len; + return len; + } + + public int read() throws IOException { + if (left == 0) + return -1; + int b = raf.read(); + if (b == -1) + return -1; + left--; + return b; + } + + public void close() throws IOException { + raf.close(); + } + } + + private ModelByteBuffer(ModelByteBuffer parent, + long beginIndex, long endIndex, boolean independent) { + this.root = parent.root; + this.offset = 0; + long parent_len = parent.len; + if (beginIndex < 0) + beginIndex = 0; + if (beginIndex > parent_len) + beginIndex = parent_len; + if (endIndex < 0) + endIndex = 0; + if (endIndex > parent_len) + endIndex = parent_len; + if (beginIndex > endIndex) + beginIndex = endIndex; + offset = beginIndex; + len = endIndex - beginIndex; + if (independent) { + buffer = root.buffer; + if (root.file != null) { + file = root.file; + fileoffset = root.fileoffset + arrayOffset(); + offset = 0; + } else + offset = arrayOffset(); + root = this; + } + } + + public ModelByteBuffer(byte[] buffer) { + this.buffer = buffer; + this.offset = 0; + this.len = buffer.length; + } + + public ModelByteBuffer(byte[] buffer, int offset, int len) { + this.buffer = buffer; + this.offset = offset; + this.len = len; + } + + public ModelByteBuffer(File file) { + this.file = file; + this.fileoffset = 0; + this.len = file.length(); + } + + public ModelByteBuffer(File file, long offset, long len) { + this.file = file; + this.fileoffset = offset; + this.len = len; + } + + public void writeTo(OutputStream out) throws IOException { + if (root.file != null && root.buffer == null) { + InputStream is = getInputStream(); + byte[] buff = new byte[1024]; + int ret; + while ((ret = is.read(buff)) != -1) + out.write(buff, 0, ret); + } else + out.write(array(), (int) arrayOffset(), (int) capacity()); + } + + public InputStream getInputStream() { + if (root.file != null && root.buffer == null) { + try { + return new RandomFileInputStream(); + } catch (IOException e) { + //e.printStackTrace(); + return null; + } + } + return new ByteArrayInputStream(array(), + (int)arrayOffset(), (int)capacity()); + } + + public ModelByteBuffer subbuffer(long beginIndex) { + return subbuffer(beginIndex, capacity()); + } + + public ModelByteBuffer subbuffer(long beginIndex, long endIndex) { + return subbuffer(beginIndex, endIndex, false); + } + + public ModelByteBuffer subbuffer(long beginIndex, long endIndex, + boolean independent) { + return new ModelByteBuffer(this, beginIndex, endIndex, independent); + } + + public byte[] array() { + return root.buffer; + } + + public long arrayOffset() { + if (root != this) + return root.arrayOffset() + offset; + return offset; + } + + public long capacity() { + return len; + } + + public ModelByteBuffer getRoot() { + return root; + } + + public File getFile() { + return file; + } + + public long getFilePointer() { + return fileoffset; + } + + public static void loadAll(Collection col) + throws IOException { + File selfile = null; + RandomAccessFile raf = null; + try { + for (ModelByteBuffer mbuff : col) { + mbuff = mbuff.root; + if (mbuff.file == null) + continue; + if (mbuff.buffer != null) + continue; + if (selfile == null || !selfile.equals(mbuff.file)) { + if (raf != null) { + raf.close(); + raf = null; + } + selfile = mbuff.file; + raf = new RandomAccessFile(mbuff.file, "r"); + } + raf.seek(mbuff.fileoffset); + byte[] buffer = new byte[(int) mbuff.capacity()]; + + int read = 0; + int avail = buffer.length; + while (read != avail) { + if (avail - read > 65536) { + raf.readFully(buffer, read, 65536); + read += 65536; + } else { + raf.readFully(buffer, read, avail - read); + read = avail; + } + + } + + mbuff.buffer = buffer; + mbuff.offset = 0; + } + } finally { + if (raf != null) + raf.close(); + } + } + + public void load() throws IOException { + if (root != this) { + root.load(); + return; + } + if (buffer != null) + return; + if (file == null) { + throw new IllegalStateException( + "No file associated with this ByteBuffer!"); + } + + DataInputStream is = new DataInputStream(getInputStream()); + buffer = new byte[(int) capacity()]; + offset = 0; + is.readFully(buffer); + is.close(); + + } + + public void unload() { + if (root != this) { + root.unload(); + return; + } + if (file == null) { + throw new IllegalStateException( + "No file associated with this ByteBuffer!"); + } + root.buffer = null; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java b/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java new file mode 100644 index 00000000000..d7da52a7643 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java @@ -0,0 +1,281 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +/** + * Wavetable oscillator for pre-loaded data. + * + * @author Karl Helgason + */ +public class ModelByteBufferWavetable implements ModelWavetable { + + private class Buffer8PlusInputStream extends InputStream { + + private boolean bigendian; + private int framesize_pc; + int pos = 0; + int pos2 = 0; + int markpos = 0; + int markpos2 = 0; + + public Buffer8PlusInputStream() { + framesize_pc = format.getFrameSize() / format.getChannels(); + bigendian = format.isBigEndian(); + } + + public int read(byte[] b, int off, int len) throws IOException { + int avail = available(); + if (avail <= 0) + return -1; + if (len > avail) + len = avail; + byte[] buff1 = buffer.array(); + byte[] buff2 = buffer8.array(); + pos += buffer.arrayOffset(); + pos2 += buffer8.arrayOffset(); + if (bigendian) { + for (int i = 0; i < len; i += (framesize_pc + 1)) { + System.arraycopy(buff1, pos, b, i, framesize_pc); + System.arraycopy(buff2, pos2, b, i + framesize_pc, 1); + pos += framesize_pc; + pos2 += 1; + } + } else { + for (int i = 0; i < len; i += (framesize_pc + 1)) { + System.arraycopy(buff2, pos2, b, i, 1); + System.arraycopy(buff1, pos, b, i + 1, framesize_pc); + pos += framesize_pc; + pos2 += 1; + } + } + pos -= buffer.arrayOffset(); + pos2 -= buffer8.arrayOffset(); + return len; + } + + public long skip(long n) throws IOException { + int avail = available(); + if (avail <= 0) + return -1; + if (n > avail) + n = avail; + pos += (n / (framesize_pc + 1)) * (framesize_pc); + pos2 += n / (framesize_pc + 1); + return super.skip(n); + } + + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public int read() throws IOException { + byte[] b = new byte[1]; + int ret = read(b, 0, 1); + if (ret == -1) + return -1; + return 0 & 0xFF; + } + + public boolean markSupported() { + return true; + } + + public int available() throws IOException { + return (int)buffer.capacity() + (int)buffer8.capacity() - pos - pos2; + } + + public synchronized void mark(int readlimit) { + markpos = pos; + markpos2 = pos2; + } + + public synchronized void reset() throws IOException { + pos = markpos; + pos2 = markpos2; + + } + } + + private float loopStart = -1; + private float loopLength = -1; + private ModelByteBuffer buffer; + private ModelByteBuffer buffer8 = null; + private AudioFormat format = null; + private float pitchcorrection = 0; + private float attenuation = 0; + private int loopType = LOOP_TYPE_OFF; + + public ModelByteBufferWavetable(ModelByteBuffer buffer) { + this.buffer = buffer; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, + float pitchcorrection) { + this.buffer = buffer; + this.pitchcorrection = pitchcorrection; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format) { + this.format = format; + this.buffer = buffer; + } + + public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format, + float pitchcorrection) { + this.format = format; + this.buffer = buffer; + this.pitchcorrection = pitchcorrection; + } + + public void set8BitExtensionBuffer(ModelByteBuffer buffer) { + buffer8 = buffer; + } + + public ModelByteBuffer get8BitExtensionBuffer() { + return buffer8; + } + + public ModelByteBuffer getBuffer() { + return buffer; + } + + public AudioFormat getFormat() { + if (format == null) { + if (buffer == null) + return null; + InputStream is = buffer.getInputStream(); + AudioFormat format = null; + try { + format = AudioSystem.getAudioFileFormat(is).getFormat(); + } catch (Exception e) { + //e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + //e.printStackTrace(); + } + return format; + } + return format; + } + + public AudioFloatInputStream openStream() { + if (buffer == null) + return null; + if (format == null) { + InputStream is = buffer.getInputStream(); + AudioInputStream ais = null; + try { + ais = AudioSystem.getAudioInputStream(is); + } catch (Exception e) { + //e.printStackTrace(); + return null; + } + return AudioFloatInputStream.getInputStream(ais); + } + if (buffer.array() == null) { + return AudioFloatInputStream.getInputStream(new AudioInputStream( + buffer.getInputStream(), format, buffer.capacity())); + } + if (buffer8 != null) { + if (format.getEncoding().equals(Encoding.PCM_SIGNED) + || format.getEncoding().equals(Encoding.PCM_UNSIGNED)) { + InputStream is = new Buffer8PlusInputStream(); + AudioFormat format2 = new AudioFormat( + format.getEncoding(), + format.getSampleRate(), + format.getSampleSizeInBits() + 8, + format.getChannels(), + format.getFrameSize() + (1 * format.getChannels()), + format.getFrameRate(), + format.isBigEndian()); + + AudioInputStream ais = new AudioInputStream(is, format2, + buffer.capacity() / format.getFrameSize()); + return AudioFloatInputStream.getInputStream(ais); + } + } + return AudioFloatInputStream.getInputStream(format, buffer.array(), + (int)buffer.arrayOffset(), (int)buffer.capacity()); + } + + public int getChannels() { + return getFormat().getChannels(); + } + + public ModelOscillatorStream open(float samplerate) { + // ModelWavetableOscillator doesn't support ModelOscillatorStream + return null; + } + + // attenuation is in cB + public float getAttenuation() { + return attenuation; + } + // attenuation is in cB + public void setAttenuation(float attenuation) { + this.attenuation = attenuation; + } + + public float getLoopLength() { + return loopLength; + } + + public void setLoopLength(float loopLength) { + this.loopLength = loopLength; + } + + public float getLoopStart() { + return loopStart; + } + + public void setLoopStart(float loopStart) { + this.loopStart = loopStart; + } + + public void setLoopType(int loopType) { + this.loopType = loopType; + } + + public int getLoopType() { + return loopType; + } + + public float getPitchcorrection() { + return pitchcorrection; + } + + public void setPitchcorrection(float pitchcorrection) { + this.pitchcorrection = pitchcorrection; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java b/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java new file mode 100644 index 00000000000..1f6dfd6e97d --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelChannelMixer.java @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; + +/** + * ModelChannelMixer is used to process channel voice mix output before going + * to master output.
+ * It can be used to:
+ *

    + *
  • Implement non-voice oriented instruments.
  • + *
  • Add insert effect to instruments; for example distortion effect.
  • + * + *

    + * Warning! Classes that implements ModelChannelMixer must be thread-safe. + * + * @author Karl Helgason + */ +public interface ModelChannelMixer extends MidiChannel { + + // Used to process input audio from voices mix. + public boolean process(float[][] buffer, int offset, int len); + + // Is used to trigger that this mixer is not be used + // and it should fade out. + public void stop(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java b/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java new file mode 100644 index 00000000000..349d6b42b7a --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelConnectionBlock.java @@ -0,0 +1,135 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Connection blocks are used to connect source variable + * to a destination variable. + * For example Note On velocity can be connected to output gain. + * In DLS this is called articulator and in SoundFonts (SF2) a modulator. + * + * @author Karl Helgason + */ +public class ModelConnectionBlock { + + // + // source1 * source2 * scale -> destination + // + private final static ModelSource[] no_sources = new ModelSource[0]; + private ModelSource[] sources = no_sources; + private double scale = 1; + private ModelDestination destination; + + public ModelConnectionBlock() { + } + + public ModelConnectionBlock(double scale, ModelDestination destination) { + this.scale = scale; + this.destination = destination; + } + + public ModelConnectionBlock(ModelSource source, + ModelDestination destination) { + if (source != null) { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + this.destination = destination; + } + + public ModelConnectionBlock(ModelSource source, double scale, + ModelDestination destination) { + if (source != null) { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } + this.scale = scale; + this.destination = destination; + } + + public ModelConnectionBlock(ModelSource source, ModelSource control, + ModelDestination destination) { + if (source != null) { + if (control == null) { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } else { + this.sources = new ModelSource[2]; + this.sources[0] = source; + this.sources[1] = control; + } + } + this.destination = destination; + } + + public ModelConnectionBlock(ModelSource source, ModelSource control, + double scale, ModelDestination destination) { + if (source != null) { + if (control == null) { + this.sources = new ModelSource[1]; + this.sources[0] = source; + } else { + this.sources = new ModelSource[2]; + this.sources[0] = source; + this.sources[1] = control; + } + } + this.scale = scale; + this.destination = destination; + } + + public ModelDestination getDestination() { + return destination; + } + + public void setDestination(ModelDestination destination) { + this.destination = destination; + } + + public double getScale() { + return scale; + } + + public void setScale(double scale) { + this.scale = scale; + } + + public ModelSource[] getSources() { + return sources; + } + + public void setSources(ModelSource[] source) { + this.sources = source; + } + + public void addSource(ModelSource source) { + ModelSource[] oldsources = sources; + sources = new ModelSource[oldsources.length + 1]; + for (int i = 0; i < oldsources.length; i++) { + sources[i] = oldsources[i]; + } + sources[sources.length - 1] = source; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java b/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java new file mode 100644 index 00000000000..e8c1db41e1b --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelDestination.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class is used to identify destinations in connection blocks, + * see ModelConnectionBlock. + * + * @author Karl Helgason + */ +public class ModelDestination { + + public static final ModelIdentifier DESTINATION_NONE = null; + public static final ModelIdentifier DESTINATION_KEYNUMBER + = new ModelIdentifier("noteon", "keynumber"); + public static final ModelIdentifier DESTINATION_VELOCITY + = new ModelIdentifier("noteon", "velocity"); + public static final ModelIdentifier DESTINATION_PITCH + = new ModelIdentifier("osc", "pitch"); // cent + public static final ModelIdentifier DESTINATION_GAIN + = new ModelIdentifier("mixer", "gain"); // cB + public static final ModelIdentifier DESTINATION_PAN + = new ModelIdentifier("mixer", "pan"); // 0.1 % + public static final ModelIdentifier DESTINATION_REVERB + = new ModelIdentifier("mixer", "reverb"); // 0.1 % + public static final ModelIdentifier DESTINATION_CHORUS + = new ModelIdentifier("mixer", "chorus"); // 0.1 % + public static final ModelIdentifier DESTINATION_LFO1_DELAY + = new ModelIdentifier("lfo", "delay", 0); // timecent + public static final ModelIdentifier DESTINATION_LFO1_FREQ + = new ModelIdentifier("lfo", "freq", 0); // cent + public static final ModelIdentifier DESTINATION_LFO2_DELAY + = new ModelIdentifier("lfo", "delay", 1); // timecent + public static final ModelIdentifier DESTINATION_LFO2_FREQ + = new ModelIdentifier("lfo", "freq", 1); // cent + public static final ModelIdentifier DESTINATION_EG1_DELAY + = new ModelIdentifier("eg", "delay", 0); // timecent + public static final ModelIdentifier DESTINATION_EG1_ATTACK + = new ModelIdentifier("eg", "attack", 0); // timecent + public static final ModelIdentifier DESTINATION_EG1_HOLD + = new ModelIdentifier("eg", "hold", 0); // timecent + public static final ModelIdentifier DESTINATION_EG1_DECAY + = new ModelIdentifier("eg", "decay", 0); // timecent + public static final ModelIdentifier DESTINATION_EG1_SUSTAIN + = new ModelIdentifier("eg", "sustain", 0); + // 0.1 % (I want this to be value not %) + public static final ModelIdentifier DESTINATION_EG1_RELEASE + = new ModelIdentifier("eg", "release", 0); // timecent + public static final ModelIdentifier DESTINATION_EG1_SHUTDOWN + = new ModelIdentifier("eg", "shutdown", 0); // timecent + public static final ModelIdentifier DESTINATION_EG2_DELAY + = new ModelIdentifier("eg", "delay", 1); // timecent + public static final ModelIdentifier DESTINATION_EG2_ATTACK + = new ModelIdentifier("eg", "attack", 1); // timecent + public static final ModelIdentifier DESTINATION_EG2_HOLD + = new ModelIdentifier("eg", "hold", 1); // 0.1 % + public static final ModelIdentifier DESTINATION_EG2_DECAY + = new ModelIdentifier("eg", "decay", 1); // timecent + public static final ModelIdentifier DESTINATION_EG2_SUSTAIN + = new ModelIdentifier("eg", "sustain", 1); + // 0.1 % ( I want this to be value not %) + public static final ModelIdentifier DESTINATION_EG2_RELEASE + = new ModelIdentifier("eg", "release", 1); // timecent + public static final ModelIdentifier DESTINATION_EG2_SHUTDOWN + = new ModelIdentifier("eg", "shutdown", 1); // timecent + public static final ModelIdentifier DESTINATION_FILTER_FREQ + = new ModelIdentifier("filter", "freq", 0); // cent + public static final ModelIdentifier DESTINATION_FILTER_Q + = new ModelIdentifier("filter", "q", 0); // cB + private ModelIdentifier destination = DESTINATION_NONE; + private ModelTransform transform = new ModelStandardTransform(); + + public ModelDestination() { + } + + public ModelDestination(ModelIdentifier id) { + destination = id; + } + + public ModelIdentifier getIdentifier() { + return destination; + } + + public void setIdentifier(ModelIdentifier destination) { + this.destination = destination; + } + + public ModelTransform getTransform() { + return transform; + } + + public void setTransform(ModelTransform transform) { + this.transform = transform; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java b/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java new file mode 100644 index 00000000000..cdcfda5f3d6 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelDirectedPlayer.java @@ -0,0 +1,36 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * ModelDirectedPlayer is the one who is directed by ModelDirector + * to play ModelPerformer objects. + * + * @author Karl Helgason + */ +public interface ModelDirectedPlayer { + + public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java b/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java new file mode 100644 index 00000000000..c7e7e914f2b --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelDirector.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A director chooses what performers should be played for each note on + * and note off events. + * + * ModelInstrument can implement custom performer who chooses what performers + * to play for example by sustain pedal is off or on. + * + * The default director (ModelStandardDirector) chooses performers + * by there keyfrom,keyto,velfrom,velto properties. + * + * @author Karl Helgason + */ +public interface ModelDirector { + + public void noteOn(int noteNumber, int velocity); + + public void noteOff(int noteNumber, int velocity); + + public void close(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java b/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java new file mode 100644 index 00000000000..9900a679fc5 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelIdentifier.java @@ -0,0 +1,169 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class stores the identity of source and destinations in connection + * blocks, see ModelConnectionBlock. + * + * @author Karl Helgason + */ +public class ModelIdentifier { + + /* + * Object Variable + * ------ -------- + * + * // INPUT parameters + * noteon keynumber 7 bit midi value + * velocity 7 bit midi vale + * on 1 or 0 + * + * midi pitch 14 bit midi value + * channel_pressure 7 bit midi value + * poly_pressure 7 bit midi value + * + * midi_cc 0 (midi control #0 7 bit midi value + * 1 (midi control #1 7 bit midi value + * ... + * 127 (midi control #127 7 bit midi value + * + * midi_rpn 0 (midi rpn control #0) 14 bit midi value + * 1 (midi rpn control #1) 14 bit midi value + * .... + * + * // DAHDSR envelope generator + * eg (null) + * delay timecent + * attack timecent + * hold timecent + * decay timecent + * sustain 0.1 % + * release timecent + * + * // Low frequency oscillirator (sine wave) + * lfo (null) + * delay timcent + * freq cent + * + * // Resonance LowPass Filter 6dB slope + * filter (null) (output/input) + * freq cent + * q cB + * + * // The oscillator with preloaded wavetable data + * osc (null) + * pitch cent + * + * // Output mixer pins + * mixer gain cB + * pan 0.1 % + * reverb 0.1 % + * chorus 0.1 % + * + */ + private String object = null; + private String variable = null; + private int instance = 0; + + public ModelIdentifier(String object) { + this.object = object; + } + + public ModelIdentifier(String object, int instance) { + this.object = object; + this.instance = instance; + } + + public ModelIdentifier(String object, String variable) { + this.object = object; + this.variable = variable; + + } + + public ModelIdentifier(String object, String variable, int instance) { + this.object = object; + this.variable = variable; + this.instance = instance; + + } + + public int getInstance() { + return instance; + } + + public void setInstance(int instance) { + this.instance = instance; + } + + public String getObject() { + return object; + } + + public void setObject(String object) { + this.object = object; + } + + public String getVariable() { + return variable; + } + + public void setVariable(String variable) { + this.variable = variable; + } + + public int hashCode() { + int hashcode = instance; + if(object != null) hashcode |= object.hashCode(); + if(variable != null) hashcode |= variable.hashCode(); + return hashcode; + } + + public boolean equals(Object obj) { + if (!(obj instanceof ModelIdentifier)) + return false; + + ModelIdentifier mobj = (ModelIdentifier)obj; + if ((object == null) != (mobj.object == null)) + return false; + if ((variable == null) != (mobj.variable == null)) + return false; + if (mobj.getInstance() != getInstance()) + return false; + if (!(object == null || object.equals(mobj.object))) + return false; + if (!(variable == null || variable.equals(mobj.variable))) + return false; + return true; + } + + public String toString() { + if (variable == null) { + return object + "[" + instance + "]"; + } else { + return object + "[" + instance + "]" + "." + variable; + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java b/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java new file mode 100644 index 00000000000..37d0e583eac --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelInstrument.java @@ -0,0 +1,136 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.AudioFormat; + +/** + * The model instrument class. + * + *

    The main methods to override are:
    + * getPerformer, getDirector, getChannelMixer. + * + *

    Performers are used to define what voices which will + * playback when using the instrument.
    + * + * ChannelMixer is used to add channel-wide processing + * on voices output or to define non-voice oriented instruments.
    + * + * Director is used to change how the synthesizer + * chooses what performers to play on midi events. + * + * @author Karl Helgason + */ +public abstract class ModelInstrument extends Instrument { + + protected ModelInstrument(Soundbank soundbank, Patch patch, String name, + Class dataClass) { + super(soundbank, patch, name, dataClass); + } + + public ModelDirector getDirector(ModelPerformer[] performers, + MidiChannel channel, ModelDirectedPlayer player) { + return new ModelStandardDirector(performers, player); + } + + public ModelPerformer[] getPerformers() { + return new ModelPerformer[0]; + } + + public ModelChannelMixer getChannelMixer(MidiChannel channel, + AudioFormat format) { + return null; + } + + // Get General MIDI 2 Alias patch for this instrument. + public Patch getPatchAlias() { + Patch patch = getPatch(); + int program = patch.getProgram(); + int bank = patch.getBank(); + if (bank != 0) + return patch; + boolean percussion = false; + if (getPatch() instanceof ModelPatch) + percussion = ((ModelPatch)getPatch()).isPercussion(); + if (percussion) + return new Patch(0x78 << 7, program); + else + return new Patch(0x79 << 7, program); + } + + // Return name of all the keys. + // This information is generated from ModelPerformer.getName() + // returned from getPerformers(). + public String[] getKeys() { + String[] keys = new String[128]; + for (ModelPerformer performer : getPerformers()) { + for (int k = performer.getKeyFrom(); k <= performer.getKeyTo(); k++) { + if (k >= 0 && k < 128 && keys[k] == null) { + String name = performer.getName(); + if (name == null) + name = "untitled"; + keys[k] = name; + } + } + } + return keys; + } + + // Return what channels this instrument will probably response + // on General MIDI synthesizer. + public boolean[] getChannels() { + boolean percussion = false; + if (getPatch() instanceof ModelPatch) + percussion = ((ModelPatch)getPatch()).isPercussion(); + + // Check if instrument is percussion. + if (percussion) { + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = false; + ch[9] = true; + return ch; + } + + // Check if instrument uses General MIDI 2 default banks. + int bank = getPatch().getBank(); + if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = true; + return ch; + } + + boolean[] ch = new boolean[16]; + for (int i = 0; i < ch.length; i++) + ch[i] = true; + ch[9] = false; + return ch; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java b/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java new file mode 100644 index 00000000000..7268971f0d7 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelInstrumentComparator.java @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Comparator; +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; + +/** + * Instrument comparator class. + * Used to order instrument by program, bank, percussion. + * + * @author Karl Helgason + */ +public class ModelInstrumentComparator implements Comparator { + + public int compare(Instrument arg0, Instrument arg1) { + Patch p0 = arg0.getPatch(); + Patch p1 = arg1.getPatch(); + int a = p0.getBank() * 128 + p0.getProgram(); + int b = p1.getBank() * 128 + p1.getProgram(); + if (p0 instanceof ModelPatch) { + a += ((ModelPatch)p0).isPercussion() ? 2097152 : 0; + } + if (p1 instanceof ModelPatch) { + b += ((ModelPatch)p1).isPercussion() ? 2097152 : 0; + } + return a - b; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java b/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java new file mode 100644 index 00000000000..6064852dee2 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelMappedInstrument.java @@ -0,0 +1,62 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; +import javax.sound.sampled.AudioFormat; + +/** + * This class is used to map instrument to another patch. + * + * @author Karl Helgason + */ +public class ModelMappedInstrument extends ModelInstrument { + + private ModelInstrument ins; + + public ModelMappedInstrument(ModelInstrument ins, Patch patch) { + super(ins.getSoundbank(), patch, ins.getName(), ins.getDataClass()); + this.ins = ins; + } + + public Object getData() { + return ins.getData(); + } + + public ModelPerformer[] getPerformers() { + return ins.getPerformers(); + } + + public ModelDirector getDirector(ModelPerformer[] performers, + MidiChannel channel, ModelDirectedPlayer player) { + return ins.getDirector(performers, channel, player); + } + + public ModelChannelMixer getChannelMixer(MidiChannel channel, + AudioFormat format) { + return ins.getChannelMixer(channel, format); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java b/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java new file mode 100644 index 00000000000..3312473d2ad --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelOscillator.java @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This interface is used for oscillators. + * See example in ModelDefaultOscillator which is a wavetable oscillator. + * + * @author Karl Helgason + */ +public interface ModelOscillator { + + public int getChannels(); + + /** + * Attenuation is in cB. + * @return + */ + public float getAttenuation(); + + public ModelOscillatorStream open(float samplerate); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java b/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java new file mode 100644 index 00000000000..10ec5da46b9 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelOscillatorStream.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.VoiceStatus; + +/** + * This interface is used for audio streams from ModelOscillator. + * + * @author Karl Helgason + */ +public interface ModelOscillatorStream { + + public void setPitch(float pitch); // Pitch is in cents! + + public void noteOn(MidiChannel channel, VoiceStatus voice, int noteNumber, + int velocity); + + public void noteOff(int velocity); + + public int read(float[][] buffer, int offset, int len) throws IOException; + + public void close() throws IOException; +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java b/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java new file mode 100644 index 00000000000..6b4c5b01df4 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelPatch.java @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.Patch; + +/** + * A extended patch object that has isPercussion function. + * Which is necessary to identify percussion instruments + * from melodic instruments. + * + * @author Karl Helgason + */ +public class ModelPatch extends Patch { + + private boolean percussion = false; + + public ModelPatch(int bank, int program) { + super(bank, program); + } + + public ModelPatch(int bank, int program, boolean percussion) { + super(bank, program); + this.percussion = percussion; + } + + public boolean isPercussion() { + return percussion; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java b/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java new file mode 100644 index 00000000000..6ba48674c7c --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelPerformer.java @@ -0,0 +1,143 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to define how to synthesize audio in universal maner + * for both SF2 and DLS instruments. + * + * @author Karl Helgason + */ +public class ModelPerformer { + + private List oscillators = new ArrayList(); + private List connectionBlocks + = new ArrayList(); + private int keyFrom = 0; + private int keyTo = 127; + private int velFrom = 0; + private int velTo = 127; + private int exclusiveClass = 0; + private boolean releaseTrigger = false; + private boolean selfNonExclusive = false; + private Object userObject = null; + private boolean addDefaultConnections = true; + private String name = null; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getConnectionBlocks() { + return connectionBlocks; + } + + public void setConnectionBlocks(List connectionBlocks) { + this.connectionBlocks = connectionBlocks; + } + + public List getOscillators() { + return oscillators; + } + + public int getExclusiveClass() { + return exclusiveClass; + } + + public void setExclusiveClass(int exclusiveClass) { + this.exclusiveClass = exclusiveClass; + } + + public boolean isSelfNonExclusive() { + return selfNonExclusive; + } + + public void setSelfNonExclusive(boolean selfNonExclusive) { + this.selfNonExclusive = selfNonExclusive; + } + + public int getKeyFrom() { + return keyFrom; + } + + public void setKeyFrom(int keyFrom) { + this.keyFrom = keyFrom; + } + + public int getKeyTo() { + return keyTo; + } + + public void setKeyTo(int keyTo) { + this.keyTo = keyTo; + } + + public int getVelFrom() { + return velFrom; + } + + public void setVelFrom(int velFrom) { + this.velFrom = velFrom; + } + + public int getVelTo() { + return velTo; + } + + public void setVelTo(int velTo) { + this.velTo = velTo; + } + + public boolean isReleaseTriggered() { + return releaseTrigger; + } + + public void setReleaseTriggered(boolean value) { + this.releaseTrigger = value; + } + + public Object getUserObject() { + return userObject; + } + + public void setUserObject(Object object) { + userObject = object; + } + + public boolean isDefaultConnectionsEnabled() { + return addDefaultConnections; + } + + public void setDefaultConnectionsEnabled(boolean addDefaultConnections) { + this.addDefaultConnections = addDefaultConnections; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelSource.java b/jdk/src/share/classes/com/sun/media/sound/ModelSource.java new file mode 100644 index 00000000000..1ad5f3e24ec --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelSource.java @@ -0,0 +1,109 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This class is used to identify sources in connection blocks, + * see ModelConnectionBlock. + * + * @author Karl Helgason + */ +public class ModelSource { + + public static final ModelIdentifier SOURCE_NONE = null; + public static final ModelIdentifier SOURCE_NOTEON_KEYNUMBER = + new ModelIdentifier("noteon", "keynumber"); // midi keynumber + public static final ModelIdentifier SOURCE_NOTEON_VELOCITY = + new ModelIdentifier("noteon", "velocity"); // midi velocity + public static final ModelIdentifier SOURCE_EG1 = + new ModelIdentifier("eg", null, 0); + public static final ModelIdentifier SOURCE_EG2 = + new ModelIdentifier("eg", null, 1); + public static final ModelIdentifier SOURCE_LFO1 = + new ModelIdentifier("lfo", null, 0); + public static final ModelIdentifier SOURCE_LFO2 = + new ModelIdentifier("lfo", null, 1); + public static final ModelIdentifier SOURCE_MIDI_PITCH = + new ModelIdentifier("midi", "pitch", 0); // (0..16383) + public static final ModelIdentifier SOURCE_MIDI_CHANNEL_PRESSURE = + new ModelIdentifier("midi", "channel_pressure", 0); // (0..127) +// public static final ModelIdentifier SOURCE_MIDI_MONO_PRESSURE = +// new ModelIdentifier("midi","mono_pressure",0); // (0..127) + public static final ModelIdentifier SOURCE_MIDI_POLY_PRESSURE = + new ModelIdentifier("midi", "poly_pressure", 0); // (0..127) + public static final ModelIdentifier SOURCE_MIDI_CC_0 = + new ModelIdentifier("midi_cc", "0", 0); // (0..127) + public static final ModelIdentifier SOURCE_MIDI_RPN_0 = + new ModelIdentifier("midi_rpn", "0", 0); // (0..16383) + private ModelIdentifier source = SOURCE_NONE; + private ModelTransform transform; + + public ModelSource() { + this.transform = new ModelStandardTransform(); + } + + public ModelSource(ModelIdentifier id) { + source = id; + this.transform = new ModelStandardTransform(); + } + + public ModelSource(ModelIdentifier id, boolean direction) { + source = id; + this.transform = new ModelStandardTransform(direction); + } + + public ModelSource(ModelIdentifier id, boolean direction, boolean polarity) { + source = id; + this.transform = new ModelStandardTransform(direction, polarity); + } + + public ModelSource(ModelIdentifier id, boolean direction, boolean polarity, + int transform) { + source = id; + this.transform = + new ModelStandardTransform(direction, polarity, transform); + } + + public ModelSource(ModelIdentifier id, ModelTransform transform) { + source = id; + this.transform = transform; + } + + public ModelIdentifier getIdentifier() { + return source; + } + + public void setIdentifier(ModelIdentifier source) { + this.source = source; + } + + public ModelTransform getTransform() { + return transform; + } + + public void setTransform(ModelTransform transform) { + this.transform = transform; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java b/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java new file mode 100644 index 00000000000..f9c9fc21b25 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelStandardDirector.java @@ -0,0 +1,86 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A standard director who chooses performers + * by there keyfrom,keyto,velfrom,velto properties. + * + * @author Karl Helgason + */ +public class ModelStandardDirector implements ModelDirector { + + ModelPerformer[] performers; + ModelDirectedPlayer player; + boolean noteOnUsed = false; + boolean noteOffUsed = false; + + public ModelStandardDirector(ModelPerformer[] performers, + ModelDirectedPlayer player) { + this.performers = performers; + this.player = player; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if (p.isReleaseTriggered()) { + noteOffUsed = true; + } else { + noteOnUsed = true; + } + } + } + + public void close() { + } + + public void noteOff(int noteNumber, int velocity) { + if (!noteOffUsed) + return; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber) { + if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity) { + if (p.isReleaseTriggered()) { + player.play(i, null); + } + } + } + } + } + + public void noteOn(int noteNumber, int velocity) { + if (!noteOnUsed) + return; + for (int i = 0; i < performers.length; i++) { + ModelPerformer p = performers[i]; + if (p.getKeyFrom() <= noteNumber && p.getKeyTo() >= noteNumber) { + if (p.getVelFrom() <= velocity && p.getVelTo() >= velocity) { + if (!p.isReleaseTriggered()) { + player.play(i, null); + } + } + } + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java b/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java new file mode 100644 index 00000000000..8cac033b343 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelStandardTransform.java @@ -0,0 +1,139 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A standard transformer used in connection blocks. + * It expects input values to be between 0 and 1. + * + * The result of the transform is + * between 0 and 1 if polarity = unipolar and + * between -1 and 1 if polarity = bipolar. + * + * These constraints only applies to Concave, Convex and Switch transforms. + * + * @author Karl Helgason + */ +public class ModelStandardTransform implements ModelTransform { + + public static final boolean DIRECTION_MIN2MAX = false; + public static final boolean DIRECTION_MAX2MIN = true; + public static final boolean POLARITY_UNIPOLAR = false; + public static final boolean POLARITY_BIPOLAR = true; + public static final int TRANSFORM_LINEAR = 0; + // concave: output = (20*log10(127^2/value^2)) / 96 + public static final int TRANSFORM_CONCAVE = 1; + // convex: same as concave except that start and end point are reversed. + public static final int TRANSFORM_CONVEX = 2; + // switch: if value > avg(max,min) then max else min + public static final int TRANSFORM_SWITCH = 3; + public static final int TRANSFORM_ABSOLUTE = 4; + private boolean direction = DIRECTION_MIN2MAX; + private boolean polarity = POLARITY_UNIPOLAR; + private int transform = TRANSFORM_LINEAR; + + public ModelStandardTransform() { + } + + public ModelStandardTransform(boolean direction) { + this.direction = direction; + } + + public ModelStandardTransform(boolean direction, boolean polarity) { + this.direction = direction; + this.polarity = polarity; + } + + public ModelStandardTransform(boolean direction, boolean polarity, + int transform) { + this.direction = direction; + this.polarity = polarity; + this.transform = transform; + } + + public double transform(double value) { + double s; + double a; + if (direction == DIRECTION_MAX2MIN) + value = 1.0 - value; + if (polarity == POLARITY_BIPOLAR) + value = value * 2.0 - 1.0; + switch (transform) { + case TRANSFORM_CONCAVE: + s = Math.signum(value); + a = Math.abs(value); + a = -((5.0 / 12.0) / Math.log(10)) * Math.log(1.0 - a); + if (a < 0) + a = 0; + else if (a > 1) + a = 1; + return s * a; + case TRANSFORM_CONVEX: + s = Math.signum(value); + a = Math.abs(value); + a = 1.0 + ((5.0 / 12.0) / Math.log(10)) * Math.log(a); + if (a < 0) + a = 0; + else if (a > 1) + a = 1; + return s * a; + case TRANSFORM_SWITCH: + if (polarity == POLARITY_BIPOLAR) + return (value > 0) ? 1 : -1; + else + return (value > 0.5) ? 1 : 0; + case TRANSFORM_ABSOLUTE: + return Math.abs(value); + default: + break; + } + + return value; + } + + public boolean getDirection() { + return direction; + } + + public void setDirection(boolean direction) { + this.direction = direction; + } + + public boolean getPolarity() { + return polarity; + } + + public void setPolarity(boolean polarity) { + this.polarity = polarity; + } + + public int getTransform() { + return transform; + } + + public void setTransform(int transform) { + this.transform = transform; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java b/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java new file mode 100644 index 00000000000..8b12938ba77 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelTransform.java @@ -0,0 +1,35 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Model transform interface. + * + * @author Karl Helgason + */ +public interface ModelTransform { + + abstract public double transform(double value); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java b/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java new file mode 100644 index 00000000000..b162ce1a700 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/ModelWavetable.java @@ -0,0 +1,49 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This is a wavetable oscillator interface. + * + * @author Karl Helgason + */ +public interface ModelWavetable extends ModelOscillator { + + public static final int LOOP_TYPE_OFF = 0; + public static final int LOOP_TYPE_FORWARD = 1; + public static final int LOOP_TYPE_RELEASE = 2; + public static final int LOOP_TYPE_PINGPONG = 4; + public static final int LOOP_TYPE_REVERSE = 8; + + public AudioFloatInputStream openStream(); + + public float getLoopLength(); + + public float getLoopStart(); + + public int getLoopType(); + + public float getPitchcorrection(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/Platform.java b/jdk/src/share/classes/com/sun/media/sound/Platform.java index 7dc55a50bf9..c29c0becf35 100644 --- a/jdk/src/share/classes/com/sun/media/sound/Platform.java +++ b/jdk/src/share/classes/com/sun/media/sound/Platform.java @@ -42,8 +42,6 @@ class Platform { // native library we need to load private static final String libNameMain = "jsound"; - private static final String libNameMain2 = "jsoundhs"; - private static final String libNameALSA = "jsoundalsa"; private static final String libNameDSound = "jsoundds"; @@ -158,9 +156,8 @@ class Platform { if(Printer.trace)Printer.trace(">>Platform.loadLibraries"); try { - // load the main libraries + // load the main library JSSecurityManager.loadLibrary(libNameMain); - JSSecurityManager.loadLibrary(libNameMain2); // just for the heck of it... loadedLibs |= LIB_MAIN; } catch (SecurityException e) { diff --git a/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java b/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java new file mode 100644 index 00000000000..0202b00ac8f --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidDataException.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This exception is used when a RIFF file contains illegal or unexpected data. + * + * @author Karl Helgason + */ +public class RIFFInvalidDataException extends InvalidDataException { + + private static final long serialVersionUID = 1L; + + public RIFFInvalidDataException() { + super("Invalid Data!"); + } + + public RIFFInvalidDataException(String s) { + super(s); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java b/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java new file mode 100644 index 00000000000..edab090e1f2 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/RIFFInvalidFormatException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * This exception is used when a reader is used to read RIFF file of a format it + * doesn't unterstand or support. + * + * @author Karl Helgason + */ +public class RIFFInvalidFormatException extends InvalidFormatException { + + private static final long serialVersionUID = 1L; + + public RIFFInvalidFormatException() { + super("Invalid format!"); + } + + public RIFFInvalidFormatException(String s) { + super(s); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java b/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java new file mode 100644 index 00000000000..3433bdecb36 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/RIFFReader.java @@ -0,0 +1,332 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +/** + * Resource Interchange File Format (RIFF) stream decoder. + * + * @author Karl Helgason + */ +public class RIFFReader extends InputStream { + + private RIFFReader root; + private long filepointer = 0; + private String fourcc; + private String riff_type = null; + private long ckSize = 0; + private InputStream stream; + private long avail; + private RIFFReader lastiterator = null; + + public RIFFReader(InputStream stream) throws IOException { + + if (stream instanceof RIFFReader) + root = ((RIFFReader)stream).root; + else + root = this; + + this.stream = stream; + avail = Integer.MAX_VALUE; + ckSize = Integer.MAX_VALUE; + + // Check for RIFF null paddings, + int b; + while (true) { + b = read(); + if (b == -1) { + fourcc = ""; // don't put null value into fourcc, + // because it is expected to + // always contain a string value + riff_type = null; + avail = 0; + return; + } + if (b != 0) + break; + } + + byte[] fourcc = new byte[4]; + fourcc[0] = (byte) b; + readFully(fourcc, 1, 3); + this.fourcc = new String(fourcc, "ascii"); + ckSize = readUnsignedInt(); + + avail = this.ckSize; + + if (getFormat().equals("RIFF") || getFormat().equals("LIST")) { + byte[] format = new byte[4]; + readFully(format); + this.riff_type = new String(format, "ascii"); + } + } + + public long getFilePointer() throws IOException { + return root.filepointer; + } + + public boolean hasNextChunk() throws IOException { + if (lastiterator != null) + lastiterator.finish(); + return avail != 0; + } + + public RIFFReader nextChunk() throws IOException { + if (lastiterator != null) + lastiterator.finish(); + if (avail == 0) + return null; + lastiterator = new RIFFReader(this); + return lastiterator; + } + + public String getFormat() { + return fourcc; + } + + public String getType() { + return riff_type; + } + + public long getSize() { + return ckSize; + } + + public int read() throws IOException { + if (avail == 0) + return -1; + int b = stream.read(); + if (b == -1) + return -1; + avail--; + filepointer++; + return b; + } + + public int read(byte[] b, int offset, int len) throws IOException { + if (avail == 0) + return -1; + if (len > avail) { + int rlen = stream.read(b, offset, (int)avail); + if (rlen != -1) + filepointer += rlen; + avail = 0; + return rlen; + } else { + int ret = stream.read(b, offset, len); + if (ret == -1) + return -1; + avail -= ret; + filepointer += ret; + return ret; + } + } + + public final void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + public final void readFully(byte b[], int off, int len) throws IOException { + if (len < 0) + throw new IndexOutOfBoundsException(); + while (len > 0) { + int s = read(b, off, len); + if (s < 0) + throw new EOFException(); + if (s == 0) + Thread.yield(); + off += s; + len -= s; + } + } + + public final long skipBytes(long n) throws IOException { + if (n < 0) + return 0; + long skipped = 0; + while (skipped != n) { + long s = skip(n - skipped); + if (s < 0) + break; + if (s == 0) + Thread.yield(); + skipped += s; + } + return skipped; + } + + public long skip(long n) throws IOException { + if (avail == 0) + return -1; + if (n > avail) { + long len = stream.skip(avail); + if (len != -1) + filepointer += len; + avail = 0; + return len; + } else { + long ret = stream.skip(n); + if (ret == -1) + return -1; + avail -= ret; + filepointer += ret; + return ret; + } + } + + public int available() { + return (int)avail; + } + + public void finish() throws IOException { + if (avail != 0) { + skipBytes(avail); + } + } + + // Read ASCII chars from stream + public String readString(int len) throws IOException { + byte[] buff = new byte[len]; + readFully(buff); + for (int i = 0; i < buff.length; i++) { + if (buff[i] == 0) { + return new String(buff, 0, i, "ascii"); + } + } + return new String(buff, "ascii"); + } + + // Read 8 bit signed integer from stream + public byte readByte() throws IOException { + int ch = read(); + if (ch < 0) + throw new EOFException(); + return (byte) ch; + } + + // Read 16 bit signed integer from stream + public short readShort() throws IOException { + int ch1 = read(); + int ch2 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + return (short)(ch1 | (ch2 << 8)); + } + + // Read 32 bit signed integer from stream + public int readInt() throws IOException { + int ch1 = read(); + int ch2 = read(); + int ch3 = read(); + int ch4 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + } + + // Read 64 bit signed integer from stream + public long readLong() throws IOException { + long ch1 = read(); + long ch2 = read(); + long ch3 = read(); + long ch4 = read(); + long ch5 = read(); + long ch6 = read(); + long ch7 = read(); + long ch8 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + if (ch5 < 0) + throw new EOFException(); + if (ch6 < 0) + throw new EOFException(); + if (ch7 < 0) + throw new EOFException(); + if (ch8 < 0) + throw new EOFException(); + return ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24) + | (ch5 << 32) | (ch6 << 40) | (ch7 << 48) | (ch8 << 56); + } + + // Read 8 bit unsigned integer from stream + public int readUnsignedByte() throws IOException { + int ch = read(); + if (ch < 0) + throw new EOFException(); + return ch; + } + + // Read 16 bit unsigned integer from stream + public int readUnsignedShort() throws IOException { + int ch1 = read(); + int ch2 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + return ch1 | (ch2 << 8); + } + + // Read 32 bit unsigned integer from stream + public long readUnsignedInt() throws IOException { + long ch1 = read(); + long ch2 = read(); + long ch3 = read(); + long ch4 = read(); + if (ch1 < 0) + throw new EOFException(); + if (ch2 < 0) + throw new EOFException(); + if (ch3 < 0) + throw new EOFException(); + if (ch4 < 0) + throw new EOFException(); + return ch1 + (ch2 << 8) | (ch3 << 16) | (ch4 << 24); + } + + public void close() throws IOException { + finish(); + if (this == root) + stream.close(); + stream = null; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java b/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java new file mode 100644 index 00000000000..0c59f36a69f --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/RIFFWriter.java @@ -0,0 +1,365 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +/** + * Resource Interchange File Format (RIFF) stream encoder. + * + * @author Karl Helgason + */ +public class RIFFWriter extends OutputStream { + + private interface RandomAccessWriter { + + public void seek(long chunksizepointer) throws IOException; + + public long getPointer() throws IOException; + + public void close() throws IOException; + + public void write(int b) throws IOException; + + public void write(byte[] b, int off, int len) throws IOException; + + public void write(byte[] bytes) throws IOException; + + public long length() throws IOException; + + public void setLength(long i) throws IOException; + } + + private static class RandomAccessFileWriter implements RandomAccessWriter { + + RandomAccessFile raf; + + public RandomAccessFileWriter(File file) throws FileNotFoundException { + this.raf = new RandomAccessFile(file, "rw"); + } + + public RandomAccessFileWriter(String name) throws FileNotFoundException { + this.raf = new RandomAccessFile(name, "rw"); + } + + public void seek(long chunksizepointer) throws IOException { + raf.seek(chunksizepointer); + } + + public long getPointer() throws IOException { + return raf.getFilePointer(); + } + + public void close() throws IOException { + raf.close(); + } + + public void write(int b) throws IOException { + raf.write(b); + } + + public void write(byte[] b, int off, int len) throws IOException { + raf.write(b, off, len); + } + + public void write(byte[] bytes) throws IOException { + raf.write(bytes); + } + + public long length() throws IOException { + return raf.length(); + } + + public void setLength(long i) throws IOException { + raf.setLength(i); + } + } + + private static class RandomAccessByteWriter implements RandomAccessWriter { + + byte[] buff = new byte[32]; + int length = 0; + int pos = 0; + byte[] s; + OutputStream stream; + + public RandomAccessByteWriter(OutputStream stream) { + this.stream = stream; + } + + public void seek(long chunksizepointer) throws IOException { + pos = (int) chunksizepointer; + } + + public long getPointer() throws IOException { + return pos; + } + + public void close() throws IOException { + stream.write(buff, 0, length); + stream.close(); + } + + public void write(int b) throws IOException { + if (s == null) + s = new byte[1]; + s[0] = (byte)b; + write(s, 0, 1); + } + + public void write(byte[] b, int off, int len) throws IOException { + int newsize = pos + len; + if (newsize > length) + setLength(newsize); + int end = off + len; + for (int i = off; i < end; i++) { + buff[pos++] = b[i]; + } + } + + public void write(byte[] bytes) throws IOException { + write(bytes, 0, bytes.length); + } + + public long length() throws IOException { + return length; + } + + public void setLength(long i) throws IOException { + length = (int) i; + if (length > buff.length) { + int newlen = Math.max(buff.length << 1, length); + byte[] newbuff = new byte[newlen]; + System.arraycopy(buff, 0, newbuff, 0, buff.length); + buff = newbuff; + } + } + } + private int chunktype = 0; // 0=RIFF, 1=LIST; 2=CHUNK + private RandomAccessWriter raf; + private long chunksizepointer; + private long startpointer; + private RIFFWriter childchunk = null; + private boolean open = true; + private boolean writeoverride = false; + + public RIFFWriter(String name, String format) throws IOException { + this(new RandomAccessFileWriter(name), format, 0); + } + + public RIFFWriter(File file, String format) throws IOException { + this(new RandomAccessFileWriter(file), format, 0); + } + + public RIFFWriter(OutputStream stream, String format) throws IOException { + this(new RandomAccessByteWriter(stream), format, 0); + } + + private RIFFWriter(RandomAccessWriter raf, String format, int chunktype) + throws IOException { + if (chunktype == 0) + if (raf.length() != 0) + raf.setLength(0); + this.raf = raf; + if (raf.getPointer() % 2 != 0) + raf.write(0); + + if (chunktype == 0) + raf.write("RIFF".getBytes("ascii")); + else if (chunktype == 1) + raf.write("LIST".getBytes("ascii")); + else + raf.write((format + " ").substring(0, 4).getBytes("ascii")); + + chunksizepointer = raf.getPointer(); + this.chunktype = 2; + writeUnsignedInt(0); + this.chunktype = chunktype; + startpointer = raf.getPointer(); + if (chunktype != 2) + raf.write((format + " ").substring(0, 4).getBytes("ascii")); + + } + + public void seek(long pos) throws IOException { + raf.seek(pos); + } + + public long getFilePointer() throws IOException { + return raf.getPointer(); + } + + public void setWriteOverride(boolean writeoverride) { + this.writeoverride = writeoverride; + } + + public boolean getWriteOverride() { + return writeoverride; + } + + public void close() throws IOException { + if (!open) + return; + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + + int bakchunktype = chunktype; + long fpointer = raf.getPointer(); + raf.seek(chunksizepointer); + chunktype = 2; + writeUnsignedInt(fpointer - startpointer); + + if (bakchunktype == 0) + raf.close(); + else + raf.seek(fpointer); + open = false; + raf = null; + } + + public void write(int b) throws IOException { + if (!writeoverride) { + if (chunktype != 2) { + throw new IllegalArgumentException( + "Only chunks can write bytes!"); + } + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + } + raf.write(b); + } + + public void write(byte b[], int off, int len) throws IOException { + if (!writeoverride) { + if (chunktype != 2) { + throw new IllegalArgumentException( + "Only chunks can write bytes!"); + } + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + } + raf.write(b, off, len); + } + + public RIFFWriter writeList(String format) throws IOException { + if (chunktype == 2) { + throw new IllegalArgumentException( + "Only LIST and RIFF can write lists!"); + } + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + childchunk = new RIFFWriter(this.raf, format, 1); + return childchunk; + } + + public RIFFWriter writeChunk(String format) throws IOException { + if (chunktype == 2) { + throw new IllegalArgumentException( + "Only LIST and RIFF can write chunks!"); + } + if (childchunk != null) { + childchunk.close(); + childchunk = null; + } + childchunk = new RIFFWriter(this.raf, format, 2); + return childchunk; + } + + // Write ASCII chars to stream + public void writeString(String string) throws IOException { + byte[] buff = string.getBytes(); + write(buff); + } + + // Write ASCII chars to stream + public void writeString(String string, int len) throws IOException { + byte[] buff = string.getBytes(); + if (buff.length > len) + write(buff, 0, len); + else { + write(buff); + for (int i = buff.length; i < len; i++) + write(0); + } + } + + // Write 8 bit signed integer to stream + public void writeByte(int b) throws IOException { + write(b); + } + + // Write 16 bit signed integer to stream + public void writeShort(short b) throws IOException { + write((b >>> 0) & 0xFF); + write((b >>> 8) & 0xFF); + } + + // Write 32 bit signed integer to stream + public void writeInt(int b) throws IOException { + write((b >>> 0) & 0xFF); + write((b >>> 8) & 0xFF); + write((b >>> 16) & 0xFF); + write((b >>> 24) & 0xFF); + } + + // Write 64 bit signed integer to stream + public void writeLong(long b) throws IOException { + write((int) (b >>> 0) & 0xFF); + write((int) (b >>> 8) & 0xFF); + write((int) (b >>> 16) & 0xFF); + write((int) (b >>> 24) & 0xFF); + write((int) (b >>> 32) & 0xFF); + write((int) (b >>> 40) & 0xFF); + write((int) (b >>> 48) & 0xFF); + write((int) (b >>> 56) & 0xFF); + } + + // Write 8 bit unsigned integer to stream + public void writeUnsignedByte(int b) throws IOException { + writeByte((byte) b); + } + + // Write 16 bit unsigned integer to stream + public void writeUnsignedShort(int b) throws IOException { + writeShort((short) b); + } + + // Write 32 bit unsigned integer to stream + public void writeUnsignedInt(long b) throws IOException { + writeInt((int) b); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java b/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java index 82ef73c8c8b..bdb092cbf16 100644 --- a/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java +++ b/jdk/src/share/classes/com/sun/media/sound/RealTimeSequencer.java @@ -54,10 +54,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon private final static boolean DEBUG_PUMP = false; private final static boolean DEBUG_PUMP_ALL = false; - - /** if true, we bridge RMF files over to the old MixerSequencer */ - private final static boolean RMF = true; - /** * Event Dispatcher thread. Should be using a shared event * dispatcher instance with a factory in EventDispatcher @@ -145,9 +141,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon private ArrayList controllerEventListeners = new ArrayList(); - /** for RMF media we need the RMF sequencer */ - private MixerSequencer seqBridge = null; - /** automatic connection support */ private boolean autoConnect = false; @@ -220,21 +213,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon playThread.setSequence(sequence); } } - if (RMF) { - if (seqBridge != null) { - seqBridge.close(); - seqBridge = null; - } - // if previous file was an RMF, but this file is not RMF, - // then need to call implOpen again! - if (isOpen() && sequence != null && playThread == null) { - try { - implOpen(); - } catch (MidiUnavailableException mue) { - if (Printer.err) mue.printStackTrace(); - } - } - } if (Printer.trace) Printer.trace("<< RealTimeSequencer: setSequence(" + sequence +") completed"); } @@ -249,52 +227,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon return; } - // need to be able to detect RMF - if (RMF) { - MidiFileFormat fileFormat = MidiSystem.getMidiFileFormat(stream); // can throw IOException, InvalidMidiDataException - int type = fileFormat.getType(); - int resolution = fileFormat.getResolution(); - if (Printer.debug) Printer.debug("Got file with type="+type+" and resolution="+resolution); - if (resolution == MidiFileFormat.UNKNOWN_LENGTH) { - // seems to be RMF - if (seqBridge == null) { - try { - seqBridge = new MixerSequencer(); - if (isOpen()) { - seqBridge.open(); - } - } catch (MidiUnavailableException mue) { - // uhum, strange situation. Need to cast to InvalidMidiDataException - throw new InvalidMidiDataException(mue.getMessage()); - } - } - seqBridge.setSequence(stream); - // propagate state - seqBridge.setTempoFactor(getTempoFactor()); - - // propagate listeners - synchronized(metaEventListeners) { - for (int i = 0 ; i < metaEventListeners.size(); i++) { - seqBridge.addMetaEventListener((MetaEventListener) (metaEventListeners.get(i))); - } - } - synchronized(controllerEventListeners) { - for (int i = 0 ; i < controllerEventListeners.size(); i++) { - ControllerListElement cve = (ControllerListElement) (controllerEventListeners.get(i)); - seqBridge.addControllerEventListener(cve.listener, cve.controllers); - } - } - // disable the current sequence of RealTimeSequencer - //setSequence((Sequence) null); -> will remove bridge again! - this.sequence = null; - return; - } - if (seqBridge != null) { - seqBridge.close(); - seqBridge = null; - } - } - Sequence seq = MidiSystem.getSequence(stream); // can throw IOException, InvalidMidiDataException setSequence(seq); @@ -305,22 +237,11 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public Sequence getSequence() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getSequence(); - } - } return sequence; } public synchronized void start() { - if (RMF) { - if (seqBridge != null) { - seqBridge.start(); - return; - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: start()"); // sequencer not open: throw an exception @@ -346,12 +267,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized void stop() { - if (RMF) { - if (seqBridge != null) { - seqBridge.stop(); - return; - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: stop()"); if (!isOpen()) { @@ -373,23 +288,11 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public boolean isRunning() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.isRunning(); - } - } return running; } public void startRecording() { - if (RMF) { - if (seqBridge != null) { - seqBridge.startRecording(); - return; - } - } - if (!isOpen()) { throw new IllegalStateException("Sequencer not open"); } @@ -400,13 +303,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void stopRecording() { - if (RMF) { - if (seqBridge != null) { - seqBridge.stopRecording(); - return; - } - } - if (!isOpen()) { throw new IllegalStateException("Sequencer not open"); } @@ -415,23 +311,11 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public boolean isRecording() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.isRecording(); - } - } return recording; } public void recordEnable(Track track, int channel) { - if (RMF) { - if (seqBridge != null) { - seqBridge.recordEnable(track, channel); - return; - } - } - if (!findTrack(track)) { throw new IllegalArgumentException("Track does not exist in the current sequence"); } @@ -449,13 +333,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void recordDisable(Track track) { - if (RMF) { - if (seqBridge != null) { - seqBridge.recordDisable(track); - return; - } - } - synchronized(recordingTracks) { RecordingTrack rc = RecordingTrack.get(recordingTracks, track); if (rc != null) { @@ -482,11 +359,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public float getTempoInBPM() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTempoInBPM(); - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoInBPM() "); return (float) MidiUtils.convertTempo(getTempoInMPQ()); @@ -494,12 +366,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setTempoInBPM(float bpm) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTempoInBPM(bpm); - return; - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: setTempoInBPM() "); if (bpm <= 0) { // should throw IllegalArgumentException @@ -511,12 +377,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public float getTempoInMPQ() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTempoInMPQ(); - } - } - if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoInMPQ() "); if (needCaching()) { @@ -537,12 +397,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setTempoInMPQ(float mpq) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTempoInMPQ(mpq); - return; - } - } if (mpq <= 0) { // should throw IllegalArgumentException mpq = 1.0f; @@ -564,12 +418,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setTempoFactor(float factor) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTempoFactor(factor); - return; - } - } if (factor <= 0) { // should throw IllegalArgumentException return; @@ -588,11 +436,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public float getTempoFactor() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTempoFactor(); - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTempoFactor() "); if (needCaching()) { @@ -606,11 +449,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public long getTickLength() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTickLength(); - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTickLength() "); if (sequence == null) { @@ -622,11 +460,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized long getTickPosition() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTickPosition(); - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: getTickPosition() "); if (getDataPump() == null || sequence == null) { @@ -638,12 +471,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized void setTickPosition(long tick) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTickPosition(tick); - return; - } - } if (tick < 0) { // should throw IllegalArgumentException return; @@ -667,12 +494,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public long getMicrosecondLength() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getMicrosecondLength(); - } - } - if (Printer.trace) Printer.trace(">> RealTimeSequencer: getMicrosecondLength() "); if (sequence == null) { @@ -684,12 +505,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public long getMicrosecondPosition() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getMicrosecondPosition(); - } - } - if (Printer.trace) Printer.trace(">> RealTimeSequencer: getMicrosecondPosition() "); if (getDataPump() == null || sequence == null) { @@ -702,13 +517,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setMicrosecondPosition(long microseconds) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setMicrosecondPosition(microseconds); - return; - } - } - if (microseconds < 0) { // should throw IllegalArgumentException return; @@ -734,33 +542,16 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setMasterSyncMode(Sequencer.SyncMode sync) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setMasterSyncMode(sync); - return; - } - } // not supported } public Sequencer.SyncMode getMasterSyncMode() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getMasterSyncMode(); - } - } return masterSyncMode; } public Sequencer.SyncMode[] getMasterSyncModes() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getMasterSyncModes(); - } - } - Sequencer.SyncMode[] returnedModes = new Sequencer.SyncMode[masterSyncModes.length]; System.arraycopy(masterSyncModes, 0, returnedModes, 0, masterSyncModes.length); return returnedModes; @@ -768,33 +559,16 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void setSlaveSyncMode(Sequencer.SyncMode sync) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setSlaveSyncMode(sync); - return; - } - } // not supported } public Sequencer.SyncMode getSlaveSyncMode() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getSlaveSyncMode(); - } - } return slaveSyncMode; } public Sequencer.SyncMode[] getSlaveSyncModes() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getSlaveSyncModes(); - } - } - Sequencer.SyncMode[] returnedModes = new Sequencer.SyncMode[slaveSyncModes.length]; System.arraycopy(slaveSyncModes, 0, returnedModes, 0, slaveSyncModes.length); return returnedModes; @@ -812,12 +586,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized void setTrackMute(int track, boolean mute) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTrackMute(track, mute); - return; - } - } int trackCount = getTrackCount(); if (track < 0 || track >= getTrackCount()) return; trackMuted = ensureBoolArraySize(trackMuted, trackCount); @@ -829,11 +597,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized boolean getTrackMute(int track) { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTrackMute(track); - } - } if (track < 0 || track >= getTrackCount()) return false; if (trackMuted == null || trackMuted.length <= track) return false; return trackMuted[track]; @@ -841,12 +604,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized void setTrackSolo(int track, boolean solo) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setTrackSolo(track, solo); - return; - } - } int trackCount = getTrackCount(); if (track < 0 || track >= getTrackCount()) return; trackSolo = ensureBoolArraySize(trackSolo, trackCount); @@ -858,11 +615,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public synchronized boolean getTrackSolo(int track) { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getTrackSolo(track); - } - } if (track < 0 || track >= getTrackCount()) return false; if (trackSolo == null || trackSolo.length <= track) return false; return trackSolo[track]; @@ -870,12 +622,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public boolean addMetaEventListener(MetaEventListener listener) { - if (RMF) { - if (seqBridge != null) { - seqBridge.addMetaEventListener(listener); - // do not return here! - } - } synchronized(metaEventListeners) { if (! metaEventListeners.contains(listener)) { @@ -887,12 +633,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public void removeMetaEventListener(MetaEventListener listener) { - if (RMF) { - if (seqBridge != null) { - seqBridge.removeMetaEventListener(listener); - // do not return here! - } - } synchronized(metaEventListeners) { int index = metaEventListeners.indexOf(listener); if (index >= 0) { @@ -903,13 +643,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public int[] addControllerEventListener(ControllerEventListener listener, int[] controllers) { - if (RMF) { - if (seqBridge != null) { - seqBridge.addControllerEventListener(listener, controllers); - // do not return here! - } - } - synchronized(controllerEventListeners) { // first find the listener. if we have one, add the controllers @@ -938,12 +671,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon public int[] removeControllerEventListener(ControllerEventListener listener, int[] controllers) { - if (RMF) { - if (seqBridge != null) { - seqBridge.removeControllerEventListener(listener, controllers); - // do not return here! - } - } synchronized(controllerEventListeners) { ControllerListElement cve = null; boolean flag = false; @@ -973,12 +700,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon ////////////////// LOOPING (added in 1.5) /////////////////////// public void setLoopStartPoint(long tick) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setLoopStartPoint(tick); - return; - } - } if ((tick > getTickLength()) || ((loopEnd != -1) && (tick > loopEnd)) || (tick < 0)) { @@ -988,21 +709,10 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon } public long getLoopStartPoint() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getLoopStartPoint(); - } - } return loopStart; } public void setLoopEndPoint(long tick) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setLoopEndPoint(tick); - return; - } - } if ((tick > getTickLength()) || ((loopStart > tick) && (tick != -1)) || (tick < -1)) { @@ -1012,21 +722,10 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon } public long getLoopEndPoint() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getLoopEndPoint(); - } - } return loopEnd; } public void setLoopCount(int count) { - if (RMF) { - if (seqBridge != null) { - seqBridge.setLoopCount(count); - return; - } - } if (count != LOOP_CONTINUOUSLY && count < 0) { throw new IllegalArgumentException("illegal value for loop count: "+count); @@ -1038,11 +737,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon } public int getLoopCount() { - if (RMF) { - if (seqBridge != null) { - return seqBridge.getLoopCount(); - } - } return loopCount; } @@ -1053,13 +747,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon */ protected void implOpen() throws MidiUnavailableException { if (Printer.trace) Printer.trace(">> RealTimeSequencer: implOpen()"); - if (RMF) { - if (seqBridge != null) { - seqBridge.open(); - if (Printer.trace) Printer.trace("<< RealTimeSequencer: -> called seqBridge.open"); - return; - } - } //openInternalSynth(); @@ -1095,12 +782,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon synth.open(); if (synth instanceof ReferenceCountingDevice) { rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting(); - if (synth.getClass().toString().contains("com.sun.media.sound.MixerSynth") - && (synth.getDefaultSoundbank() == null)) { - // don't use this receiver if no soundbank available - rec = null; - synth.close(); - } } else { rec = synth.getReceiver(); } @@ -1147,12 +828,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon protected synchronized void implClose() { - if (RMF) { - if (seqBridge != null) { - seqBridge.close(); - // don't return here! - } - } if (Printer.trace) Printer.trace(">> RealTimeSequencer: implClose() "); if (playThread == null) { @@ -1302,12 +977,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon // OVERRIDES OF ABSTRACT MIDI DEVICE METHODS protected boolean hasReceivers() { - if (RMF) { - if (seqBridge != null) { - //RMF does not allow recording - return false; - } - } return true; } @@ -1318,12 +987,6 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon protected boolean hasTransmitters() { - if (RMF) { - if (seqBridge != null) { - //RMF does never allow setting own receivers - return false; - } - } return true; } diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java b/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java new file mode 100644 index 00000000000..3740ee96b24 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2GlobalRegion.java @@ -0,0 +1,33 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Soundfont global region. + * + * @author Karl Helgason + */ +public class SF2GlobalRegion extends SF2Region { +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java b/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java new file mode 100644 index 00000000000..ae44a7fe052 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Instrument.java @@ -0,0 +1,911 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Patch; + +/** + * Soundfont instrument. + * + * @author Karl Helgason + */ +public class SF2Instrument extends ModelInstrument { + + protected String name = ""; + protected int preset = 0; + protected int bank = 0; + protected long library = 0; + protected long genre = 0; + protected long morphology = 0; + protected SF2GlobalRegion globalregion = null; + protected List regions + = new ArrayList(); + + public SF2Instrument() { + super(null, null, null, null); + } + + public SF2Instrument(SF2Soundbank soundbank) { + super(soundbank, null, null, null); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Patch getPatch() { + if (bank == 128) + return new ModelPatch(0, preset, true); + else + return new ModelPatch(bank << 7, preset, false); + } + + public void setPatch(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) { + bank = 128; + preset = patch.getProgram(); + } else { + bank = patch.getBank() >> 7; + preset = patch.getProgram(); + } + } + + public Object getData() { + return null; + } + + public long getGenre() { + return genre; + } + + public void setGenre(long genre) { + this.genre = genre; + } + + public long getLibrary() { + return library; + } + + public void setLibrary(long library) { + this.library = library; + } + + public long getMorphology() { + return morphology; + } + + public void setMorphology(long morphology) { + this.morphology = morphology; + } + + public List getRegions() { + return regions; + } + + public SF2GlobalRegion getGlobalRegion() { + return globalregion; + } + + public void setGlobalZone(SF2GlobalRegion zone) { + globalregion = zone; + } + + public String toString() { + if (bank == 128) + return "Drumkit: " + name + " preset #" + preset; + else + return "Instrument: " + name + " bank #" + bank + + " preset #" + preset; + } + + public ModelPerformer[] getPerformers() { + int performercount = 0; + for (SF2InstrumentRegion presetzone : regions) + performercount += presetzone.getLayer().getRegions().size(); + ModelPerformer[] performers = new ModelPerformer[performercount]; + int pi = 0; + + SF2GlobalRegion presetglobal = globalregion; + for (SF2InstrumentRegion presetzone : regions) { + Map pgenerators = new HashMap(); + pgenerators.putAll(presetzone.getGenerators()); + if (presetglobal != null) + pgenerators.putAll(presetglobal.getGenerators()); + + SF2Layer layer = presetzone.getLayer(); + SF2GlobalRegion layerglobal = layer.getGlobalRegion(); + for (SF2LayerRegion layerzone : layer.getRegions()) { + ModelPerformer performer = new ModelPerformer(); + if (layerzone.getSample() != null) + performer.setName(layerzone.getSample().getName()); + else + performer.setName(layer.getName()); + + performers[pi++] = performer; + + int keyfrom = 0; + int keyto = 127; + int velfrom = 0; + int velto = 127; + + if (layerzone.contains(SF2Region.GENERATOR_EXCLUSIVECLASS)) { + performer.setExclusiveClass(layerzone.getInteger( + SF2Region.GENERATOR_EXCLUSIVECLASS)); + } + if (layerzone.contains(SF2Region.GENERATOR_KEYRANGE)) { + byte[] bytes = layerzone.getBytes( + SF2Region.GENERATOR_KEYRANGE); + if (bytes[0] >= 0) + if (bytes[0] > keyfrom) + keyfrom = bytes[0]; + if (bytes[1] >= 0) + if (bytes[1] < keyto) + keyto = bytes[1]; + } + if (layerzone.contains(SF2Region.GENERATOR_VELRANGE)) { + byte[] bytes = layerzone.getBytes( + SF2Region.GENERATOR_VELRANGE); + if (bytes[0] >= 0) + if (bytes[0] > velfrom) + velfrom = bytes[0]; + if (bytes[1] >= 0) + if (bytes[1] < velto) + velto = bytes[1]; + } + if (presetzone.contains(SF2Region.GENERATOR_KEYRANGE)) { + byte[] bytes = presetzone.getBytes( + SF2Region.GENERATOR_KEYRANGE); + if (bytes[0] > keyfrom) + keyfrom = bytes[0]; + if (bytes[1] < keyto) + keyto = bytes[1]; + } + if (presetzone.contains(SF2Region.GENERATOR_VELRANGE)) { + byte[] bytes = presetzone.getBytes( + SF2Region.GENERATOR_VELRANGE); + if (bytes[0] > velfrom) + velfrom = bytes[0]; + if (bytes[1] < velto) + velto = bytes[1]; + } + performer.setKeyFrom(keyfrom); + performer.setKeyTo(keyto); + performer.setVelFrom(velfrom); + performer.setVelTo(velto); + + int startAddrsOffset = layerzone.getShort( + SF2Region.GENERATOR_STARTADDRSOFFSET); + int endAddrsOffset = layerzone.getShort( + SF2Region.GENERATOR_ENDADDRSOFFSET); + int startloopAddrsOffset = layerzone.getShort( + SF2Region.GENERATOR_STARTLOOPADDRSOFFSET); + int endloopAddrsOffset = layerzone.getShort( + SF2Region.GENERATOR_ENDLOOPADDRSOFFSET); + + startAddrsOffset += layerzone.getShort( + SF2Region.GENERATOR_STARTADDRSCOARSEOFFSET) * 32768; + endAddrsOffset += layerzone.getShort( + SF2Region.GENERATOR_ENDADDRSCOARSEOFFSET) * 32768; + startloopAddrsOffset += layerzone.getShort( + SF2Region.GENERATOR_STARTLOOPADDRSCOARSEOFFSET) * 32768; + endloopAddrsOffset += layerzone.getShort( + SF2Region.GENERATOR_ENDLOOPADDRSCOARSEOFFSET) * 32768; + startloopAddrsOffset -= startAddrsOffset; + endloopAddrsOffset -= startAddrsOffset; + + SF2Sample sample = layerzone.getSample(); + int rootkey = sample.originalPitch; + if (layerzone.getShort(SF2Region.GENERATOR_OVERRIDINGROOTKEY) != -1) { + rootkey = layerzone.getShort( + SF2Region.GENERATOR_OVERRIDINGROOTKEY); + } + float pitchcorrection = (-rootkey * 100) + sample.pitchCorrection; + ModelByteBuffer buff = sample.getDataBuffer(); + ModelByteBuffer buff24 = sample.getData24Buffer(); + + if (startAddrsOffset != 0 || endAddrsOffset != 0) { + buff = buff.subbuffer(startAddrsOffset * 2, + buff.capacity() + endAddrsOffset * 2); + if (buff24 != null) { + buff24 = buff24.subbuffer(startAddrsOffset, + buff24.capacity() + endAddrsOffset); + } + + /* + if (startAddrsOffset < 0) + startAddrsOffset = 0; + if (endAddrsOffset > (buff.capacity()/2-startAddrsOffset)) + startAddrsOffset = (int)buff.capacity()/2-startAddrsOffset; + byte[] data = buff.array(); + int off = (int)buff.arrayOffset() + startAddrsOffset*2; + int len = (int)buff.capacity() + endAddrsOffset*2; + if (off+len > data.length) + len = data.length - off; + buff = new ModelByteBuffer(data, off, len); + if(buff24 != null) { + data = buff.array(); + off = (int)buff.arrayOffset() + startAddrsOffset; + len = (int)buff.capacity() + endAddrsOffset; + buff24 = new ModelByteBuffer(data, off, len); + } + */ + } + + ModelByteBufferWavetable osc = new ModelByteBufferWavetable( + buff, sample.getFormat(), pitchcorrection); + if (buff24 != null) + osc.set8BitExtensionBuffer(buff24); + + Map generators = new HashMap(); + if (layerglobal != null) + generators.putAll(layerglobal.getGenerators()); + generators.putAll(layerzone.getGenerators()); + for (Map.Entry gen : pgenerators.entrySet()) { + short val; + if (!generators.containsKey(gen.getKey())) + val = layerzone.getShort(gen.getKey()); + else + val = generators.get(gen.getKey()); + val += gen.getValue(); + generators.put(gen.getKey(), val); + } + + // SampleMode: + // 0 indicates a sound reproduced with no loop + // 1 indicates a sound which loops continuously + // 2 is unused but should be interpreted as indicating no loop + // 3 indicates a sound which loops for the duration of key + // depression then proceeds to play the remainder of the sample. + int sampleMode = getGeneratorValue(generators, + SF2Region.GENERATOR_SAMPLEMODES); + if ((sampleMode == 1) || (sampleMode == 3)) { + if (sample.startLoop >= 0 && sample.endLoop > 0) { + osc.setLoopStart((int)(sample.startLoop + + startloopAddrsOffset)); + osc.setLoopLength((int)(sample.endLoop - sample.startLoop + + endloopAddrsOffset - startloopAddrsOffset)); + if (sampleMode == 1) + osc.setLoopType(ModelWavetable.LOOP_TYPE_FORWARD); + if (sampleMode == 3) + osc.setLoopType(ModelWavetable.LOOP_TYPE_RELEASE); + } + } + performer.getOscillators().add(osc); + + + short volDelay = getGeneratorValue(generators, + SF2Region.GENERATOR_DELAYVOLENV); + short volAttack = getGeneratorValue(generators, + SF2Region.GENERATOR_ATTACKVOLENV); + short volHold = getGeneratorValue(generators, + SF2Region.GENERATOR_HOLDVOLENV); + short volDecay = getGeneratorValue(generators, + SF2Region.GENERATOR_DECAYVOLENV); + short volSustain = getGeneratorValue(generators, + SF2Region.GENERATOR_SUSTAINVOLENV); + short volRelease = getGeneratorValue(generators, + SF2Region.GENERATOR_RELEASEVOLENV); + + if (volHold != -12000) { + short volKeyNumToHold = getGeneratorValue(generators, + SF2Region.GENERATOR_KEYNUMTOVOLENVHOLD); + volHold += 60 * volKeyNumToHold; + float fvalue = -volKeyNumToHold * 128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG1_HOLD; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, + new ModelDestination(dest))); + } + if (volDecay != -12000) { + short volKeyNumToDecay = getGeneratorValue(generators, + SF2Region.GENERATOR_KEYNUMTOVOLENVDECAY); + volDecay += 60 * volKeyNumToDecay; + float fvalue = -volKeyNumToDecay * 128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG1_DECAY; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), fvalue, + new ModelDestination(dest))); + } + + addTimecentValue(performer, + ModelDestination.DESTINATION_EG1_DELAY, volDelay); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG1_ATTACK, volAttack); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG1_HOLD, volHold); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG1_DECAY, volDecay); + //float fvolsustain = (960-volSustain)*(1000.0f/960.0f); + + volSustain = (short)(1000 - volSustain); + if (volSustain < 0) + volSustain = 0; + if (volSustain > 1000) + volSustain = 1000; + + addValue(performer, + ModelDestination.DESTINATION_EG1_SUSTAIN, volSustain); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG1_RELEASE, volRelease); + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOFILTERFC) != 0 + || getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOPITCH) != 0) { + short modDelay = getGeneratorValue(generators, + SF2Region.GENERATOR_DELAYMODENV); + short modAttack = getGeneratorValue(generators, + SF2Region.GENERATOR_ATTACKMODENV); + short modHold = getGeneratorValue(generators, + SF2Region.GENERATOR_HOLDMODENV); + short modDecay = getGeneratorValue(generators, + SF2Region.GENERATOR_DECAYMODENV); + short modSustain = getGeneratorValue(generators, + SF2Region.GENERATOR_SUSTAINMODENV); + short modRelease = getGeneratorValue(generators, + SF2Region.GENERATOR_RELEASEMODENV); + + + if (modHold != -12000) { + short modKeyNumToHold = getGeneratorValue(generators, + SF2Region.GENERATOR_KEYNUMTOMODENVHOLD); + modHold += 60 * modKeyNumToHold; + float fvalue = -modKeyNumToHold * 128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG2_HOLD; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), + fvalue, new ModelDestination(dest))); + } + if (modDecay != -12000) { + short modKeyNumToDecay = getGeneratorValue(generators, + SF2Region.GENERATOR_KEYNUMTOMODENVDECAY); + modDecay += 60 * modKeyNumToDecay; + float fvalue = -modKeyNumToDecay * 128; + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_EG2_DECAY; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), + fvalue, new ModelDestination(dest))); + } + + addTimecentValue(performer, + ModelDestination.DESTINATION_EG2_DELAY, modDelay); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG2_ATTACK, modAttack); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG2_HOLD, modHold); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG2_DECAY, modDecay); + if (modSustain < 0) + modSustain = 0; + if (modSustain > 1000) + modSustain = 1000; + addValue(performer, ModelDestination.DESTINATION_EG2_SUSTAIN, + 1000 - modSustain); + addTimecentValue(performer, + ModelDestination.DESTINATION_EG2_RELEASE, modRelease); + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOFILTERFC) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOFILTERFC); + ModelIdentifier src = ModelSource.SOURCE_EG2; + ModelIdentifier dest + = ModelDestination.DESTINATION_FILTER_FREQ; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), + fvalue, new ModelDestination(dest))); + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOPITCH) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_MODENVTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_EG2; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), + fvalue, new ModelDestination(dest))); + } + + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0 + || getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOPITCH) != 0 + || getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) { + short lfo_freq = getGeneratorValue(generators, + SF2Region.GENERATOR_FREQMODLFO); + short lfo_delay = getGeneratorValue(generators, + SF2Region.GENERATOR_DELAYMODLFO); + addTimecentValue(performer, + ModelDestination.DESTINATION_LFO1_DELAY, lfo_delay); + addValue(performer, + ModelDestination.DESTINATION_LFO1_FREQ, lfo_freq); + } + + short vib_freq = getGeneratorValue(generators, + SF2Region.GENERATOR_FREQVIBLFO); + short vib_delay = getGeneratorValue(generators, + SF2Region.GENERATOR_DELAYVIBLFO); + addTimecentValue(performer, + ModelDestination.DESTINATION_LFO2_DELAY, vib_delay); + addValue(performer, + ModelDestination.DESTINATION_LFO2_FREQ, vib_freq); + + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_VIBLFOTOPITCH) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_VIBLFOTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_LFO2; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + fvalue, new ModelDestination(dest))); + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOFILTERFC) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOFILTERFC); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_FILTER_FREQ; + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + fvalue, new ModelDestination(dest))); + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOPITCH) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOPITCH); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + fvalue, new ModelDestination(dest))); + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOVOLUME) != 0) { + double fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_MODLFOTOVOLUME); + ModelIdentifier src = ModelSource.SOURCE_LFO1; + ModelIdentifier dest = ModelDestination.DESTINATION_GAIN; + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(src, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR), + fvalue, new ModelDestination(dest))); + } + + if (layerzone.getShort(SF2Region.GENERATOR_KEYNUM) != -1) { + double val = layerzone.getShort(SF2Region.GENERATOR_KEYNUM)/128.0; + addValue(performer, ModelDestination.DESTINATION_KEYNUMBER, val); + } + + if (layerzone.getShort(SF2Region.GENERATOR_VELOCITY) != -1) { + double val = layerzone.getShort(SF2Region.GENERATOR_VELOCITY) + / 128.0; + addValue(performer, ModelDestination.DESTINATION_VELOCITY, val); + } + + if (getGeneratorValue(generators, + SF2Region.GENERATOR_INITIALFILTERFC) < 13500) { + short filter_freq = getGeneratorValue(generators, + SF2Region.GENERATOR_INITIALFILTERFC); + short filter_q = getGeneratorValue(generators, + SF2Region.GENERATOR_INITIALFILTERQ); + addValue(performer, + ModelDestination.DESTINATION_FILTER_FREQ, filter_freq); + addValue(performer, + ModelDestination.DESTINATION_FILTER_Q, filter_q); + } + + int tune = 100 * getGeneratorValue(generators, + SF2Region.GENERATOR_COARSETUNE); + tune += getGeneratorValue(generators, + SF2Region.GENERATOR_FINETUNE); + if (tune != 0) { + addValue(performer, + ModelDestination.DESTINATION_PITCH, (short) tune); + } + if (getGeneratorValue(generators, SF2Region.GENERATOR_PAN) != 0) { + short val = getGeneratorValue(generators, + SF2Region.GENERATOR_PAN); + addValue(performer, ModelDestination.DESTINATION_PAN, val); + } + if (getGeneratorValue(generators, SF2Region.GENERATOR_INITIALATTENUATION) != 0) { + short val = getGeneratorValue(generators, + SF2Region.GENERATOR_INITIALATTENUATION); + addValue(performer, + ModelDestination.DESTINATION_GAIN, -0.376287f * val); + } + if (getGeneratorValue(generators, + SF2Region.GENERATOR_CHORUSEFFECTSSEND) != 0) { + short val = getGeneratorValue(generators, + SF2Region.GENERATOR_CHORUSEFFECTSSEND); + addValue(performer, ModelDestination.DESTINATION_CHORUS, val); + } + if (getGeneratorValue(generators, + SF2Region.GENERATOR_REVERBEFFECTSSEND) != 0) { + short val = getGeneratorValue(generators, + SF2Region.GENERATOR_REVERBEFFECTSSEND); + addValue(performer, ModelDestination.DESTINATION_REVERB, val); + } + if (getGeneratorValue(generators, + SF2Region.GENERATOR_SCALETUNING) != 100) { + short fvalue = getGeneratorValue(generators, + SF2Region.GENERATOR_SCALETUNING); + if (fvalue == 0) { + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(null, rootkey * 100, + new ModelDestination(dest))); + } else { + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(null, rootkey * (100 - fvalue), + new ModelDestination(dest))); + } + + ModelIdentifier src = ModelSource.SOURCE_NOTEON_KEYNUMBER; + ModelIdentifier dest = ModelDestination.DESTINATION_PITCH; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(new ModelSource(src), + 128 * fvalue, new ModelDestination(dest))); + + } + + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_NOTEON_VELOCITY, + new ModelTransform() { + public double transform(double value) { + if (value < 0.5) + return 1 - value * 2; + else + return 0; + } + }), + -2400, + new ModelDestination( + ModelDestination.DESTINATION_FILTER_FREQ))); + + + performer.getConnectionBlocks().add( + new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_cc", "1", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 50, new ModelDestination( + ModelDestination.DESTINATION_PITCH))); + + if (layer.getGlobalRegion() != null) { + for (SF2Modulator modulator + : layer.getGlobalRegion().getModulators()) { + convertModulator(performer, modulator); + } + } + for (SF2Modulator modulator : layerzone.getModulators()) + convertModulator(performer, modulator); + + if (presetglobal != null) { + for (SF2Modulator modulator : presetglobal.getModulators()) + convertModulator(performer, modulator); + } + for (SF2Modulator modulator : presetzone.getModulators()) + convertModulator(performer, modulator); + + } + } + return performers; + } + + private void convertModulator(ModelPerformer performer, + SF2Modulator modulator) { + ModelSource src1 = convertSource(modulator.getSourceOperator()); + ModelSource src2 = convertSource(modulator.getAmountSourceOperator()); + if (src1 == null && modulator.getSourceOperator() != 0) + return; + if (src2 == null && modulator.getAmountSourceOperator() != 0) + return; + double amount = modulator.getAmount(); + double[] amountcorrection = new double[1]; + ModelSource[] extrasrc = new ModelSource[1]; + amountcorrection[0] = 1; + ModelDestination dst = convertDestination( + modulator.getDestinationOperator(), amountcorrection, extrasrc); + amount *= amountcorrection[0]; + if (dst == null) + return; + if (modulator.getTransportOperator() == SF2Modulator.TRANSFORM_ABSOLUTE) { + ((ModelStandardTransform)dst.getTransform()).setTransform( + ModelStandardTransform.TRANSFORM_ABSOLUTE); + } + ModelConnectionBlock conn = new ModelConnectionBlock(src1, src2, amount, dst); + if (extrasrc[0] != null) + conn.addSource(extrasrc[0]); + performer.getConnectionBlocks().add(conn); + + } + + private static ModelSource convertSource(int src) { + if (src == 0) + return null; + ModelIdentifier id = null; + int idsrc = src & 0x7F; + if ((src & SF2Modulator.SOURCE_MIDI_CONTROL) != 0) { + id = new ModelIdentifier("midi_cc", Integer.toString(idsrc)); + } else { + if (idsrc == SF2Modulator.SOURCE_NOTE_ON_VELOCITY) + id = ModelSource.SOURCE_NOTEON_VELOCITY; + if (idsrc == SF2Modulator.SOURCE_NOTE_ON_KEYNUMBER) + id = ModelSource.SOURCE_NOTEON_KEYNUMBER; + if (idsrc == SF2Modulator.SOURCE_POLY_PRESSURE) + id = ModelSource.SOURCE_MIDI_POLY_PRESSURE; + if (idsrc == SF2Modulator.SOURCE_CHANNEL_PRESSURE) + id = ModelSource.SOURCE_MIDI_CHANNEL_PRESSURE; + if (idsrc == SF2Modulator.SOURCE_PITCH_WHEEL) + id = ModelSource.SOURCE_MIDI_PITCH; + if (idsrc == SF2Modulator.SOURCE_PITCH_SENSITIVITY) + id = new ModelIdentifier("midi_rpn", "0"); + } + if (id == null) + return null; + + ModelSource msrc = new ModelSource(id); + ModelStandardTransform transform + = (ModelStandardTransform) msrc.getTransform(); + + if ((SF2Modulator.SOURCE_DIRECTION_MAX_MIN & src) != 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + + if ((SF2Modulator.SOURCE_POLARITY_BIPOLAR & src) != 0) + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + + if ((SF2Modulator.SOURCE_TYPE_CONCAVE & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + if ((SF2Modulator.SOURCE_TYPE_CONVEX & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX); + if ((SF2Modulator.SOURCE_TYPE_SWITCH & src) != 0) + transform.setTransform(ModelStandardTransform.TRANSFORM_SWITCH); + + return msrc; + } + + protected static ModelDestination convertDestination(int dst, + double[] amountcorrection, ModelSource[] extrasrc) { + ModelIdentifier id = null; + switch (dst) { + case SF2Region.GENERATOR_INITIALFILTERFC: + id = ModelDestination.DESTINATION_FILTER_FREQ; + break; + case SF2Region.GENERATOR_INITIALFILTERQ: + id = ModelDestination.DESTINATION_FILTER_Q; + break; + case SF2Region.GENERATOR_CHORUSEFFECTSSEND: + id = ModelDestination.DESTINATION_CHORUS; + break; + case SF2Region.GENERATOR_REVERBEFFECTSSEND: + id = ModelDestination.DESTINATION_REVERB; + break; + case SF2Region.GENERATOR_PAN: + id = ModelDestination.DESTINATION_PAN; + break; + case SF2Region.GENERATOR_DELAYMODLFO: + id = ModelDestination.DESTINATION_LFO1_DELAY; + break; + case SF2Region.GENERATOR_FREQMODLFO: + id = ModelDestination.DESTINATION_LFO1_FREQ; + break; + case SF2Region.GENERATOR_DELAYVIBLFO: + id = ModelDestination.DESTINATION_LFO2_DELAY; + break; + case SF2Region.GENERATOR_FREQVIBLFO: + id = ModelDestination.DESTINATION_LFO2_FREQ; + break; + + case SF2Region.GENERATOR_DELAYMODENV: + id = ModelDestination.DESTINATION_EG2_DELAY; + break; + case SF2Region.GENERATOR_ATTACKMODENV: + id = ModelDestination.DESTINATION_EG2_ATTACK; + break; + case SF2Region.GENERATOR_HOLDMODENV: + id = ModelDestination.DESTINATION_EG2_HOLD; + break; + case SF2Region.GENERATOR_DECAYMODENV: + id = ModelDestination.DESTINATION_EG2_DECAY; + break; + case SF2Region.GENERATOR_SUSTAINMODENV: + id = ModelDestination.DESTINATION_EG2_SUSTAIN; + amountcorrection[0] = -1; + break; + case SF2Region.GENERATOR_RELEASEMODENV: + id = ModelDestination.DESTINATION_EG2_RELEASE; + break; + case SF2Region.GENERATOR_DELAYVOLENV: + id = ModelDestination.DESTINATION_EG1_DELAY; + break; + case SF2Region.GENERATOR_ATTACKVOLENV: + id = ModelDestination.DESTINATION_EG1_ATTACK; + break; + case SF2Region.GENERATOR_HOLDVOLENV: + id = ModelDestination.DESTINATION_EG1_HOLD; + break; + case SF2Region.GENERATOR_DECAYVOLENV: + id = ModelDestination.DESTINATION_EG1_DECAY; + break; + case SF2Region.GENERATOR_SUSTAINVOLENV: + id = ModelDestination.DESTINATION_EG1_SUSTAIN; + amountcorrection[0] = -1; + break; + case SF2Region.GENERATOR_RELEASEVOLENV: + id = ModelDestination.DESTINATION_EG1_RELEASE; + break; + case SF2Region.GENERATOR_KEYNUM: + id = ModelDestination.DESTINATION_KEYNUMBER; + break; + case SF2Region.GENERATOR_VELOCITY: + id = ModelDestination.DESTINATION_VELOCITY; + break; + + case SF2Region.GENERATOR_COARSETUNE: + amountcorrection[0] = 100; + id = ModelDestination.DESTINATION_PITCH; + break; + + case SF2Region.GENERATOR_FINETUNE: + id = ModelDestination.DESTINATION_PITCH; + break; + + case SF2Region.GENERATOR_INITIALATTENUATION: + id = ModelDestination.DESTINATION_GAIN; + amountcorrection[0] = -0.376287f; + break; + + case SF2Region.GENERATOR_VIBLFOTOPITCH: + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOPITCH: + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOFILTERFC: + id = ModelDestination.DESTINATION_FILTER_FREQ; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODLFOTOVOLUME: + id = ModelDestination.DESTINATION_GAIN; + amountcorrection[0] = -0.376287f; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODENVTOPITCH: + id = ModelDestination.DESTINATION_PITCH; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_EG2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + case SF2Region.GENERATOR_MODENVTOFILTERFC: + id = ModelDestination.DESTINATION_FILTER_FREQ; + extrasrc[0] = new ModelSource( + ModelSource.SOURCE_EG2, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR); + break; + + default: + break; + } + if (id != null) + return new ModelDestination(id); + return null; + } + + private void addTimecentValue(ModelPerformer performer, + ModelIdentifier dest, short value) { + double fvalue; + if (value == -12000) + fvalue = Double.NEGATIVE_INFINITY; + else + fvalue = value; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private void addValue(ModelPerformer performer, + ModelIdentifier dest, short value) { + double fvalue = value; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private void addValue(ModelPerformer performer, + ModelIdentifier dest, double value) { + double fvalue = value; + performer.getConnectionBlocks().add( + new ModelConnectionBlock(fvalue, new ModelDestination(dest))); + } + + private short getGeneratorValue(Map generators, int gen) { + if (generators.containsKey(gen)) + return generators.get(gen); + return SF2Region.getDefaultValue(gen); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java b/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java new file mode 100644 index 00000000000..a1a09eda54d --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2InstrumentRegion.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Soundfont instrument region. + * + * @author Karl Helgason + */ +public class SF2InstrumentRegion extends SF2Region { + + protected SF2Layer layer; + + public SF2Layer getLayer() { + return layer; + } + + public void setLayer(SF2Layer layer) { + this.layer = layer; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java b/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java new file mode 100644 index 00000000000..7af78a35fc1 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Layer.java @@ -0,0 +1,78 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; + +import javax.sound.midi.SoundbankResource; + +/** + * Soundfont layer. + * + * @author Karl Helgason + */ +public class SF2Layer extends SoundbankResource { + + protected String name = ""; + protected SF2GlobalRegion globalregion = null; + protected List regions = new ArrayList(); + + public SF2Layer(SF2Soundbank soundBank) { + super(soundBank, null, null); + } + + public SF2Layer() { + super(null, null, null); + } + + public Object getData() { + return null; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getRegions() { + return regions; + } + + public SF2GlobalRegion getGlobalRegion() { + return globalregion; + } + + public void setGlobalZone(SF2GlobalRegion zone) { + globalregion = zone; + } + + public String toString() { + return "Layer: " + name; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java b/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java new file mode 100644 index 00000000000..c2006497e0d --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2LayerRegion.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Soundfont layer region. + * + * @author Karl Helgason + */ +public class SF2LayerRegion extends SF2Region { + + protected SF2Sample sample; + + public SF2Sample getSample() { + return sample; + } + + public void setSample(SF2Sample sample) { + this.sample = sample; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java b/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java new file mode 100644 index 00000000000..4851fb12723 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Modulator.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Soundfont modulator container. + * + * @author Karl Helgason + */ +public class SF2Modulator { + + public final static int SOURCE_NONE = 0; + public final static int SOURCE_NOTE_ON_VELOCITY = 2; + public final static int SOURCE_NOTE_ON_KEYNUMBER = 3; + public final static int SOURCE_POLY_PRESSURE = 10; + public final static int SOURCE_CHANNEL_PRESSURE = 13; + public final static int SOURCE_PITCH_WHEEL = 14; + public final static int SOURCE_PITCH_SENSITIVITY = 16; + public final static int SOURCE_MIDI_CONTROL = 128 * 1; + public final static int SOURCE_DIRECTION_MIN_MAX = 256 * 0; + public final static int SOURCE_DIRECTION_MAX_MIN = 256 * 1; + public final static int SOURCE_POLARITY_UNIPOLAR = 512 * 0; + public final static int SOURCE_POLARITY_BIPOLAR = 512 * 1; + public final static int SOURCE_TYPE_LINEAR = 1024 * 0; + public final static int SOURCE_TYPE_CONCAVE = 1024 * 1; + public final static int SOURCE_TYPE_CONVEX = 1024 * 2; + public final static int SOURCE_TYPE_SWITCH = 1024 * 3; + public final static int TRANSFORM_LINEAR = 0; + public final static int TRANSFORM_ABSOLUTE = 2; + protected int sourceOperator; + protected int destinationOperator; + protected short amount; + protected int amountSourceOperator; + protected int transportOperator; + + public short getAmount() { + return amount; + } + + public void setAmount(short amount) { + this.amount = amount; + } + + public int getAmountSourceOperator() { + return amountSourceOperator; + } + + public void setAmountSourceOperator(int amountSourceOperator) { + this.amountSourceOperator = amountSourceOperator; + } + + public int getTransportOperator() { + return transportOperator; + } + + public void setTransportOperator(int transportOperator) { + this.transportOperator = transportOperator; + } + + public int getDestinationOperator() { + return destinationOperator; + } + + public void setDestinationOperator(int destinationOperator) { + this.destinationOperator = destinationOperator; + } + + public int getSourceOperator() { + return sourceOperator; + } + + public void setSourceOperator(int sourceOperator) { + this.sourceOperator = sourceOperator; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Region.java b/jdk/src/share/classes/com/sun/media/sound/SF2Region.java new file mode 100644 index 00000000000..3acef4382a3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Region.java @@ -0,0 +1,167 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Soundfont general region. + * + * @author Karl Helgason + */ +public class SF2Region { + + public final static int GENERATOR_STARTADDRSOFFSET = 0; + public final static int GENERATOR_ENDADDRSOFFSET = 1; + public final static int GENERATOR_STARTLOOPADDRSOFFSET = 2; + public final static int GENERATOR_ENDLOOPADDRSOFFSET = 3; + public final static int GENERATOR_STARTADDRSCOARSEOFFSET = 4; + public final static int GENERATOR_MODLFOTOPITCH = 5; + public final static int GENERATOR_VIBLFOTOPITCH = 6; + public final static int GENERATOR_MODENVTOPITCH = 7; + public final static int GENERATOR_INITIALFILTERFC = 8; + public final static int GENERATOR_INITIALFILTERQ = 9; + public final static int GENERATOR_MODLFOTOFILTERFC = 10; + public final static int GENERATOR_MODENVTOFILTERFC = 11; + public final static int GENERATOR_ENDADDRSCOARSEOFFSET = 12; + public final static int GENERATOR_MODLFOTOVOLUME = 13; + public final static int GENERATOR_UNUSED1 = 14; + public final static int GENERATOR_CHORUSEFFECTSSEND = 15; + public final static int GENERATOR_REVERBEFFECTSSEND = 16; + public final static int GENERATOR_PAN = 17; + public final static int GENERATOR_UNUSED2 = 18; + public final static int GENERATOR_UNUSED3 = 19; + public final static int GENERATOR_UNUSED4 = 20; + public final static int GENERATOR_DELAYMODLFO = 21; + public final static int GENERATOR_FREQMODLFO = 22; + public final static int GENERATOR_DELAYVIBLFO = 23; + public final static int GENERATOR_FREQVIBLFO = 24; + public final static int GENERATOR_DELAYMODENV = 25; + public final static int GENERATOR_ATTACKMODENV = 26; + public final static int GENERATOR_HOLDMODENV = 27; + public final static int GENERATOR_DECAYMODENV = 28; + public final static int GENERATOR_SUSTAINMODENV = 29; + public final static int GENERATOR_RELEASEMODENV = 30; + public final static int GENERATOR_KEYNUMTOMODENVHOLD = 31; + public final static int GENERATOR_KEYNUMTOMODENVDECAY = 32; + public final static int GENERATOR_DELAYVOLENV = 33; + public final static int GENERATOR_ATTACKVOLENV = 34; + public final static int GENERATOR_HOLDVOLENV = 35; + public final static int GENERATOR_DECAYVOLENV = 36; + public final static int GENERATOR_SUSTAINVOLENV = 37; + public final static int GENERATOR_RELEASEVOLENV = 38; + public final static int GENERATOR_KEYNUMTOVOLENVHOLD = 39; + public final static int GENERATOR_KEYNUMTOVOLENVDECAY = 40; + public final static int GENERATOR_INSTRUMENT = 41; + public final static int GENERATOR_RESERVED1 = 42; + public final static int GENERATOR_KEYRANGE = 43; + public final static int GENERATOR_VELRANGE = 44; + public final static int GENERATOR_STARTLOOPADDRSCOARSEOFFSET = 45; + public final static int GENERATOR_KEYNUM = 46; + public final static int GENERATOR_VELOCITY = 47; + public final static int GENERATOR_INITIALATTENUATION = 48; + public final static int GENERATOR_RESERVED2 = 49; + public final static int GENERATOR_ENDLOOPADDRSCOARSEOFFSET = 50; + public final static int GENERATOR_COARSETUNE = 51; + public final static int GENERATOR_FINETUNE = 52; + public final static int GENERATOR_SAMPLEID = 53; + public final static int GENERATOR_SAMPLEMODES = 54; + public final static int GENERATOR_RESERVED3 = 55; + public final static int GENERATOR_SCALETUNING = 56; + public final static int GENERATOR_EXCLUSIVECLASS = 57; + public final static int GENERATOR_OVERRIDINGROOTKEY = 58; + public final static int GENERATOR_UNUSED5 = 59; + public final static int GENERATOR_ENDOPR = 60; + protected Map generators = new HashMap(); + protected List modulators = new ArrayList(); + + public Map getGenerators() { + return generators; + } + + public boolean contains(int generator) { + return generators.containsKey(generator); + } + + static public short getDefaultValue(int generator) { + if (generator == 8) return (short)13500; + if (generator == 21) return (short)-12000; + if (generator == 23) return (short)-12000; + if (generator == 25) return (short)-12000; + if (generator == 26) return (short)-12000; + if (generator == 27) return (short)-12000; + if (generator == 28) return (short)-12000; + if (generator == 30) return (short)-12000; + if (generator == 33) return (short)-12000; + if (generator == 34) return (short)-12000; + if (generator == 35) return (short)-12000; + if (generator == 36) return (short)-12000; + if (generator == 38) return (short)-12000; + if (generator == 43) return (short)0x7F00; + if (generator == 44) return (short)0x7F00; + if (generator == 46) return (short)-1; + if (generator == 47) return (short)-1; + if (generator == 56) return (short)100; + if (generator == 58) return (short)-1; + return 0; + } + + public short getShort(int generator) { + if (!contains(generator)) + return getDefaultValue(generator); + return generators.get(generator); + } + + public void putShort(int generator, short value) { + generators.put(generator, value); + } + + public byte[] getBytes(int generator) { + int val = getInteger(generator); + byte[] bytes = new byte[2]; + bytes[0] = (byte) (0xFF & val); + bytes[1] = (byte) ((0xFF00 & val) >> 8); + return bytes; + } + + public void putBytes(int generator, byte[] bytes) { + generators.put(generator, (short) (bytes[0] + (bytes[1] << 8))); + } + + public int getInteger(int generator) { + return 0xFFFF & getShort(generator); + } + + public void putInteger(int generator, int value) { + generators.put(generator, (short) value); + } + + public List getModulators() { + return modulators; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java b/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java new file mode 100644 index 00000000000..582b34615d3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Sample.java @@ -0,0 +1,216 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.InputStream; + +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * Soundfont sample storage. + * + * @author Karl Helgason + */ +public class SF2Sample extends SoundbankResource { + + protected String name = ""; + protected long startLoop = 0; + protected long endLoop = 0; + protected long sampleRate = 44100; + protected int originalPitch = 60; + protected byte pitchCorrection = 0; + protected int sampleLink = 0; + protected int sampleType = 0; + protected ModelByteBuffer data; + protected ModelByteBuffer data24; + + public SF2Sample(Soundbank soundBank) { + super(soundBank, null, AudioInputStream.class); + } + + public SF2Sample() { + super(null, null, AudioInputStream.class); + } + + public Object getData() { + + AudioFormat format = getFormat(); + /* + if (sampleFile != null) { + FileInputStream fis; + try { + fis = new FileInputStream(sampleFile); + RIFFReader riff = new RIFFReader(fis); + if (!riff.getFormat().equals("RIFF")) { + throw new RIFFInvalidDataException( + "Input stream is not a valid RIFF stream!"); + } + if (!riff.getType().equals("sfbk")) { + throw new RIFFInvalidDataException( + "Input stream is not a valid SoundFont!"); + } + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("sdta")) { + while(chunk.hasNextChunk()) { + RIFFReader chunkchunk = chunk.nextChunk(); + if(chunkchunk.getFormat().equals("smpl")) { + chunkchunk.skip(sampleOffset); + return new AudioInputStream(chunkchunk, + format, sampleLen); + } + } + } + } + } + return null; + } catch (Exception e) { + return new Throwable(e.toString()); + } + } + */ + InputStream is = data.getInputStream(); + if (is == null) + return null; + return new AudioInputStream(is, format, data.capacity()); + } + + public ModelByteBuffer getDataBuffer() { + return data; + } + + public ModelByteBuffer getData24Buffer() { + return data24; + } + + public AudioFormat getFormat() { + return new AudioFormat(sampleRate, 16, 1, true, false); + } + + public void setData(ModelByteBuffer data) { + this.data = data; + } + + public void setData(byte[] data) { + this.data = new ModelByteBuffer(data); + } + + public void setData(byte[] data, int offset, int length) { + this.data = new ModelByteBuffer(data, offset, length); + } + + public void setData24(ModelByteBuffer data24) { + this.data24 = data24; + } + + public void setData24(byte[] data24) { + this.data24 = new ModelByteBuffer(data24); + } + + public void setData24(byte[] data24, int offset, int length) { + this.data24 = new ModelByteBuffer(data24, offset, length); + } + + /* + public void setData(File file, int offset, int length) { + this.data = null; + this.sampleFile = file; + this.sampleOffset = offset; + this.sampleLen = length; + } + */ + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getEndLoop() { + return endLoop; + } + + public void setEndLoop(long endLoop) { + this.endLoop = endLoop; + } + + public int getOriginalPitch() { + return originalPitch; + } + + public void setOriginalPitch(int originalPitch) { + this.originalPitch = originalPitch; + } + + public byte getPitchCorrection() { + return pitchCorrection; + } + + public void setPitchCorrection(byte pitchCorrection) { + this.pitchCorrection = pitchCorrection; + } + + public int getSampleLink() { + return sampleLink; + } + + public void setSampleLink(int sampleLink) { + this.sampleLink = sampleLink; + } + + public long getSampleRate() { + return sampleRate; + } + + public void setSampleRate(long sampleRate) { + this.sampleRate = sampleRate; + } + + public int getSampleType() { + return sampleType; + } + + public void setSampleType(int sampleType) { + this.sampleType = sampleType; + } + + public long getStartLoop() { + return startLoop; + } + + public void setStartLoop(long startLoop) { + this.startLoop = startLoop; + } + + public String toString() { + return "Sample: " + name; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java b/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java new file mode 100644 index 00000000000..7ae60d870e8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2Soundbank.java @@ -0,0 +1,973 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; + +/** + * A SoundFont 2.04 soundbank reader. + * + * Based on SoundFont 2.04 specification from: + *

    http://developer.creative.com
    + * http://www.soundfont.com/ ; + * + * @author Karl Helgason + */ +public class SF2Soundbank implements Soundbank { + + // version of the Sound Font RIFF file + protected int major = 2; + protected int minor = 1; + // target Sound Engine + protected String targetEngine = "EMU8000"; + // Sound Font Bank Name + protected String name = "untitled"; + // Sound ROM Name + protected String romName = null; + // Sound ROM Version + protected int romVersionMajor = -1; + protected int romVersionMinor = -1; + // Date of Creation of the Bank + protected String creationDate = null; + // Sound Designers and Engineers for the Bank + protected String engineers = null; + // Product for which the Bank was intended + protected String product = null; + // Copyright message + protected String copyright = null; + // Comments + protected String comments = null; + // The SoundFont tools used to create and alter the bank + protected String tools = null; + // The Sample Data loaded from the SoundFont + private ModelByteBuffer sampleData = null; + private ModelByteBuffer sampleData24 = null; + private File sampleFile = null; + private boolean largeFormat = false; + private List instruments = new ArrayList(); + private List layers = new ArrayList(); + private List samples = new ArrayList(); + + public SF2Soundbank() { + } + + public SF2Soundbank(URL url) throws IOException { + + InputStream is = url.openStream(); + try { + readSoundbank(is); + } finally { + is.close(); + } + } + + public SF2Soundbank(File file) throws IOException { + largeFormat = true; + sampleFile = file; + InputStream is = new FileInputStream(file); + try { + readSoundbank(is); + } finally { + is.close(); + } + } + + public SF2Soundbank(InputStream inputstream) throws IOException { + readSoundbank(inputstream); + } + + private void readSoundbank(InputStream inputstream) throws IOException { + RIFFReader riff = new RIFFReader(inputstream); + if (!riff.getFormat().equals("RIFF")) { + throw new RIFFInvalidFormatException( + "Input stream is not a valid RIFF stream!"); + } + if (!riff.getType().equals("sfbk")) { + throw new RIFFInvalidFormatException( + "Input stream is not a valid SoundFont!"); + } + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("LIST")) { + if (chunk.getType().equals("INFO")) + readInfoChunk(chunk); + if (chunk.getType().equals("sdta")) + readSdtaChunk(chunk); + if (chunk.getType().equals("pdta")) + readPdtaChunk(chunk); + } + } + } + + private void readInfoChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("ifil")) { + major = chunk.readUnsignedShort(); + minor = chunk.readUnsignedShort(); + } else if (format.equals("isng")) { + this.targetEngine = chunk.readString(chunk.available()); + } else if (format.equals("INAM")) { + this.name = chunk.readString(chunk.available()); + } else if (format.equals("irom")) { + this.romName = chunk.readString(chunk.available()); + } else if (format.equals("iver")) { + romVersionMajor = chunk.readUnsignedShort(); + romVersionMinor = chunk.readUnsignedShort(); + } else if (format.equals("ICRD")) { + this.creationDate = chunk.readString(chunk.available()); + } else if (format.equals("IENG")) { + this.engineers = chunk.readString(chunk.available()); + } else if (format.equals("IPRD")) { + this.product = chunk.readString(chunk.available()); + } else if (format.equals("ICOP")) { + this.copyright = chunk.readString(chunk.available()); + } else if (format.equals("ICMT")) { + this.comments = chunk.readString(chunk.available()); + } else if (format.equals("ISFT")) { + this.tools = chunk.readString(chunk.available()); + } + + } + } + + private void readSdtaChunk(RIFFReader riff) throws IOException { + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + if (chunk.getFormat().equals("smpl")) { + if (!largeFormat) { + byte[] sampleData = new byte[chunk.available()]; + + int read = 0; + int avail = chunk.available(); + while (read != avail) { + if (avail - read > 65536) { + chunk.readFully(sampleData, read, 65536); + read += 65536; + } else { + chunk.readFully(sampleData, read, avail - read); + read = avail; + } + + } + this.sampleData = new ModelByteBuffer(sampleData); + //chunk.read(sampleData); + } else { + this.sampleData = new ModelByteBuffer(sampleFile, + chunk.getFilePointer(), chunk.available()); + } + } + if (chunk.getFormat().equals("sm24")) { + if (!largeFormat) { + byte[] sampleData24 = new byte[chunk.available()]; + //chunk.read(sampleData24); + + int read = 0; + int avail = chunk.available(); + while (read != avail) { + if (avail - read > 65536) { + chunk.readFully(sampleData24, read, 65536); + read += 65536; + } else { + chunk.readFully(sampleData24, read, avail - read); + read = avail; + } + + } + this.sampleData24 = new ModelByteBuffer(sampleData24); + } else { + this.sampleData24 = new ModelByteBuffer(sampleFile, + chunk.getFilePointer(), chunk.available()); + } + + } + } + } + + private void readPdtaChunk(RIFFReader riff) throws IOException { + + List presets = new ArrayList(); + List presets_bagNdx = new ArrayList(); + List presets_splits_gen + = new ArrayList(); + List presets_splits_mod + = new ArrayList(); + + List instruments = new ArrayList(); + List instruments_bagNdx = new ArrayList(); + List instruments_splits_gen + = new ArrayList(); + List instruments_splits_mod + = new ArrayList(); + + while (riff.hasNextChunk()) { + RIFFReader chunk = riff.nextChunk(); + String format = chunk.getFormat(); + if (format.equals("phdr")) { + // Preset Header / Instrument + if (chunk.available() % 38 != 0) + throw new RIFFInvalidDataException(); + int count = chunk.available() / 38; + for (int i = 0; i < count; i++) { + SF2Instrument preset = new SF2Instrument(this); + preset.name = chunk.readString(20); + preset.preset = chunk.readUnsignedShort(); + preset.bank = chunk.readUnsignedShort(); + presets_bagNdx.add(chunk.readUnsignedShort()); + preset.library = chunk.readUnsignedInt(); + preset.genre = chunk.readUnsignedInt(); + preset.morphology = chunk.readUnsignedInt(); + presets.add(preset); + if (i != count - 1) + this.instruments.add(preset); + } + } else if (format.equals("pbag")) { + // Preset Zones / Instruments splits + if (chunk.available() % 4 != 0) + throw new RIFFInvalidDataException(); + int count = chunk.available() / 4; + + // Skip first record + { + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while (presets_splits_gen.size() < gencount) + presets_splits_gen.add(null); + while (presets_splits_mod.size() < modcount) + presets_splits_mod.add(null); + count--; + } + + int offset = presets_bagNdx.get(0); + // Offset should be 0 (but just case) + for (int i = 0; i < offset; i++) { + if (count == 0) + throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while (presets_splits_gen.size() < gencount) + presets_splits_gen.add(null); + while (presets_splits_mod.size() < modcount) + presets_splits_mod.add(null); + count--; + } + + for (int i = 0; i < presets_bagNdx.size() - 1; i++) { + int zone_count = presets_bagNdx.get(i + 1) + - presets_bagNdx.get(i); + SF2Instrument preset = presets.get(i); + for (int ii = 0; ii < zone_count; ii++) { + if (count == 0) + throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + SF2InstrumentRegion split = new SF2InstrumentRegion(); + preset.regions.add(split); + while (presets_splits_gen.size() < gencount) + presets_splits_gen.add(split); + while (presets_splits_mod.size() < modcount) + presets_splits_mod.add(split); + count--; + } + } + } else if (format.equals("pmod")) { + // Preset Modulators / Split Modulators + for (int i = 0; i < presets_splits_mod.size(); i++) { + SF2Modulator modulator = new SF2Modulator(); + modulator.sourceOperator = chunk.readUnsignedShort(); + modulator.destinationOperator = chunk.readUnsignedShort(); + modulator.amount = chunk.readShort(); + modulator.amountSourceOperator = chunk.readUnsignedShort(); + modulator.transportOperator = chunk.readUnsignedShort(); + SF2InstrumentRegion split = presets_splits_mod.get(i); + if (split != null) + split.modulators.add(modulator); + } + } else if (format.equals("pgen")) { + // Preset Generators / Split Generators + for (int i = 0; i < presets_splits_gen.size(); i++) { + int operator = chunk.readUnsignedShort(); + short amount = chunk.readShort(); + SF2InstrumentRegion split = presets_splits_gen.get(i); + if (split != null) + split.generators.put(operator, amount); + } + } else if (format.equals("inst")) { + // Instrument Header / Layers + if (chunk.available() % 22 != 0) + throw new RIFFInvalidDataException(); + int count = chunk.available() / 22; + for (int i = 0; i < count; i++) { + SF2Layer layer = new SF2Layer(this); + layer.name = chunk.readString(20); + instruments_bagNdx.add(chunk.readUnsignedShort()); + instruments.add(layer); + if (i != count - 1) + this.layers.add(layer); + } + } else if (format.equals("ibag")) { + // Instrument Zones / Layer splits + if (chunk.available() % 4 != 0) + throw new RIFFInvalidDataException(); + int count = chunk.available() / 4; + + // Skip first record + { + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while (instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(null); + while (instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(null); + count--; + } + + int offset = instruments_bagNdx.get(0); + // Offset should be 0 (but just case) + for (int i = 0; i < offset; i++) { + if (count == 0) + throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + while (instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(null); + while (instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(null); + count--; + } + + for (int i = 0; i < instruments_bagNdx.size() - 1; i++) { + int zone_count = instruments_bagNdx.get(i + 1) - instruments_bagNdx.get(i); + SF2Layer layer = layers.get(i); + for (int ii = 0; ii < zone_count; ii++) { + if (count == 0) + throw new RIFFInvalidDataException(); + int gencount = chunk.readUnsignedShort(); + int modcount = chunk.readUnsignedShort(); + SF2LayerRegion split = new SF2LayerRegion(); + layer.regions.add(split); + while (instruments_splits_gen.size() < gencount) + instruments_splits_gen.add(split); + while (instruments_splits_mod.size() < modcount) + instruments_splits_mod.add(split); + count--; + } + } + + } else if (format.equals("imod")) { + // Instrument Modulators / Split Modulators + for (int i = 0; i < instruments_splits_mod.size(); i++) { + SF2Modulator modulator = new SF2Modulator(); + modulator.sourceOperator = chunk.readUnsignedShort(); + modulator.destinationOperator = chunk.readUnsignedShort(); + modulator.amount = chunk.readShort(); + modulator.amountSourceOperator = chunk.readUnsignedShort(); + modulator.transportOperator = chunk.readUnsignedShort(); + SF2LayerRegion split = instruments_splits_gen.get(i); + if (split != null) + split.modulators.add(modulator); + } + } else if (format.equals("igen")) { + // Instrument Generators / Split Generators + for (int i = 0; i < instruments_splits_gen.size(); i++) { + int operator = chunk.readUnsignedShort(); + short amount = chunk.readShort(); + SF2LayerRegion split = instruments_splits_gen.get(i); + if (split != null) + split.generators.put(operator, amount); + } + } else if (format.equals("shdr")) { + // Sample Headers + if (chunk.available() % 46 != 0) + throw new RIFFInvalidDataException(); + int count = chunk.available() / 46; + for (int i = 0; i < count; i++) { + SF2Sample sample = new SF2Sample(this); + sample.name = chunk.readString(20); + long start = chunk.readUnsignedInt(); + long end = chunk.readUnsignedInt(); + sample.data = sampleData.subbuffer(start * 2, end * 2, true); + if (sampleData24 != null) + sample.data24 = sampleData24.subbuffer(start, end, true); + /* + sample.data = new ModelByteBuffer(sampleData, (int)(start*2), + (int)((end - start)*2)); + if (sampleData24 != null) + sample.data24 = new ModelByteBuffer(sampleData24, + (int)start, (int)(end - start)); + */ + sample.startLoop = chunk.readUnsignedInt() - start; + sample.endLoop = chunk.readUnsignedInt() - start; + if (sample.startLoop < 0) + sample.startLoop = -1; + if (sample.endLoop < 0) + sample.endLoop = -1; + sample.sampleRate = chunk.readUnsignedInt(); + sample.originalPitch = chunk.readUnsignedByte(); + sample.pitchCorrection = chunk.readByte(); + sample.sampleLink = chunk.readUnsignedShort(); + sample.sampleType = chunk.readUnsignedShort(); + if (i != count - 1) + this.samples.add(sample); + } + } + } + + Iterator liter = this.layers.iterator(); + while (liter.hasNext()) { + SF2Layer layer = liter.next(); + Iterator siter = layer.regions.iterator(); + SF2Region globalsplit = null; + while (siter.hasNext()) { + SF2LayerRegion split = siter.next(); + if (split.generators.get(SF2LayerRegion.GENERATOR_SAMPLEID) != null) { + int sampleid = split.generators.get( + SF2LayerRegion.GENERATOR_SAMPLEID); + split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID); + split.sample = samples.get(sampleid); + } else { + globalsplit = split; + } + } + if (globalsplit != null) { + layer.getRegions().remove(globalsplit); + SF2GlobalRegion gsplit = new SF2GlobalRegion(); + gsplit.generators = globalsplit.generators; + gsplit.modulators = globalsplit.modulators; + layer.setGlobalZone(gsplit); + } + } + + + Iterator iiter = this.instruments.iterator(); + while (iiter.hasNext()) { + SF2Instrument instrument = iiter.next(); + Iterator siter = instrument.regions.iterator(); + SF2Region globalsplit = null; + while (siter.hasNext()) { + SF2InstrumentRegion split = siter.next(); + if (split.generators.get(SF2LayerRegion.GENERATOR_INSTRUMENT) != null) { + int instrumentid = split.generators.get( + SF2InstrumentRegion.GENERATOR_INSTRUMENT); + split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT); + split.layer = layers.get(instrumentid); + } else { + globalsplit = split; + } + } + + if (globalsplit != null) { + instrument.getRegions().remove(globalsplit); + SF2GlobalRegion gsplit = new SF2GlobalRegion(); + gsplit.generators = globalsplit.generators; + gsplit.modulators = globalsplit.modulators; + instrument.setGlobalZone(gsplit); + } + } + + } + + public void save(String name) throws IOException { + writeSoundbank(new RIFFWriter(name, "sfbk")); + } + + public void save(File file) throws IOException { + writeSoundbank(new RIFFWriter(file, "sfbk")); + } + + public void save(OutputStream out) throws IOException { + writeSoundbank(new RIFFWriter(out, "sfbk")); + } + + private void writeSoundbank(RIFFWriter writer) throws IOException { + writeInfo(writer.writeList("INFO")); + writeSdtaChunk(writer.writeList("sdta")); + writePdtaChunk(writer.writeList("pdta")); + writer.close(); + } + + private void writeInfoStringChunk(RIFFWriter writer, String name, + String value) throws IOException { + if (value == null) + return; + RIFFWriter chunk = writer.writeChunk(name); + chunk.writeString(value); + int len = value.getBytes("ascii").length; + chunk.write(0); + len++; + if (len % 2 != 0) + chunk.write(0); + } + + private void writeInfo(RIFFWriter writer) throws IOException { + if (this.targetEngine == null) + this.targetEngine = "EMU8000"; + if (this.name == null) + this.name = ""; + + RIFFWriter ifil_chunk = writer.writeChunk("ifil"); + ifil_chunk.writeUnsignedShort(this.major); + ifil_chunk.writeUnsignedShort(this.minor); + writeInfoStringChunk(writer, "isng", this.targetEngine); + writeInfoStringChunk(writer, "INAM", this.name); + writeInfoStringChunk(writer, "irom", this.romName); + if (romVersionMajor != -1) { + RIFFWriter iver_chunk = writer.writeChunk("iver"); + iver_chunk.writeUnsignedShort(this.romVersionMajor); + iver_chunk.writeUnsignedShort(this.romVersionMinor); + } + writeInfoStringChunk(writer, "ICRD", this.creationDate); + writeInfoStringChunk(writer, "IENG", this.engineers); + writeInfoStringChunk(writer, "IPRD", this.product); + writeInfoStringChunk(writer, "ICOP", this.copyright); + writeInfoStringChunk(writer, "ICMT", this.comments); + writeInfoStringChunk(writer, "ISFT", this.tools); + + writer.close(); + } + + private void writeSdtaChunk(RIFFWriter writer) throws IOException { + + byte[] pad = new byte[32]; + + RIFFWriter smpl_chunk = writer.writeChunk("smpl"); + for (SF2Sample sample : samples) { + ModelByteBuffer data = sample.getDataBuffer(); + data.writeTo(smpl_chunk); + /* + smpl_chunk.write(data.array(), + data.arrayOffset(), + data.capacity()); + */ + smpl_chunk.write(pad); + smpl_chunk.write(pad); + } + if (major < 2) + return; + if (major == 2 && minor < 4) + return; + + + for (SF2Sample sample : samples) { + ModelByteBuffer data24 = sample.getData24Buffer(); + if (data24 == null) + return; + } + + RIFFWriter sm24_chunk = writer.writeChunk("sm24"); + for (SF2Sample sample : samples) { + ModelByteBuffer data = sample.getData24Buffer(); + data.writeTo(sm24_chunk); + /* + sm24_chunk.write(data.array(), + data.arrayOffset(), + data.capacity());*/ + smpl_chunk.write(pad); + } + } + + private void writeModulators(RIFFWriter writer, List modulators) + throws IOException { + for (SF2Modulator modulator : modulators) { + writer.writeUnsignedShort(modulator.sourceOperator); + writer.writeUnsignedShort(modulator.destinationOperator); + writer.writeShort(modulator.amount); + writer.writeUnsignedShort(modulator.amountSourceOperator); + writer.writeUnsignedShort(modulator.transportOperator); + } + } + + private void writeGenerators(RIFFWriter writer, Map generators) + throws IOException { + Short keyrange = (Short) generators.get(SF2Region.GENERATOR_KEYRANGE); + Short velrange = (Short) generators.get(SF2Region.GENERATOR_VELRANGE); + if (keyrange != null) { + writer.writeUnsignedShort(SF2Region.GENERATOR_KEYRANGE); + writer.writeShort(keyrange); + } + if (velrange != null) { + writer.writeUnsignedShort(SF2Region.GENERATOR_VELRANGE); + writer.writeShort(velrange); + } + for (Map.Entry generator : generators.entrySet()) { + if (generator.getKey() == SF2Region.GENERATOR_KEYRANGE) + continue; + if (generator.getKey() == SF2Region.GENERATOR_VELRANGE) + continue; + writer.writeUnsignedShort(generator.getKey()); + writer.writeShort(generator.getValue()); + } + } + + private void writePdtaChunk(RIFFWriter writer) throws IOException { + + RIFFWriter phdr_chunk = writer.writeChunk("phdr"); + int phdr_zone_count = 0; + for (SF2Instrument preset : this.instruments) { + phdr_chunk.writeString(preset.name, 20); + phdr_chunk.writeUnsignedShort(preset.preset); + phdr_chunk.writeUnsignedShort(preset.bank); + phdr_chunk.writeUnsignedShort(phdr_zone_count); + if (preset.getGlobalRegion() != null) + phdr_zone_count += 1; + phdr_zone_count += preset.getRegions().size(); + phdr_chunk.writeUnsignedInt(preset.library); + phdr_chunk.writeUnsignedInt(preset.genre); + phdr_chunk.writeUnsignedInt(preset.morphology); + } + phdr_chunk.writeString("EOP", 20); + phdr_chunk.writeUnsignedShort(0); + phdr_chunk.writeUnsignedShort(0); + phdr_chunk.writeUnsignedShort(phdr_zone_count); + phdr_chunk.writeUnsignedInt(0); + phdr_chunk.writeUnsignedInt(0); + phdr_chunk.writeUnsignedInt(0); + + + RIFFWriter pbag_chunk = writer.writeChunk("pbag"); + int pbag_gencount = 0; + int pbag_modcount = 0; + for (SF2Instrument preset : this.instruments) { + if (preset.getGlobalRegion() != null) { + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + pbag_gencount += preset.getGlobalRegion().getGenerators().size(); + pbag_modcount += preset.getGlobalRegion().getModulators().size(); + } + for (SF2InstrumentRegion region : preset.getRegions()) { + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + if (layers.indexOf(region.layer) != -1) { + // One generator is used to reference to instrument record + pbag_gencount += 1; + } + pbag_gencount += region.getGenerators().size(); + pbag_modcount += region.getModulators().size(); + + } + } + pbag_chunk.writeUnsignedShort(pbag_gencount); + pbag_chunk.writeUnsignedShort(pbag_modcount); + + RIFFWriter pmod_chunk = writer.writeChunk("pmod"); + for (SF2Instrument preset : this.instruments) { + if (preset.getGlobalRegion() != null) { + writeModulators(pmod_chunk, + preset.getGlobalRegion().getModulators()); + } + for (SF2InstrumentRegion region : preset.getRegions()) + writeModulators(pmod_chunk, region.getModulators()); + } + pmod_chunk.write(new byte[10]); + + RIFFWriter pgen_chunk = writer.writeChunk("pgen"); + for (SF2Instrument preset : this.instruments) { + if (preset.getGlobalRegion() != null) { + writeGenerators(pgen_chunk, + preset.getGlobalRegion().getGenerators()); + } + for (SF2InstrumentRegion region : preset.getRegions()) { + writeGenerators(pgen_chunk, region.getGenerators()); + int ix = (int) layers.indexOf(region.layer); + if (ix != -1) { + pgen_chunk.writeUnsignedShort(SF2Region.GENERATOR_INSTRUMENT); + pgen_chunk.writeShort((short) ix); + } + } + } + pgen_chunk.write(new byte[4]); + + RIFFWriter inst_chunk = writer.writeChunk("inst"); + int inst_zone_count = 0; + for (SF2Layer instrument : this.layers) { + inst_chunk.writeString(instrument.name, 20); + inst_chunk.writeUnsignedShort(inst_zone_count); + if (instrument.getGlobalRegion() != null) + inst_zone_count += 1; + inst_zone_count += instrument.getRegions().size(); + } + inst_chunk.writeString("EOI", 20); + inst_chunk.writeUnsignedShort(inst_zone_count); + + + RIFFWriter ibag_chunk = writer.writeChunk("ibag"); + int ibag_gencount = 0; + int ibag_modcount = 0; + for (SF2Layer instrument : this.layers) { + if (instrument.getGlobalRegion() != null) { + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + ibag_gencount + += instrument.getGlobalRegion().getGenerators().size(); + ibag_modcount + += instrument.getGlobalRegion().getModulators().size(); + } + for (SF2LayerRegion region : instrument.getRegions()) { + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + if (samples.indexOf(region.sample) != -1) { + // One generator is used to reference to instrument record + ibag_gencount += 1; + } + ibag_gencount += region.getGenerators().size(); + ibag_modcount += region.getModulators().size(); + + } + } + ibag_chunk.writeUnsignedShort(ibag_gencount); + ibag_chunk.writeUnsignedShort(ibag_modcount); + + + RIFFWriter imod_chunk = writer.writeChunk("imod"); + for (SF2Layer instrument : this.layers) { + if (instrument.getGlobalRegion() != null) { + writeModulators(imod_chunk, + instrument.getGlobalRegion().getModulators()); + } + for (SF2LayerRegion region : instrument.getRegions()) + writeModulators(imod_chunk, region.getModulators()); + } + imod_chunk.write(new byte[10]); + + RIFFWriter igen_chunk = writer.writeChunk("igen"); + for (SF2Layer instrument : this.layers) { + if (instrument.getGlobalRegion() != null) { + writeGenerators(igen_chunk, + instrument.getGlobalRegion().getGenerators()); + } + for (SF2LayerRegion region : instrument.getRegions()) { + writeGenerators(igen_chunk, region.getGenerators()); + int ix = samples.indexOf(region.sample); + if (ix != -1) { + igen_chunk.writeUnsignedShort(SF2Region.GENERATOR_SAMPLEID); + igen_chunk.writeShort((short) ix); + } + } + } + igen_chunk.write(new byte[4]); + + + RIFFWriter shdr_chunk = writer.writeChunk("shdr"); + long sample_pos = 0; + for (SF2Sample sample : samples) { + shdr_chunk.writeString(sample.name, 20); + long start = sample_pos; + sample_pos += sample.data.capacity() / 2; + long end = sample_pos; + long startLoop = sample.startLoop + start; + long endLoop = sample.endLoop + start; + if (startLoop < start) + startLoop = start; + if (endLoop > end) + endLoop = end; + shdr_chunk.writeUnsignedInt(start); + shdr_chunk.writeUnsignedInt(end); + shdr_chunk.writeUnsignedInt(startLoop); + shdr_chunk.writeUnsignedInt(endLoop); + shdr_chunk.writeUnsignedInt(sample.sampleRate); + shdr_chunk.writeUnsignedByte(sample.originalPitch); + shdr_chunk.writeByte(sample.pitchCorrection); + shdr_chunk.writeUnsignedShort(sample.sampleLink); + shdr_chunk.writeUnsignedShort(sample.sampleType); + sample_pos += 32; + } + shdr_chunk.writeString("EOS", 20); + shdr_chunk.write(new byte[26]); + + } + + public String getName() { + return name; + } + + public String getVersion() { + return major + "." + minor; + } + + public String getVendor() { + return engineers; + } + + public String getDescription() { + return comments; + } + + public void setName(String s) { + name = s; + } + + public void setVendor(String s) { + engineers = s; + } + + public void setDescription(String s) { + comments = s; + } + + public SoundbankResource[] getResources() { + SoundbankResource[] resources + = new SoundbankResource[layers.size() + samples.size()]; + int j = 0; + for (int i = 0; i < layers.size(); i++) + resources[j++] = layers.get(i); + for (int i = 0; i < samples.size(); i++) + resources[j++] = samples.get(i); + return resources; + } + + public SF2Instrument[] getInstruments() { + SF2Instrument[] inslist_array + = instruments.toArray(new SF2Instrument[instruments.size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public SF2Layer[] getLayers() { + return layers.toArray(new SF2Layer[layers.size()]); + } + + public SF2Sample[] getSamples() { + return samples.toArray(new SF2Sample[samples.size()]); + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch)patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch) patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public String getCreationDate() { + return creationDate; + } + + public void setCreationDate(String creationDate) { + this.creationDate = creationDate; + } + + public String getProduct() { + return product; + } + + public void setProduct(String product) { + this.product = product; + } + + public String getRomName() { + return romName; + } + + public void setRomName(String romName) { + this.romName = romName; + } + + public int getRomVersionMajor() { + return romVersionMajor; + } + + public void setRomVersionMajor(int romVersionMajor) { + this.romVersionMajor = romVersionMajor; + } + + public int getRomVersionMinor() { + return romVersionMinor; + } + + public void setRomVersionMinor(int romVersionMinor) { + this.romVersionMinor = romVersionMinor; + } + + public String getTargetEngine() { + return targetEngine; + } + + public void setTargetEngine(String targetEngine) { + this.targetEngine = targetEngine; + } + + public String getTools() { + return tools; + } + + public void setTools(String tools) { + this.tools = tools; + } + + public void addResource(SoundbankResource resource) { + if (resource instanceof SF2Instrument) + instruments.add((SF2Instrument)resource); + if (resource instanceof SF2Layer) + layers.add((SF2Layer)resource); + if (resource instanceof SF2Sample) + samples.add((SF2Sample)resource); + } + + public void removeResource(SoundbankResource resource) { + if (resource instanceof SF2Instrument) + instruments.remove((SF2Instrument)resource); + if (resource instanceof SF2Layer) + layers.remove((SF2Layer)resource); + if (resource instanceof SF2Sample) + samples.remove((SF2Sample)resource); + } + + public void addInstrument(SF2Instrument resource) { + instruments.add(resource); + } + + public void removeInstrument(SF2Instrument resource) { + instruments.remove(resource); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java b/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java new file mode 100644 index 00000000000..942752df21e --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SF2SoundbankReader.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.Soundbank; +import javax.sound.midi.spi.SoundbankReader; + +/** + * This class is used to connect the SF2SoundBank class + * to the SoundbankReader SPI interface. + * + * @author Karl Helgason + */ +public class SF2SoundbankReader extends SoundbankReader { + + public Soundbank getSoundbank(URL url) + throws InvalidMidiDataException, IOException { + try { + return new SF2Soundbank(url); + } catch (RIFFInvalidFormatException e) { + return null; + } catch(IOException ioe) { + return null; + } + } + + public Soundbank getSoundbank(InputStream stream) + throws InvalidMidiDataException, IOException { + try { + stream.mark(512); + return new SF2Soundbank(stream); + } catch (RIFFInvalidFormatException e) { + stream.reset(); + return null; + } + } + + public Soundbank getSoundbank(File file) + throws InvalidMidiDataException, IOException { + try { + return new SF2Soundbank(file); + } catch (RIFFInvalidFormatException e) { + return null; + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java b/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java new file mode 100644 index 00000000000..92c60810599 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SimpleInstrument.java @@ -0,0 +1,196 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.List; +import javax.sound.midi.Patch; + +/** + * A simple instrument that is made of other ModelInstrument, ModelPerformer + * objects. + * + * @author Karl Helgason + */ +public class SimpleInstrument extends ModelInstrument { + + private static class SimpleInstrumentPart { + ModelPerformer[] performers; + int keyFrom; + int keyTo; + int velFrom; + int velTo; + int exclusiveClass; + } + protected int preset = 0; + protected int bank = 0; + protected boolean percussion = false; + protected String name = ""; + protected List parts + = new ArrayList(); + + public SimpleInstrument() { + super(null, null, null, null); + } + + public void clear() { + parts.clear(); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo, + int velFrom, int velTo, int exclusiveClass) { + SimpleInstrumentPart part = new SimpleInstrumentPart(); + part.performers = performers; + part.keyFrom = keyFrom; + part.keyTo = keyTo; + part.velFrom = velFrom; + part.velTo = velTo; + part.exclusiveClass = exclusiveClass; + parts.add(part); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo, + int velFrom, int velTo) { + add(performers, keyFrom, keyTo, velFrom, velTo, -1); + } + + public void add(ModelPerformer[] performers, int keyFrom, int keyTo) { + add(performers, keyFrom, keyTo, 0, 127, -1); + } + + public void add(ModelPerformer[] performers) { + add(performers, 0, 127, 0, 127, -1); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo, + int velFrom, int velTo, int exclusiveClass) { + add(new ModelPerformer[]{performer}, keyFrom, keyTo, velFrom, velTo, + exclusiveClass); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo, + int velFrom, int velTo) { + add(new ModelPerformer[]{performer}, keyFrom, keyTo, velFrom, velTo); + } + + public void add(ModelPerformer performer, int keyFrom, int keyTo) { + add(new ModelPerformer[]{performer}, keyFrom, keyTo); + } + + public void add(ModelPerformer performer) { + add(new ModelPerformer[]{performer}); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom, + int velTo, int exclusiveClass) { + add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo, exclusiveClass); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo, int velFrom, + int velTo) { + add(ins.getPerformers(), keyFrom, keyTo, velFrom, velTo); + } + + public void add(ModelInstrument ins, int keyFrom, int keyTo) { + add(ins.getPerformers(), keyFrom, keyTo); + } + + public void add(ModelInstrument ins) { + add(ins.getPerformers()); + } + + public ModelPerformer[] getPerformers() { + + int percount = 0; + for (SimpleInstrumentPart part : parts) + if (part.performers != null) + percount += part.performers.length; + + ModelPerformer[] performers = new ModelPerformer[percount]; + int px = 0; + for (SimpleInstrumentPart part : parts) { + if (part.performers != null) { + for (ModelPerformer mperfm : part.performers) { + ModelPerformer performer = new ModelPerformer(); + performer.setName(getName()); + performers[px++] = performer; + + performer.setDefaultConnectionsEnabled( + mperfm.isDefaultConnectionsEnabled()); + performer.setKeyFrom(mperfm.getKeyFrom()); + performer.setKeyTo(mperfm.getKeyTo()); + performer.setVelFrom(mperfm.getVelFrom()); + performer.setVelTo(mperfm.getVelTo()); + performer.setExclusiveClass(mperfm.getExclusiveClass()); + performer.setSelfNonExclusive(mperfm.isSelfNonExclusive()); + performer.setReleaseTriggered(mperfm.isReleaseTriggered()); + if (part.exclusiveClass != -1) + performer.setExclusiveClass(part.exclusiveClass); + if (part.keyFrom > performer.getKeyFrom()) + performer.setKeyFrom(part.keyFrom); + if (part.keyTo < performer.getKeyTo()) + performer.setKeyTo(part.keyTo); + if (part.velFrom > performer.getVelFrom()) + performer.setVelFrom(part.velFrom); + if (part.velTo < performer.getVelTo()) + performer.setVelTo(part.velTo); + performer.getOscillators().addAll(mperfm.getOscillators()); + performer.getConnectionBlocks().addAll( + mperfm.getConnectionBlocks()); + } + } + } + + return performers; + } + + public Object getData() { + return null; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public ModelPatch getPatch() { + return new ModelPatch(bank, preset, percussion); + } + + public void setPatch(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch)patch).isPercussion()) { + percussion = true; + bank = patch.getBank(); + preset = patch.getProgram(); + } else { + percussion = false; + bank = patch.getBank(); + preset = patch.getProgram(); + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java b/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java new file mode 100644 index 00000000000..c5dea6e73da --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SimpleSoundbank.java @@ -0,0 +1,145 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; + +/** + * A simple soundbank that contains instruments and soundbankresources. + * + * @author Karl Helgason + */ +public class SimpleSoundbank implements Soundbank { + + String name = ""; + String version = ""; + String vendor = ""; + String description = ""; + List resources = new ArrayList(); + List instruments = new ArrayList(); + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + public String getVendor() { + return vendor; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setName(String name) { + this.name = name; + } + + public void setVendor(String vendor) { + this.vendor = vendor; + } + + public void setVersion(String version) { + this.version = version; + } + + public SoundbankResource[] getResources() { + return resources.toArray(new SoundbankResource[resources.size()]); + } + + public Instrument[] getInstruments() { + Instrument[] inslist_array + = instruments.toArray(new Instrument[resources.size()]); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + + public Instrument getInstrument(Patch patch) { + int program = patch.getProgram(); + int bank = patch.getBank(); + boolean percussion = false; + if (patch instanceof ModelPatch) + percussion = ((ModelPatch)patch).isPercussion(); + for (Instrument instrument : instruments) { + Patch patch2 = instrument.getPatch(); + int program2 = patch2.getProgram(); + int bank2 = patch2.getBank(); + if (program == program2 && bank == bank2) { + boolean percussion2 = false; + if (patch2 instanceof ModelPatch) + percussion2 = ((ModelPatch)patch2).isPercussion(); + if (percussion == percussion2) + return instrument; + } + } + return null; + } + + public void addResource(SoundbankResource resource) { + if (resource instanceof Instrument) + instruments.add((Instrument) resource); + else + resources.add(resource); + } + + public void removeResource(SoundbankResource resource) { + if (resource instanceof Instrument) + instruments.remove((Instrument) resource); + else + resources.remove(resource); + } + + public void addInstrument(Instrument resource) { + instruments.add(resource); + } + + public void removeInstrument(Instrument resource) { + instruments.remove(resource); + } + + public void addAllInstruments(Soundbank soundbank) { + for (Instrument ins : soundbank.getInstruments()) + addInstrument(ins); + } + + public void removeAllInstruments(Soundbank soundbank) { + for (Instrument ins : soundbank.getInstruments()) + removeInstrument(ins); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java new file mode 100644 index 00000000000..4fcb26c4543 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftAbstractResampler.java @@ -0,0 +1,390 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.util.Arrays; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.VoiceStatus; + +/** + * Abstract resampler class. + * + * @author Karl Helgason + */ +public abstract class SoftAbstractResampler implements SoftResampler { + + private class ModelAbstractResamplerStream implements SoftResamplerStreamer { + + AudioFloatInputStream stream; + boolean stream_eof = false; + int loopmode; + boolean loopdirection = true; // true = forward + float loopstart; + float looplen; + float target_pitch; + float[] current_pitch = new float[1]; + boolean started; + boolean eof; + int sector_pos = 0; + int sector_size = 400; + int sector_loopstart = -1; + boolean markset = false; + int marklimit = 0; + int streampos = 0; + int nrofchannels = 2; + boolean noteOff_flag = false; + float[][] ibuffer; + boolean ibuffer_order = true; + float[] sbuffer; + int pad; + int pad2; + float[] ix = new float[1]; + int[] ox = new int[1]; + float samplerateconv = 1; + float pitchcorrection = 0; + + public ModelAbstractResamplerStream() { + pad = getPadding(); + pad2 = getPadding() * 2; + ibuffer = new float[2][sector_size + pad2]; + ibuffer_order = true; + } + + public void noteOn(MidiChannel channel, VoiceStatus voice, + int noteNumber, int velocity) { + } + + public void noteOff(int velocity) { + noteOff_flag = true; + } + + public void open(ModelWavetable osc, float outputsamplerate) + throws IOException { + + eof = false; + nrofchannels = osc.getChannels(); + if (ibuffer.length < nrofchannels) { + ibuffer = new float[nrofchannels][sector_size + pad2]; + } + + stream = osc.openStream(); + streampos = 0; + stream_eof = false; + pitchcorrection = osc.getPitchcorrection(); + samplerateconv + = stream.getFormat().getSampleRate() / outputsamplerate; + looplen = osc.getLoopLength(); + loopstart = osc.getLoopStart(); + sector_loopstart = (int) (loopstart / sector_size); + sector_loopstart = sector_loopstart - 1; + + sector_pos = 0; + + if (sector_loopstart < 0) + sector_loopstart = 0; + started = false; + loopmode = osc.getLoopType(); + + if (loopmode != 0) { + markset = false; + marklimit = nrofchannels * (int) (looplen + pad2 + 1); + } else + markset = true; + // loopmode = 0; + + target_pitch = samplerateconv; + current_pitch[0] = samplerateconv; + + ibuffer_order = true; + loopdirection = true; + noteOff_flag = false; + + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0); + ix[0] = pad; + eof = false; + + ix[0] = sector_size + pad; + sector_pos = -1; + streampos = -sector_size; + + nextBuffer(); + } + + public void setPitch(float pitch) { + /* + this.pitch = (float) Math.pow(2f, + (pitchcorrection + pitch) / 1200.0f) + * samplerateconv; + */ + this.target_pitch = (float)Math.exp( + (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0)) + * samplerateconv; + + if (!started) + current_pitch[0] = this.target_pitch; + } + + public void nextBuffer() throws IOException { + if (ix[0] < pad) { + if (markset) { + // reset to target sector + stream.reset(); + ix[0] += streampos - (sector_loopstart * sector_size); + sector_pos = sector_loopstart; + streampos = sector_pos * sector_size; + + // and go one sector backward + ix[0] += sector_size; + sector_pos -= 1; + streampos -= sector_size; + stream_eof = false; + } + } + + if (ix[0] >= sector_size + pad) { + if (stream_eof) { + eof = true; + return; + } + } + + if (ix[0] >= sector_size * 4 + pad) { + int skips = (int)((ix[0] - sector_size * 4 + pad) / sector_size); + ix[0] -= sector_size * skips; + sector_pos += skips; + streampos += sector_size * skips; + stream.skip(sector_size * skips); + } + + while (ix[0] >= sector_size + pad) { + if (!markset) { + if (sector_pos + 1 == sector_loopstart) { + stream.mark(marklimit); + markset = true; + } + } + ix[0] -= sector_size; + sector_pos++; + streampos += sector_size; + + for (int c = 0; c < nrofchannels; c++) { + float[] cbuffer = ibuffer[c]; + for (int i = 0; i < pad2; i++) + cbuffer[i] = cbuffer[i + sector_size]; + } + + int ret; + if (nrofchannels == 1) + ret = stream.read(ibuffer[0], pad2, sector_size); + else { + int slen = sector_size * nrofchannels; + if (sbuffer == null || sbuffer.length < slen) + sbuffer = new float[slen]; + int sret = stream.read(sbuffer, 0, slen); + if (sret == -1) + ret = -1; + else { + ret = sret / nrofchannels; + for (int i = 0; i < nrofchannels; i++) { + float[] buff = ibuffer[i]; + int ix = i; + int ix_step = nrofchannels; + int ox = pad2; + for (int j = 0; j < ret; j++, ix += ix_step, ox++) + buff[ox] = sbuffer[ix]; + } + } + + } + + if (ret == -1) { + ret = 0; + stream_eof = true; + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], pad2, pad2 + sector_size, 0f); + return; + } + if (ret != sector_size) { + for (int i = 0; i < nrofchannels; i++) + Arrays.fill(ibuffer[i], pad2 + ret, pad2 + sector_size, 0f); + } + + ibuffer_order = true; + + } + + } + + public void reverseBuffers() { + ibuffer_order = !ibuffer_order; + for (int c = 0; c < nrofchannels; c++) { + float[] cbuff = ibuffer[c]; + int len = cbuff.length - 1; + int len2 = cbuff.length / 2; + for (int i = 0; i < len2; i++) { + float x = cbuff[i]; + cbuff[i] = cbuff[len - i]; + cbuff[len - i] = x; + } + } + } + + public int read(float[][] buffer, int offset, int len) + throws IOException { + + if (eof) + return -1; + + if (noteOff_flag) + if ((loopmode & 2) != 0) + if (loopdirection) + loopmode = 0; + + + float pitchstep = (target_pitch - current_pitch[0]) / len; + float[] current_pitch = this.current_pitch; + started = true; + + int[] ox = this.ox; + ox[0] = offset; + int ox_end = len + offset; + + float ixend = sector_size + pad; + if (!loopdirection) + ixend = pad; + while (ox[0] != ox_end) { + nextBuffer(); + if (!loopdirection) { + // If we are in backward playing part of pingpong + // or reverse loop + + if (streampos < (loopstart + pad)) { + ixend = loopstart - streampos + pad2; + if (ix[0] <= ixend) { + if ((loopmode & 4) != 0) { + // Ping pong loop, change loopdirection + loopdirection = true; + ixend = sector_size + pad; + continue; + } + + ix[0] += looplen; + ixend = pad; + continue; + } + } + + if (ibuffer_order != loopdirection) + reverseBuffers(); + + ix[0] = (sector_size + pad2) - ix[0]; + ixend = (sector_size + pad2) - ixend; + ixend++; + + float bak_ix = ix[0]; + int bak_ox = ox[0]; + float bak_pitch = current_pitch[0]; + for (int i = 0; i < nrofchannels; i++) { + if (buffer[i] != null) { + ix[0] = bak_ix; + ox[0] = bak_ox; + current_pitch[0] = bak_pitch; + interpolate(ibuffer[i], ix, ixend, current_pitch, + pitchstep, buffer[i], ox, ox_end); + } + } + + ix[0] = (sector_size + pad2) - ix[0]; + ixend--; + ixend = (sector_size + pad2) - ixend; + + if (eof) { + current_pitch[0] = this.target_pitch; + return ox[0] - offset; + } + + continue; + } + if (loopmode != 0) { + if (streampos + sector_size > (looplen + loopstart + pad)) { + ixend = loopstart + looplen - streampos + pad2; + if (ix[0] >= ixend) { + if ((loopmode & 4) != 0 || (loopmode & 8) != 0) { + // Ping pong or revese loop, change loopdirection + loopdirection = false; + ixend = pad; + continue; + } + ixend = sector_size + pad; + ix[0] -= looplen; + continue; + } + } + } + + if (ibuffer_order != loopdirection) + reverseBuffers(); + + float bak_ix = ix[0]; + int bak_ox = ox[0]; + float bak_pitch = current_pitch[0]; + for (int i = 0; i < nrofchannels; i++) { + if (buffer[i] != null) { + ix[0] = bak_ix; + ox[0] = bak_ox; + current_pitch[0] = bak_pitch; + interpolate(ibuffer[i], ix, ixend, current_pitch, + pitchstep, buffer[i], ox, ox_end); + } + } + + if (eof) { + current_pitch[0] = this.target_pitch; + return ox[0] - offset; + } + } + + current_pitch[0] = this.target_pitch; + return len; + } + + public void close() throws IOException { + stream.close(); + } + } + + public abstract int getPadding(); + + public abstract void interpolate(float[] in, float[] in_offset, + float in_end, float[] pitch, float pitchstep, float[] out, + int[] out_offset, int out_end); + + public SoftResamplerStreamer openStreamer() { + return new ModelAbstractResamplerStream(); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java b/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java new file mode 100644 index 00000000000..ccc94899f61 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftAudioBuffer.java @@ -0,0 +1,104 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; + +/** + * This class is used to store audio buffer. + * + * @author Karl Helgason + */ +public class SoftAudioBuffer { + + private int size; + private float[] buffer; + private boolean empty = true; + private AudioFormat format; + private AudioFloatConverter converter; + private byte[] converter_buffer; + + public SoftAudioBuffer(int size, AudioFormat format) { + this.size = size; + this.format = format; + converter = AudioFloatConverter.getConverter(format); + } + + public AudioFormat getFormat() { + return format; + } + + public int getSize() { + return size; + } + + public void clear() { + if (!empty) { + Arrays.fill(buffer, 0); + empty = true; + } + } + + public boolean isSilent() { + return empty; + } + + public float[] array() { + empty = false; + if (buffer == null) + buffer = new float[size]; + return buffer; + } + + public void get(byte[] buffer, int channel) { + + int framesize_pc = (format.getFrameSize() / format.getChannels()); + int c_len = size * framesize_pc; + if (converter_buffer == null || converter_buffer.length < c_len) + converter_buffer = new byte[c_len]; + + if (format.getChannels() == 1) { + converter.toByteArray(array(), size, buffer); + } else { + converter.toByteArray(array(), size, converter_buffer); + if (channel >= format.getChannels()) + return; + int z_stepover = format.getChannels() * framesize_pc; + int k_stepover = framesize_pc; + for (int j = 0; j < framesize_pc; j++) { + int k = j; + int z = channel * framesize_pc + j; + for (int i = 0; i < size; i++) { + buffer[z] = converter_buffer[k]; + z += z_stepover; + k += k_stepover; + } + } + } + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java b/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java new file mode 100644 index 00000000000..1e8a53f721b --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftAudioProcessor.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Audio processor interface. + * + * @author Karl Helgason + */ +public interface SoftAudioProcessor { + + public void globalParameterControlChange(int[] slothpath, long param, + long value); + + public void init(float samplerate, float controlrate); + + public void setInput(int pin, SoftAudioBuffer input); + + public void setOutput(int pin, SoftAudioBuffer output); + + public void setMixMode(boolean mix); + + public void processAudio(); + + public void processControlLogic(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java b/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java new file mode 100644 index 00000000000..d19ff412bd8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftAudioPusher.java @@ -0,0 +1,91 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.SourceDataLine; + +/** + * This is a processor object that writes into SourceDataLine + * + * @author Karl Helgason + */ +public class SoftAudioPusher implements Runnable { + + private volatile boolean active = false; + private SourceDataLine sourceDataLine = null; + private Thread audiothread; + private AudioInputStream ais; + private byte[] buffer; + + public SoftAudioPusher(SourceDataLine sourceDataLine, AudioInputStream ais, + int workbuffersizer) { + this.ais = ais; + this.buffer = new byte[workbuffersizer]; + this.sourceDataLine = sourceDataLine; + } + + public synchronized void start() { + if (active) + return; + active = true; + audiothread = new Thread(this); + audiothread.setPriority(Thread.MAX_PRIORITY); + audiothread.start(); + } + + public synchronized void stop() { + if (!active) + return; + active = false; + try { + audiothread.join(); + } catch (InterruptedException e) { + //e.printStackTrace(); + } + } + + public void run() { + byte[] buffer = SoftAudioPusher.this.buffer; + AudioInputStream ais = SoftAudioPusher.this.ais; + SourceDataLine sourceDataLine = SoftAudioPusher.this.sourceDataLine; + + try { + while (active) { + // Read from audio source + int count = ais.read(buffer); + if(count < 0) break; + // Write byte buffer to source output + sourceDataLine.write(buffer, 0, count); + } + } catch (IOException e) { + active = false; + //e.printStackTrace(); + } + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java b/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java new file mode 100644 index 00000000000..8bb5f2ef66a --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftChannel.java @@ -0,0 +1,1548 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.Patch; + +/** + * Software Synthesizer MIDI channel class. + * + * @author Karl Helgason + */ +public class SoftChannel implements MidiChannel, ModelDirectedPlayer { + + private static boolean[] dontResetControls = new boolean[128]; + static { + for (int i = 0; i < dontResetControls.length; i++) + dontResetControls[i] = false; + + dontResetControls[0] = true; // Bank Select (MSB) + dontResetControls[32] = true; // Bank Select (LSB) + dontResetControls[7] = true; // Channel Volume (MSB) + dontResetControls[8] = true; // Balance (MSB) + dontResetControls[10] = true; // Pan (MSB) + dontResetControls[11] = true; // Expression (MSB) + dontResetControls[91] = true; // Effects 1 Depth (default: Reverb Send) + dontResetControls[92] = true; // Effects 2 Depth (default: Tremolo Depth) + dontResetControls[93] = true; // Effects 3 Depth (default: Chorus Send) + dontResetControls[94] = true; // Effects 4 Depth (default: Celeste [Detune] Depth) + dontResetControls[95] = true; // Effects 5 Depth (default: Phaser Depth) + dontResetControls[70] = true; // Sound Controller 1 (default: Sound Variation) + dontResetControls[71] = true; // Sound Controller 2 (default: Timbre / Harmonic Quality) + dontResetControls[72] = true; // Sound Controller 3 (default: Release Time) + dontResetControls[73] = true; // Sound Controller 4 (default: Attack Time) + dontResetControls[74] = true; // Sound Controller 5 (default: Brightness) + dontResetControls[75] = true; // Sound Controller 6 (GM2 default: Decay Time) + dontResetControls[76] = true; // Sound Controller 7 (GM2 default: Vibrato Rate) + dontResetControls[77] = true; // Sound Controller 8 (GM2 default: Vibrato Depth) + dontResetControls[78] = true; // Sound Controller 9 (GM2 default: Vibrato Delay) + dontResetControls[79] = true; // Sound Controller 10 (GM2 default: Undefined) + dontResetControls[120] = true; // All Sound Off + dontResetControls[121] = true; // Reset All Controllers + dontResetControls[122] = true; // Local Control On/Off + dontResetControls[123] = true; // All Notes Off + dontResetControls[124] = true; // Omni Mode Off + dontResetControls[125] = true; // Omni Mode On + dontResetControls[126] = true; // Poly Mode Off + dontResetControls[127] = true; // Poly Mode On + + dontResetControls[6] = true; // Data Entry (MSB) + dontResetControls[38] = true; // Data Entry (LSB) + dontResetControls[96] = true; // Data Increment + dontResetControls[97] = true; // Data Decrement + dontResetControls[98] = true; // Non-Registered Parameter Number (LSB) + dontResetControls[99] = true; // Non-Registered Parameter Number(MSB) + dontResetControls[100] = true; // RPN = Null + dontResetControls[101] = true; // RPN = Null + + } + + private static final int RPN_NULL_VALUE = (127 << 7) + 127; + private int rpn_control = RPN_NULL_VALUE; + private int nrpn_control = RPN_NULL_VALUE; + protected double portamento_time = 1; // keyschanges per control buffer time + protected int[] portamento_lastnote = new int[128]; + protected int portamento_lastnote_ix = 0; + private int portamento_control_note = -1; + private boolean portamento = false; + private boolean mono = false; + private boolean mute = false; + private boolean solo = false; + private boolean solomute = false; + private Object control_mutex; + private int channel; + private SoftVoice[] voices; + private int bank; + private int program; + private SoftSynthesizer synthesizer; + private SoftMainMixer mainmixer; + private int[] polypressure = new int[128]; + private int channelpressure = 0; + private int[] controller = new int[128]; + private int pitchbend; + private double[] co_midi_pitch = new double[1]; + private double[] co_midi_channel_pressure = new double[1]; + protected SoftTuning tuning = new SoftTuning(); + protected int tuning_bank = 0; + protected int tuning_program = 0; + protected SoftInstrument current_instrument = null; + protected ModelChannelMixer current_mixer = null; + private ModelDirector current_director = null; + + // Controller Destination Settings + protected int cds_control_number = -1; + protected ModelConnectionBlock[] cds_control_connections = null; + protected ModelConnectionBlock[] cds_channelpressure_connections = null; + protected ModelConnectionBlock[] cds_polypressure_connections = null; + protected boolean sustain = false; + protected boolean[][] keybasedcontroller_active = null; + protected double[][] keybasedcontroller_value = null; + + private class MidiControlObject implements SoftControl { + double[] pitch = co_midi_pitch; + double[] channel_pressure = co_midi_channel_pressure; + double[] poly_pressure = new double[1]; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("pitch")) + return pitch; + if (name.equals("channel_pressure")) + return channel_pressure; + if (name.equals("poly_pressure")) + return poly_pressure; + return null; + } + } + + private SoftControl[] co_midi = new SoftControl[128]; + { + for (int i = 0; i < co_midi.length; i++) { + co_midi[i] = new MidiControlObject(); + } + } + + private double[][] co_midi_cc_cc = new double[128][1]; + private SoftControl co_midi_cc = new SoftControl() { + double[][] cc = co_midi_cc_cc; + public double[] get(int instance, String name) { + if (name == null) + return null; + return cc[Integer.parseInt(name)]; + } + }; + Map co_midi_rpn_rpn_i = new HashMap(); + Map co_midi_rpn_rpn = new HashMap(); + private SoftControl co_midi_rpn = new SoftControl() { + Map rpn = co_midi_rpn_rpn; + public double[] get(int instance, String name) { + if (name == null) + return null; + int iname = Integer.parseInt(name); + double[] v = rpn.get(iname); + if (v == null) { + v = new double[1]; + rpn.put(iname, v); + } + return v; + } + }; + Map co_midi_nrpn_nrpn_i = new HashMap(); + Map co_midi_nrpn_nrpn = new HashMap(); + private SoftControl co_midi_nrpn = new SoftControl() { + Map nrpn = co_midi_nrpn_nrpn; + public double[] get(int instance, String name) { + if (name == null) + return null; + int iname = Integer.parseInt(name); + double[] v = nrpn.get(iname); + if (v == null) { + v = new double[1]; + nrpn.put(iname, v); + } + return v; + } + }; + + private static int restrict7Bit(int value) + { + if(value < 0) return 0; + if(value > 127) return 127; + return value; + } + + private static int restrict14Bit(int value) + { + if(value < 0) return 0; + if(value > 16256) return 16256; + return value; + } + + public SoftChannel(SoftSynthesizer synth, int channel) { + this.channel = channel; + this.voices = synth.getVoices(); + this.synthesizer = synth; + this.mainmixer = synth.getMainMixer(); + control_mutex = synth.control_mutex; + resetAllControllers(true); + } + + private int findFreeVoice(int x) { + for (int i = x; i < voices.length; i++) + if (!voices[i].active) + return i; + + // No free voice was found, we must steal one + + int vmode = synthesizer.getVoiceAllocationMode(); + if (vmode == 1) { + // DLS Static Voice Allocation + + // * priority ( 10, 1-9, 11-16) + // Search for channel to steal from + int steal_channel = channel; + for (int j = 0; j < voices.length; j++) { + if (voices[j].stealer_channel == null) { + if (steal_channel == 9) { + steal_channel = voices[j].channel; + } else { + if (voices[j].channel != 9) { + if (voices[j].channel > steal_channel) + steal_channel = voices[j].channel; + } + } + } + } + + int voiceNo = -1; + + SoftVoice v = null; + // Search for oldest voice in off state on steal_channel + for (int j = 0; j < voices.length; j++) { + if (voices[j].channel == steal_channel) { + if (voices[j].stealer_channel == null && !voices[j].on) { + if (v == null) { + v = voices[j]; + voiceNo = j; + } + if (voices[j].voiceID < v.voiceID) { + v = voices[j]; + voiceNo = j; + } + } + } + } + // Search for oldest voice in on state on steal_channel + if (voiceNo == -1) { + for (int j = 0; j < voices.length; j++) { + if (voices[j].channel == steal_channel) { + if (voices[j].stealer_channel == null) { + if (v == null) { + v = voices[j]; + voiceNo = j; + } + if (voices[j].voiceID < v.voiceID) { + v = voices[j]; + voiceNo = j; + } + } + } + } + } + + return voiceNo; + + } else { + // Default Voice Allocation + // * Find voice that is on + // and Find voice which has lowest voiceID ( oldest voice) + // * Or find voice that is off + // and Find voice which has lowest voiceID ( oldest voice) + + int voiceNo = -1; + + SoftVoice v = null; + // Search for oldest voice in off state + for (int j = 0; j < voices.length; j++) { + if (voices[j].stealer_channel == null && !voices[j].on) { + if (v == null) { + v = voices[j]; + voiceNo = j; + } + if (voices[j].voiceID < v.voiceID) { + v = voices[j]; + voiceNo = j; + } + } + } + // Search for oldest voice in on state + if (voiceNo == -1) { + + for (int j = 0; j < voices.length; j++) { + if (voices[j].stealer_channel == null) { + if (v == null) { + v = voices[j]; + voiceNo = j; + } + if (voices[j].voiceID < v.voiceID) { + v = voices[j]; + voiceNo = j; + } + } + } + } + + return voiceNo; + } + + } + + protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID, + int noteNumber, int velocity, ModelConnectionBlock[] connectionBlocks, + ModelChannelMixer channelmixer, boolean releaseTriggered) { + if (voice.active) { + // Voice is active , we must steal the voice + voice.stealer_channel = this; + voice.stealer_performer = p; + voice.stealer_voiceID = voiceID; + voice.stealer_noteNumber = noteNumber; + voice.stealer_velocity = velocity; + voice.stealer_extendedConnectionBlocks = connectionBlocks; + voice.stealer_channelmixer = channelmixer; + voice.stealer_releaseTriggered = releaseTriggered; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].voiceID == voice.voiceID) + voices[i].soundOff(); + return; + } + + voice.extendedConnectionBlocks = connectionBlocks; + voice.channelmixer = channelmixer; + voice.releaseTriggered = releaseTriggered; + voice.voiceID = voiceID; + voice.tuning = tuning; + voice.exclusiveClass = p.exclusiveClass; + voice.softchannel = this; + voice.channel = channel; + voice.bank = bank; + voice.program = program; + voice.instrument = current_instrument; + voice.performer = p; + voice.objects.clear(); + voice.objects.put("midi", co_midi[noteNumber]); + voice.objects.put("midi_cc", co_midi_cc); + voice.objects.put("midi_rpn", co_midi_rpn); + voice.objects.put("midi_nrpn", co_midi_nrpn); + voice.noteOn(noteNumber, velocity); + voice.setMute(mute); + voice.setSoloMute(solomute); + if (releaseTriggered) + return; + if (portamento_control_note != -1) { + voice.co_noteon_keynumber[0] + = (tuning.getTuning(portamento_control_note) / 100.0) + * (1f / 128f); + voice.portamento = true; + portamento_control_note = -1; + } else if (portamento) { + if (mono) { + if (portamento_lastnote[0] != -1) { + voice.co_noteon_keynumber[0] + = (tuning.getTuning(portamento_lastnote[0]) / 100.0) + * (1f / 128f); + voice.portamento = true; + portamento_control_note = -1; + } + portamento_lastnote[0] = noteNumber; + } else { + if (portamento_lastnote_ix != 0) { + portamento_lastnote_ix--; + voice.co_noteon_keynumber[0] + = (tuning.getTuning( + portamento_lastnote[portamento_lastnote_ix]) + / 100.0) + * (1f / 128f); + voice.portamento = true; + } + } + } + } + + public void noteOn(int noteNumber, int velocity) { + noteNumber = restrict7Bit(noteNumber); + velocity = restrict7Bit(velocity); + noteOn_internal(noteNumber, velocity); + if (current_mixer != null) + current_mixer.noteOn(noteNumber, velocity); + } + + private void noteOn_internal(int noteNumber, int velocity) { + + if (velocity == 0) { + noteOff_internal(noteNumber, 64); + return; + } + + synchronized (control_mutex) { + if (sustain) { + sustain = false; + for (int i = 0; i < voices.length; i++) { + if ((voices[i].sustain || voices[i].on) + && voices[i].channel == channel && voices[i].active + && voices[i].note == noteNumber) { + voices[i].sustain = false; + voices[i].on = true; + voices[i].noteOff(0); + } + } + sustain = true; + } + + mainmixer.activity(); + + if (mono) { + if (portamento) { + boolean n_found = false; + for (int i = 0; i < voices.length; i++) { + if (voices[i].on && voices[i].channel == channel + && voices[i].active + && voices[i].releaseTriggered == false) { + voices[i].portamento = true; + voices[i].setNote(noteNumber); + n_found = true; + } + } + if (n_found) { + portamento_lastnote[0] = noteNumber; + return; + } + } + + if (portamento_control_note != -1) { + boolean n_found = false; + for (int i = 0; i < voices.length; i++) { + if (voices[i].on && voices[i].channel == channel + && voices[i].active + && voices[i].note == portamento_control_note + && voices[i].releaseTriggered == false) { + voices[i].portamento = true; + voices[i].setNote(noteNumber); + n_found = true; + } + } + portamento_control_note = -1; + if (n_found) + return; + } + } + + if (mono) + allNotesOff(); + + if (current_instrument == null) { + current_instrument + = synthesizer.findInstrument(program, bank, channel); + if (current_instrument == null) + return; + if (current_mixer != null) + mainmixer.stopMixer(current_mixer); + current_mixer = current_instrument.getSourceInstrument() + .getChannelMixer(this, synthesizer.getFormat()); + if (current_mixer != null) + mainmixer.registerMixer(current_mixer); + current_director = current_instrument.getDirector(this, this); + applyInstrumentCustomization(); + } + prevVoiceID = synthesizer.voiceIDCounter++; + firstVoice = true; + voiceNo = 0; + + int tunedKey = (int)(Math.round(tuning.getTuning()[noteNumber]/100.0)); + play_noteNumber = noteNumber; + play_velocity = velocity; + play_releasetriggered = false; + lastVelocity[noteNumber] = velocity; + current_director.noteOn(tunedKey, velocity); + + /* + SoftPerformer[] performers = current_instrument.getPerformers(); + for (int i = 0; i < performers.length; i++) { + SoftPerformer p = performers[i]; + if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey) { + if (p.velFrom <= velocity && p.velTo >= velocity) { + if (firstVoice) { + firstVoice = false; + if (p.exclusiveClass != 0) { + int x = p.exclusiveClass; + for (int j = 0; j < voices.length; j++) { + if (voices[j].active + && voices[j].channel == channel + && voices[j].exclusiveClass == x) { + if (!(p.selfNonExclusive + && voices[j].note == noteNumber)) + voices[j].shutdown(); + } + } + } + } + voiceNo = findFreeVoice(voiceNo); + if (voiceNo == -1) + return; + initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, + velocity); + } + } + } + */ + } + } + + public void noteOff(int noteNumber, int velocity) { + noteNumber = restrict7Bit(noteNumber); + velocity = restrict7Bit(velocity); + noteOff_internal(noteNumber, velocity); + + if (current_mixer != null) + current_mixer.noteOff(noteNumber, velocity); + } + + private void noteOff_internal(int noteNumber, int velocity) { + synchronized (control_mutex) { + + if (!mono) { + if (portamento) { + if (portamento_lastnote_ix != 127) { + portamento_lastnote[portamento_lastnote_ix] = noteNumber; + portamento_lastnote_ix++; + } + } + } + + mainmixer.activity(); + for (int i = 0; i < voices.length; i++) { + if (voices[i].on && voices[i].channel == channel + && voices[i].note == noteNumber + && voices[i].releaseTriggered == false) { + voices[i].noteOff(velocity); + } + } + + // Try play back note-off triggered voices, + + if (current_instrument == null) { + current_instrument + = synthesizer.findInstrument(program, bank, channel); + if (current_instrument == null) + return; + if (current_mixer != null) + mainmixer.stopMixer(current_mixer); + current_mixer = current_instrument.getSourceInstrument() + .getChannelMixer(this, synthesizer.getFormat()); + if (current_mixer != null) + mainmixer.registerMixer(current_mixer); + current_director = current_instrument.getDirector(this, this); + applyInstrumentCustomization(); + + } + prevVoiceID = synthesizer.voiceIDCounter++; + firstVoice = true; + voiceNo = 0; + + int tunedKey = (int)(Math.round(tuning.getTuning()[noteNumber]/100.0)); + play_noteNumber = noteNumber; + play_velocity = lastVelocity[noteNumber]; + play_releasetriggered = true; + current_director.noteOff(tunedKey, velocity); + + } + } + private int[] lastVelocity = new int[128]; + private int prevVoiceID; + private boolean firstVoice = true; + private int voiceNo = 0; + private int play_noteNumber = 0; + private int play_velocity = 0; + private boolean play_releasetriggered = false; + + public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks) { + + int noteNumber = play_noteNumber; + int velocity = play_velocity; + boolean releasetriggered = play_releasetriggered; + + SoftPerformer p = current_instrument.getPerformers()[performerIndex]; + + if (firstVoice) { + firstVoice = false; + if (p.exclusiveClass != 0) { + int x = p.exclusiveClass; + for (int j = 0; j < voices.length; j++) { + if (voices[j].active && voices[j].channel == channel + && voices[j].exclusiveClass == x) { + if (!(p.selfNonExclusive && voices[j].note == noteNumber)) + voices[j].shutdown(); + } + } + } + } + + voiceNo = findFreeVoice(voiceNo); + + if (voiceNo == -1) + return; + + initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity, + connectionBlocks, current_mixer, releasetriggered); + } + + public void noteOff(int noteNumber) { + if(noteNumber < 0 || noteNumber > 127) return; + noteOff_internal(noteNumber, 64); + } + + public void setPolyPressure(int noteNumber, int pressure) { + noteNumber = restrict7Bit(noteNumber); + pressure = restrict7Bit(pressure); + + if (current_mixer != null) + current_mixer.setPolyPressure(noteNumber, pressure); + + synchronized (control_mutex) { + mainmixer.activity(); + co_midi[noteNumber].get(0, "poly_pressure")[0] = pressure*(1.0/128.0); + polypressure[noteNumber] = pressure; + for (int i = 0; i < voices.length; i++) { + if (voices[i].active && voices[i].note == noteNumber) + voices[i].setPolyPressure(pressure); + } + } + } + + public int getPolyPressure(int noteNumber) { + synchronized (control_mutex) { + return polypressure[noteNumber]; + } + } + + public void setChannelPressure(int pressure) { + pressure = restrict7Bit(pressure); + if (current_mixer != null) + current_mixer.setChannelPressure(pressure); + synchronized (control_mutex) { + mainmixer.activity(); + co_midi_channel_pressure[0] = pressure * (1.0 / 128.0); + channelpressure = pressure; + for (int i = 0; i < voices.length; i++) { + if (voices[i].active) + voices[i].setChannelPressure(pressure); + } + } + } + + public int getChannelPressure() { + synchronized (control_mutex) { + return channelpressure; + } + } + + protected void applyInstrumentCustomization() { + if (cds_control_connections == null + && cds_channelpressure_connections == null + && cds_polypressure_connections == null) { + return; + } + + ModelInstrument src_instrument = current_instrument.getSourceInstrument(); + ModelPerformer[] performers = src_instrument.getPerformers(); + ModelPerformer[] new_performers = new ModelPerformer[performers.length]; + for (int i = 0; i < new_performers.length; i++) { + ModelPerformer performer = performers[i]; + ModelPerformer new_performer = new ModelPerformer(); + new_performer.setName(performer.getName()); + new_performer.setExclusiveClass(performer.getExclusiveClass()); + new_performer.setKeyFrom(performer.getKeyFrom()); + new_performer.setKeyTo(performer.getKeyTo()); + new_performer.setVelFrom(performer.getVelFrom()); + new_performer.setVelTo(performer.getVelTo()); + new_performer.getOscillators().addAll(performer.getOscillators()); + new_performer.getConnectionBlocks().addAll( + performer.getConnectionBlocks()); + new_performers[i] = new_performer; + + List connblocks = + new_performer.getConnectionBlocks(); + + if (cds_control_connections != null) { + String cc = Integer.toString(cds_control_number); + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if (sources != null) { + for (int j = 0; j < sources.length; j++) { + ModelSource src = sources[j]; + if ("midi_cc".equals(src.getIdentifier().getObject()) + && cc.equals(src.getIdentifier().getVariable())) { + removeok = true; + } + } + } + if (removeok) + iter.remove(); + } + for (int j = 0; j < cds_control_connections.length; j++) + connblocks.add(cds_control_connections[j]); + } + + if (cds_polypressure_connections != null) { + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if (sources != null) { + for (int j = 0; j < sources.length; j++) { + ModelSource src = sources[j]; + if ("midi".equals(src.getIdentifier().getObject()) + && "poly_pressure".equals( + src.getIdentifier().getVariable())) { + removeok = true; + } + } + } + if (removeok) + iter.remove(); + } + for (int j = 0; j < cds_polypressure_connections.length; j++) + connblocks.add(cds_polypressure_connections[j]); + } + + + if (cds_channelpressure_connections != null) { + Iterator iter = connblocks.iterator(); + while (iter.hasNext()) { + ModelConnectionBlock conn = iter.next(); + ModelSource[] sources = conn.getSources(); + boolean removeok = false; + if (sources != null) { + for (int j = 0; j < sources.length; j++) { + ModelIdentifier srcid = sources[j].getIdentifier(); + if ("midi".equals(srcid.getObject()) && + "channel_pressure".equals(srcid.getVariable())) { + removeok = true; + } + } + } + if (removeok) + iter.remove(); + } + for (int j = 0; j < cds_channelpressure_connections.length; j++) + connblocks.add(cds_channelpressure_connections[j]); + } + + } + + current_instrument = new SoftInstrument(src_instrument, new_performers); + + } + + private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid, + int[] destination, int[] range) { + + /* + controlled parameter (pp)|range (rr)| Description |Default + -------------------------|----------|-------------------------|------- + 00 Pitch Control | 28H..58H | -24..+24 semitones | 40H + 01 Filter Cutoff Control | 00H..7FH | -9600..+9450 cents | 40H + 02 Amplitude Control | 00H..7FH | 0..(127/64)*100 percent | 40H + 03 LFO Pitch Depth | 00H..7FH | 0..600 cents | 0 + 04 LFO Filter Depth | 00H..7FH | 0..2400 cents | 0 + 05 LFO Amplitude Depth | 00H..7FH | 0..100 percent | 0 + */ + + List conns = new ArrayList(); + + for (int i = 0; i < destination.length; i++) { + int d = destination[i]; + int r = range[i]; + if (d == 0) { + double scale = (r - 64) * 100; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + scale, + new ModelDestination( + new ModelIdentifier("osc", "pitch"))); + conns.add(conn); + + } + if (d == 1) { + double scale = (r / 64.0 - 1.0) * 9600.0; + ModelConnectionBlock conn; + if (scale > 0) { + conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + -scale, + new ModelDestination( + ModelDestination.DESTINATION_FILTER_FREQ)); + } else { + conn = new ModelConnectionBlock( + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + scale, + new ModelDestination( + ModelDestination.DESTINATION_FILTER_FREQ)); + } + conns.add(conn); + } + if (d == 2) { + final double scale = (r / 64.0); + ModelTransform mt = new ModelTransform() { + double s = scale; + public double transform(double value) { + if (s < 1) + value = s + (value * (1.0 - s)); + else if (s > 1) + value = 1 + (value * (s - 1.0)); + else + return 0; + return -((5.0 / 12.0) / Math.log(10)) * Math.log(value); + } + }; + + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(sid, mt), -960, + new ModelDestination(ModelDestination.DESTINATION_GAIN)); + conns.add(conn); + + } + if (d == 3) { + double scale = (r / 64.0 - 1.0) * 9600.0; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + scale, + new ModelDestination( + ModelDestination.DESTINATION_PITCH)); + conns.add(conn); + } + if (d == 4) { + double scale = (r / 128.0) * 2400.0; + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + scale, + new ModelDestination( + ModelDestination.DESTINATION_FILTER_FREQ)); + conns.add(conn); + } + if (d == 5) { + final double scale = (r / 127.0); + + ModelTransform mt = new ModelTransform() { + double s = scale; + public double transform(double value) { + return -((5.0 / 12.0) / Math.log(10)) + * Math.log(1 - value * s); + } + }; + + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(sid, mt), + -960, + new ModelDestination( + ModelDestination.DESTINATION_GAIN)); + conns.add(conn); + } + } + + return conns.toArray(new ModelConnectionBlock[conns.size()]); + } + + public void mapPolyPressureToDestination(int[] destination, int[] range) { + current_instrument = null; + if (destination.length == 0) { + cds_polypressure_connections = null; + return; + } + cds_polypressure_connections + = createModelConnections( + new ModelIdentifier("midi", "poly_pressure"), + destination, range); + } + + public void mapChannelPressureToDestination(int[] destination, int[] range) { + current_instrument = null; + if (destination.length == 0) { + cds_channelpressure_connections = null; + return; + } + cds_channelpressure_connections + = createModelConnections( + new ModelIdentifier("midi", "channel_pressure"), + destination, range); + } + + public void mapControlToDestination(int control, int[] destination, int[] range) { + + if (!((control >= 0x01 && control <= 0x1F) + || (control >= 0x40 && control <= 0x5F))) { + cds_control_connections = null; + return; + } + + current_instrument = null; + cds_control_number = control; + if (destination.length == 0) { + cds_control_connections = null; + return; + } + cds_control_connections + = createModelConnections( + new ModelIdentifier("midi_cc", Integer.toString(control)), + destination, range); + } + + public void controlChangePerNote(int noteNumber, int controller, int value) { + +/* + CC# | nn | Name | vv | default | description +-----|------|-------------------------|----------------|------------|------------------------------- +7 |07H |Note Volume |00H-40H-7FH |40H |0-100-(127/64)*100(%)(Relative) +10 |0AH |*Pan |00H-7FH absolute|Preset Value|Left-Center-Right (absolute) +33-63|21-3FH|LSB for |01H-1FH | | +71 |47H |Timbre/Harmonic Intensity|00H-40H-7FH |40H (???) | +72 |48H |Release Time |00H-40H-7FH |40H (???) | +73 |49H |Attack Time |00H-40H-7FH |40H (???) | +74 |4AH |Brightness |00H-40H-7FH |40H (???) | +75 |4BH |Decay Time |00H-40H-7FH |40H (???) | +76 |4CH |Vibrato Rate |00H-40H-7FH |40H (???) | +77 |4DH |Vibrato Depth |00H-40H-7FH |40H (???) | +78 |4EH |Vibrato Delay |00H-40H-7FH |40H (???) | +91 |5BH |*Reverb Send |00H-7FH absolute|Preset Value|Left-Center-Right (absolute) +93 |5DH |*Chorus Send |00H-7FH absolute|Preset Value|Left-Center-Right (absolute) +120 |78H |**Fine Tuning |00H-40H-7FH |40H (???) | +121 |79H |**Coarse Tuning |00H-40H-7FH |40H (???) | +*/ + + if (keybasedcontroller_active == null) { + keybasedcontroller_active = new boolean[128][]; + keybasedcontroller_value = new double[128][]; + } + if (keybasedcontroller_active[noteNumber] == null) { + keybasedcontroller_active[noteNumber] = new boolean[128]; + Arrays.fill(keybasedcontroller_active[noteNumber], false); + keybasedcontroller_value[noteNumber] = new double[128]; + Arrays.fill(keybasedcontroller_value[noteNumber], 0); + } + + if (value == -1) { + keybasedcontroller_active[noteNumber][controller] = false; + } else { + keybasedcontroller_active[noteNumber][controller] = true; + keybasedcontroller_value[noteNumber][controller] = value / 128.0; + } + + if (controller < 120) { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].controlChange(controller, -1); + } else if (controller == 120) { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(1, -1); + } else if (controller == 121) { + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(2, -1); + } + + } + + public int getControlPerNote(int noteNumber, int controller) { + if (keybasedcontroller_active == null) + return -1; + if (keybasedcontroller_active[noteNumber] == null) + return -1; + if (!keybasedcontroller_active[noteNumber][controller]) + return -1; + return (int)(keybasedcontroller_value[noteNumber][controller] * 128); + } + + public void controlChange(int controller, int value) { + controller = restrict7Bit(controller); + value = restrict7Bit(value); + if (current_mixer != null) + current_mixer.controlChange(controller, value); + + synchronized (control_mutex) { + switch (controller) { + /* + Mapco_midi_rpn_rpn_i = new HashMap(); + Mapco_midi_rpn_rpn = new HashMap(); + Mapco_midi_nrpn_nrpn_i = new HashMap(); + Mapco_midi_nrpn_nrpn = new HashMap(); + */ + + case 5: + // This produce asin-like curve + // as described in General Midi Level 2 Specification, page 6 + double x = -Math.asin((value / 128.0) * 2 - 1) / Math.PI + 0.5; + x = Math.pow(100000.0, x) / 100.0; // x is now cent/msec + // Convert x from cent/msec to key/controlbuffertime + x = x / 100.0; // x is now keys/msec + x = x * 1000.0; // x is now keys/sec + x = x / synthesizer.getControlRate(); // x is now keys/controlbuffertime + portamento_time = x; + break; + case 6: + case 38: + case 96: + case 97: + int val = 0; + if (nrpn_control != RPN_NULL_VALUE) { + int[] val_i = co_midi_nrpn_nrpn_i.get(nrpn_control); + if (val_i != null) + val = val_i[0]; + } + if (rpn_control != RPN_NULL_VALUE) { + int[] val_i = co_midi_rpn_rpn_i.get(rpn_control); + if (val_i != null) + val = val_i[0]; + } + + if (controller == 6) + val = (val & 127) + (value << 7); + else if (controller == 38) + val = (val & (127 << 7)) + value; + else if (controller == 96 || controller == 97) { + int step = 1; + if (rpn_control == 2 || rpn_control == 3 || rpn_control == 4) + step = 128; + if (controller == 96) + val += step; + if (controller == 97) + val -= step; + } + + if (nrpn_control != RPN_NULL_VALUE) + nrpnChange(nrpn_control, val); + if (rpn_control != RPN_NULL_VALUE) + rpnChange(rpn_control, val); + + break; + case 64: // Hold1 (Damper) (cc#64) + boolean on = value >= 64; + if (sustain != on) { + sustain = on; + if (!on) { + for (int i = 0; i < voices.length; i++) { + if (voices[i].active && voices[i].sustain && + voices[i].channel == channel) { + voices[i].sustain = false; + if (!voices[i].on) { + voices[i].on = true; + voices[i].noteOff(0); + } + } + } + } else { + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + voices[i].redamp(); + } + } + break; + case 65: + //allNotesOff(); + portamento = value >= 64; + portamento_lastnote[0] = -1; + /* + for (int i = 0; i < portamento_lastnote.length; i++) + portamento_lastnote[i] = -1; + */ + portamento_lastnote_ix = 0; + break; + case 66: // Sostenuto (cc#66) + on = value >= 64; + if (on) { + for (int i = 0; i < voices.length; i++) { + if (voices[i].active && voices[i].on && + voices[i].channel == channel) { + voices[i].sostenuto = true; + } + } + } + if (!on) { + for (int i = 0; i < voices.length; i++) { + if (voices[i].active && voices[i].sostenuto && + voices[i].channel == channel) { + voices[i].sostenuto = false; + if (!voices[i].on) { + voices[i].on = true; + voices[i].noteOff(0); + } + } + } + } + break; + case 84: + portamento_control_note = value; + break; + case 98: + nrpn_control = (nrpn_control & (127 << 7)) + value; + rpn_control = RPN_NULL_VALUE; + break; + case 99: + nrpn_control = (nrpn_control & 127) + (value << 7); + rpn_control = RPN_NULL_VALUE; + break; + case 100: + rpn_control = (rpn_control & (127 << 7)) + value; + nrpn_control = RPN_NULL_VALUE; + break; + case 101: + rpn_control = (rpn_control & 127) + (value << 7); + nrpn_control = RPN_NULL_VALUE; + break; + case 120: + allSoundOff(); + break; + case 121: + resetAllControllers(value == 127); + break; + case 122: + localControl(value >= 64); + break; + case 123: + allNotesOff(); + break; + case 124: + setOmni(false); + break; + case 125: + setOmni(true); + break; + case 126: + if (value == 1) + setMono(true); + break; + case 127: + setMono(false); + break; + + default: + break; + } + + co_midi_cc_cc[controller][0] = value * (1.0 / 128.0); + + if (controller == 0x00) { + bank = /*(bank & 127) +*/ (value << 7); + return; + } + + if (controller == 0x20) { + bank = (bank & (127 << 7)) + value; + return; + } + + this.controller[controller] = value; + if(controller < 0x20) + this.controller[controller + 0x20] = 0; + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].controlChange(controller, value); + + } + } + + public int getController(int controller) { + synchronized (control_mutex) { + // Should only return lower 7 bits, + // even when controller is "boosted" higher. + return this.controller[controller] & 127; + } + } + + public void tuningChange(int program) { + tuningChange(0, program); + } + + public void tuningChange(int bank, int program) { + synchronized (control_mutex) { + tuning = synthesizer.getTuning(new Patch(bank, program)); + } + } + + public void programChange(int program) { + programChange(bank, program); + } + + public void programChange(int bank, int program) { + bank = restrict7Bit(bank); + program = restrict7Bit(program); + synchronized (control_mutex) { + mainmixer.activity(); + this.bank = bank; + this.program = program; + current_instrument = null; + } + } + + public int getProgram() { + synchronized (control_mutex) { + return program; + } + } + + public void setPitchBend(int bend) { + bend = restrict14Bit(bend); + if (current_mixer != null) + current_mixer.setPitchBend(bend); + synchronized (control_mutex) { + mainmixer.activity(); + co_midi_pitch[0] = bend * (1.0 / 16384.0); + pitchbend = bend; + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].setPitchBend(bend); + } + } + + public int getPitchBend() { + synchronized (control_mutex) { + return pitchbend; + } + } + + public void nrpnChange(int controller, int value) { + + /* + System.out.println("(" + channel + ").nrpnChange(" + + Integer.toHexString(controller >> 7) + + " " + Integer.toHexString(controller & 127) + + ", " + Integer.toHexString(value >> 7) + + " " + Integer.toHexString(value & 127) + ")"); + */ + + if (synthesizer.getGeneralMidiMode() == 0) { + if (controller == (0x01 << 7) + (0x08)) // Vibrato Rate + controlChange(76, value >> 7); + if (controller == (0x01 << 7) + (0x09)) // Vibrato Depth + controlChange(77, value >> 7); + if (controller == (0x01 << 7) + (0x0A)) // Vibrato Delay + controlChange(78, value >> 7); + if (controller == (0x01 << 7) + (0x20)) // Brightness + controlChange(74, value >> 7); + if (controller == (0x01 << 7) + (0x21)) // Filter Resonance + controlChange(71, value >> 7); + if (controller == (0x01 << 7) + (0x63)) // Attack Time + controlChange(73, value >> 7); + if (controller == (0x01 << 7) + (0x64)) // Decay Time + controlChange(75, value >> 7); + if (controller == (0x01 << 7) + (0x66)) // Release Time + controlChange(72, value >> 7); + + if (controller >> 7 == 0x18) // Pitch coarse + controlChangePerNote(controller % 128, 120, value >> 7); + if (controller >> 7 == 0x1A) // Volume + controlChangePerNote(controller % 128, 7, value >> 7); + if (controller >> 7 == 0x1C) // Panpot + controlChangePerNote(controller % 128, 10, value >> 7); + if (controller >> 7 == 0x1D) // Reverb + controlChangePerNote(controller % 128, 91, value >> 7); + if (controller >> 7 == 0x1E) // Chorus + controlChangePerNote(controller % 128, 93, value >> 7); + } + + int[] val_i = co_midi_nrpn_nrpn_i.get(controller); + double[] val_d = co_midi_nrpn_nrpn.get(controller); + if (val_i == null) { + val_i = new int[1]; + co_midi_nrpn_nrpn_i.put(controller, val_i); + } + if (val_d == null) { + val_d = new double[1]; + co_midi_nrpn_nrpn.put(controller, val_d); + } + val_i[0] = value; + val_d[0] = val_i[0] * (1.0 / 16384.0); + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].nrpnChange(controller, val_i[0]); + + } + + public void rpnChange(int controller, int value) { + + /* + System.out.println("(" + channel + ").rpnChange(" + + Integer.toHexString(controller >> 7) + + " " + Integer.toHexString(controller & 127) + + ", " + Integer.toHexString(value >> 7) + + " " + Integer.toHexString(value & 127) + ")"); + */ + + if (controller == 3) { + tuning_program = (value >> 7) & 127; + tuningChange(tuning_bank, tuning_program); + } + if (controller == 4) { + tuning_bank = (value >> 7) & 127; + } + + int[] val_i = co_midi_rpn_rpn_i.get(controller); + double[] val_d = co_midi_rpn_rpn.get(controller); + if (val_i == null) { + val_i = new int[1]; + co_midi_rpn_rpn_i.put(controller, val_i); + } + if (val_d == null) { + val_d = new double[1]; + co_midi_rpn_rpn.put(controller, val_d); + } + val_i[0] = value; + val_d[0] = val_i[0] * (1.0 / 16384.0); + + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + voices[i].rpnChange(controller, val_i[0]); + } + + public void resetAllControllers() { + resetAllControllers(false); + } + + public void resetAllControllers(boolean allControls) { + synchronized (control_mutex) { + mainmixer.activity(); + + for (int i = 0; i < 128; i++) { + setPolyPressure(i, 0); + } + setChannelPressure(0); + setPitchBend(8192); + for (int i = 0; i < 128; i++) { + if (!dontResetControls[i]) + controlChange(i, 0); + } + + controlChange(71, 64); // Filter Resonance + controlChange(72, 64); // Release Time + controlChange(73, 64); // Attack Time + controlChange(74, 64); // Brightness + controlChange(75, 64); // Decay Time + controlChange(76, 64); // Vibrato Rate + controlChange(77, 64); // Vibrato Depth + controlChange(78, 64); // Vibrato Delay + + controlChange(8, 64); // Balance + controlChange(11, 127); // Expression + controlChange(98, 127); // NRPN Null + controlChange(99, 127); // NRPN Null + controlChange(100, 127); // RPN = Null + controlChange(101, 127); // RPN = Null + + // see DLS 2.1 (Power-on Default Values) + if (allControls) { + + keybasedcontroller_active = null; + keybasedcontroller_value = null; + + controlChange(7, 100); // Volume + controlChange(10, 64); // Pan + controlChange(91, 40); // Reverb + + for (int controller : co_midi_rpn_rpn.keySet()) { + // don't reset tuning settings + if (controller != 3 && controller != 4) + rpnChange(controller, 0); + } + for (int controller : co_midi_nrpn_nrpn.keySet()) + nrpnChange(controller, 0); + rpnChange(0, 2 << 7); // Bitch Bend sensitivity + rpnChange(1, 64 << 7); // Channel fine tunning + rpnChange(2, 64 << 7); // Channel Coarse Tuning + rpnChange(5, 64); // Modulation Depth, +/- 50 cent + + tuning_bank = 0; + tuning_program = 0; + tuning = new SoftTuning(); + + } + + } + } + + public void allNotesOff() { + if (current_mixer != null) + current_mixer.allNotesOff(); + synchronized (control_mutex) { + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel + && voices[i].releaseTriggered == false) { + voices[i].noteOff(0); + } + } + } + + public void allSoundOff() { + if (current_mixer != null) + current_mixer.allSoundOff(); + synchronized (control_mutex) { + for (int i = 0; i < voices.length; i++) + if (voices[i].on && voices[i].channel == channel) + voices[i].soundOff(); + } + } + + public boolean localControl(boolean on) { + return false; + } + + public void setMono(boolean on) { + if (current_mixer != null) + current_mixer.setMono(on); + synchronized (control_mutex) { + allNotesOff(); + mono = on; + } + } + + public boolean getMono() { + synchronized (control_mutex) { + return mono; + } + } + + public void setOmni(boolean on) { + if (current_mixer != null) + current_mixer.setOmni(on); + allNotesOff(); + // Omni is not supported by GM2 + } + + public boolean getOmni() { + return false; + } + + public void setMute(boolean mute) { + if (current_mixer != null) + current_mixer.setMute(mute); + synchronized (control_mutex) { + this.mute = mute; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + voices[i].setMute(mute); + } + } + + public boolean getMute() { + synchronized (control_mutex) { + return mute; + } + } + + public void setSolo(boolean soloState) { + if (current_mixer != null) + current_mixer.setSolo(soloState); + + synchronized (control_mutex) { + this.solo = soloState; + + boolean soloinuse = false; + for (SoftChannel c : synthesizer.channels) { + if (c.solo) { + soloinuse = true; + break; + } + } + + if (!soloinuse) { + for (SoftChannel c : synthesizer.channels) + c.setSoloMute(false); + return; + } + + for (SoftChannel c : synthesizer.channels) + c.setSoloMute(!c.solo); + + } + + } + + private void setSoloMute(boolean mute) { + synchronized (control_mutex) { + if (solomute == mute) + return; + this.solomute = mute; + for (int i = 0; i < voices.length; i++) + if (voices[i].active && voices[i].channel == channel) + voices[i].setSoloMute(solomute); + } + } + + public boolean getSolo() { + synchronized (control_mutex) { + return solo; + } + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java b/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java new file mode 100644 index 00000000000..d4fcf886181 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftChannelProxy.java @@ -0,0 +1,202 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.MidiChannel; + +/** + * A MidiChannel proxy object used for external access to synthesizer internal + * channel objects. + * + * @author Karl Helgason + */ +public class SoftChannelProxy implements MidiChannel { + + private MidiChannel channel = null; + + public MidiChannel getChannel() { + return channel; + } + + public void setChannel(MidiChannel channel) { + this.channel = channel; + } + + public void allNotesOff() { + if (channel == null) + return; + channel.allNotesOff(); + } + + public void allSoundOff() { + if (channel == null) + return; + channel.allSoundOff(); + } + + public void controlChange(int controller, int value) { + if (channel == null) + return; + channel.controlChange(controller, value); + } + + public int getChannelPressure() { + if (channel == null) + return 0; + return channel.getChannelPressure(); + } + + public int getController(int controller) { + if (channel == null) + return 0; + return channel.getController(controller); + } + + public boolean getMono() { + if (channel == null) + return false; + return channel.getMono(); + } + + public boolean getMute() { + if (channel == null) + return false; + return channel.getMute(); + } + + public boolean getOmni() { + if (channel == null) + return false; + return channel.getOmni(); + } + + public int getPitchBend() { + if (channel == null) + return 8192; + return channel.getPitchBend(); + } + + public int getPolyPressure(int noteNumber) { + if (channel == null) + return 0; + return channel.getPolyPressure(noteNumber); + } + + public int getProgram() { + if (channel == null) + return 0; + return channel.getProgram(); + } + + public boolean getSolo() { + if (channel == null) + return false; + return channel.getSolo(); + } + + public boolean localControl(boolean on) { + if (channel == null) + return false; + return channel.localControl(on); + } + + public void noteOff(int noteNumber) { + if (channel == null) + return; + channel.noteOff(noteNumber); + } + + public void noteOff(int noteNumber, int velocity) { + if (channel == null) + return; + channel.noteOff(noteNumber, velocity); + } + + public void noteOn(int noteNumber, int velocity) { + if (channel == null) + return; + channel.noteOn(noteNumber, velocity); + } + + public void programChange(int program) { + if (channel == null) + return; + channel.programChange(program); + } + + public void programChange(int bank, int program) { + if (channel == null) + return; + channel.programChange(bank, program); + } + + public void resetAllControllers() { + if (channel == null) + return; + channel.resetAllControllers(); + } + + public void setChannelPressure(int pressure) { + if (channel == null) + return; + channel.setChannelPressure(pressure); + } + + public void setMono(boolean on) { + if (channel == null) + return; + channel.setMono(on); + } + + public void setMute(boolean mute) { + if (channel == null) + return; + channel.setMute(mute); + } + + public void setOmni(boolean on) { + if (channel == null) + return; + channel.setOmni(on); + } + + public void setPitchBend(int bend) { + if (channel == null) + return; + channel.setPitchBend(bend); + } + + public void setPolyPressure(int noteNumber, int pressure) { + if (channel == null) + return; + channel.setPolyPressure(noteNumber, pressure); + } + + public void setSolo(boolean soloState) { + if (channel == null) + return; + channel.setSolo(soloState); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java b/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java new file mode 100644 index 00000000000..0a9f6443950 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftChorus.java @@ -0,0 +1,341 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Arrays; + +/** + * A chorus effect made using LFO and variable delay. One for each channel + * (left,right), with different starting phase for stereo effect. + * + * @author Karl Helgason + */ +public class SoftChorus implements SoftAudioProcessor { + + private static class VariableDelay { + + private float[] delaybuffer; + private int rovepos = 0; + private volatile float gain = 1; + private volatile float rgain = 0; + private volatile float delay = 0; + private float lastdelay = 0; + private volatile float feedback = 0; + + public VariableDelay(int maxbuffersize) { + delaybuffer = new float[maxbuffersize]; + } + + public void setDelay(float delay) { + this.delay = delay; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + } + + public void setGain(float gain) { + this.gain = gain; + } + + public void setReverbSendGain(float rgain) { + this.rgain = rgain; + } + + public void processMix(float[] in, float[] out, float[] rout) { + float gain = this.gain; + float delay = this.delay; + float feedback = this.feedback; + + float[] delaybuffer = this.delaybuffer; + int len = in.length; + float delaydelta = (delay - lastdelay) / len; + int rnlen = delaybuffer.length; + int rovepos = this.rovepos; + + if (rout == null) + for (int i = 0; i < len; i++) { + float r = rovepos - (lastdelay + 2) + rnlen; + int ri = (int) r; + float s = r - ri; + float a = delaybuffer[ri % rnlen]; + float b = delaybuffer[(ri + 1) % rnlen]; + float o = a * (1 - s) + b * (s); + out[i] += o * gain; + delaybuffer[rovepos] = in[i] + o * feedback; + rovepos = (rovepos + 1) % rnlen; + lastdelay += delaydelta; + } + else + for (int i = 0; i < len; i++) { + float r = rovepos - (lastdelay + 2) + rnlen; + int ri = (int) r; + float s = r - ri; + float a = delaybuffer[ri % rnlen]; + float b = delaybuffer[(ri + 1) % rnlen]; + float o = a * (1 - s) + b * (s); + out[i] += o * gain; + rout[i] += o * rgain; + delaybuffer[rovepos] = in[i] + o * feedback; + rovepos = (rovepos + 1) % rnlen; + lastdelay += delaydelta; + } + this.rovepos = rovepos; + lastdelay = delay; + } + + public void processReplace(float[] in, float[] out, float[] rout) { + Arrays.fill(out, 0); + Arrays.fill(rout, 0); + processMix(in, out, rout); + } + } + + private static class LFODelay { + + private volatile double c_cos_delta; + private volatile double c_sin_delta; + private double c_cos = 1; + private double c_sin = 0; + private double depth = 0; + private VariableDelay vdelay; + private double samplerate; + private double controlrate; + + public LFODelay(double samplerate, double controlrate) { + this.samplerate = samplerate; + this.controlrate = controlrate; + // vdelay = new VariableDelay((int)(samplerate*4)); + vdelay = new VariableDelay((int) ((this.depth + 10) * 2)); + + } + + public void setDepth(double depth) { + this.depth = depth * samplerate; + vdelay = new VariableDelay((int) ((this.depth + 10) * 2)); + } + + public void setRate(double rate) { + double g = (Math.PI * 2) * (rate / controlrate); + c_cos_delta = Math.cos(g); + c_sin_delta = Math.sin(g); + } + + public void setPhase(double phase) { + c_cos = Math.cos(phase); + c_sin = Math.sin(phase); + } + + public void setFeedBack(float feedback) { + vdelay.setFeedBack(feedback); + } + + public void setGain(float gain) { + vdelay.setGain(gain); + } + + public void setReverbSendGain(float rgain) { + vdelay.setReverbSendGain(rgain); + } + + public void processMix(float[] in, float[] out, float[] rout) { + c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; + c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; + vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + vdelay.processMix(in, out, rout); + } + + public void processReplace(float[] in, float[] out, float[] rout) { + c_cos = c_cos * c_cos_delta - c_sin * c_sin_delta; + c_sin = c_cos * c_sin_delta + c_sin * c_cos_delta; + vdelay.setDelay((float) (depth * 0.5 * (c_cos + 2))); + vdelay.processReplace(in, out, rout); + + } + } + private boolean mix = true; + private SoftAudioBuffer inputA; + private SoftAudioBuffer left; + private SoftAudioBuffer right; + private SoftAudioBuffer reverb; + private LFODelay vdelay1L; + private LFODelay vdelay1R; + private float rgain = 0; + private boolean dirty = true; + private double dirty_vdelay1L_rate; + private double dirty_vdelay1R_rate; + private double dirty_vdelay1L_depth; + private double dirty_vdelay1R_depth; + private float dirty_vdelay1L_feedback; + private float dirty_vdelay1R_feedback; + private float dirty_vdelay1L_reverbsendgain; + private float dirty_vdelay1R_reverbsendgain; + private float controlrate; + + public void init(float samplerate, float controlrate) { + this.controlrate = controlrate; + vdelay1L = new LFODelay(samplerate, controlrate); + vdelay1R = new LFODelay(samplerate, controlrate); + vdelay1L.setGain(1.0f); // % + vdelay1R.setGain(1.0f); // % + vdelay1L.setPhase(0.5 * Math.PI); + vdelay1R.setPhase(0); + + globalParameterControlChange(new int[]{0x01 * 128 + 0x02}, 0, 2); + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + if (slothpath.length == 1) { + if (slothpath[0] == 0x01 * 128 + 0x02) { + if (param == 0) { // Chorus Type + switch ((int)value) { + case 0: // Chorus 1 0 (0%) 3 (0.4Hz) 5 (1.9ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 0); + globalParameterControlChange(slothpath, 1, 3); + globalParameterControlChange(slothpath, 2, 5); + globalParameterControlChange(slothpath, 4, 0); + break; + case 1: // Chorus 2 5 (4%) 9 (1.1Hz) 19 (6.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 5); + globalParameterControlChange(slothpath, 1, 9); + globalParameterControlChange(slothpath, 2, 19); + globalParameterControlChange(slothpath, 4, 0); + break; + case 2: // Chorus 3 8 (6%) 3 (0.4Hz) 19 (6.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 8); + globalParameterControlChange(slothpath, 1, 3); + globalParameterControlChange(slothpath, 2, 19); + globalParameterControlChange(slothpath, 4, 0); + break; + case 3: // Chorus 4 16 (12%) 9 (1.1Hz) 16 (5.3ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 16); + globalParameterControlChange(slothpath, 1, 9); + globalParameterControlChange(slothpath, 2, 16); + globalParameterControlChange(slothpath, 4, 0); + break; + case 4: // FB Chorus 64 (49%) 2 (0.2Hz) 24 (7.8ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 64); + globalParameterControlChange(slothpath, 1, 2); + globalParameterControlChange(slothpath, 2, 24); + globalParameterControlChange(slothpath, 4, 0); + break; + case 5: // Flanger 112 (86%) 1 (0.1Hz) 5 (1.9ms) 0 (0%) + globalParameterControlChange(slothpath, 3, 112); + globalParameterControlChange(slothpath, 1, 1); + globalParameterControlChange(slothpath, 2, 5); + globalParameterControlChange(slothpath, 4, 0); + break; + default: + break; + } + } else if (param == 1) { // Mod Rate + dirty_vdelay1L_rate = (value * 0.122); + dirty_vdelay1R_rate = (value * 0.122); + dirty = true; + } else if (param == 2) { // Mod Depth + dirty_vdelay1L_depth = ((value + 1) / 3200.0); + dirty_vdelay1R_depth = ((value + 1) / 3200.0); + dirty = true; + } else if (param == 3) { // Feedback + dirty_vdelay1L_feedback = (value * 0.00763f); + dirty_vdelay1R_feedback = (value * 0.00763f); + dirty = true; + } + if (param == 4) { // Send to Reverb + rgain = value * 0.00787f; + dirty_vdelay1L_reverbsendgain = (value * 0.00787f); + dirty_vdelay1R_reverbsendgain = (value * 0.00787f); + dirty = true; + } + + } + } + } + + public void processControlLogic() { + if (dirty) { + dirty = false; + vdelay1L.setRate(dirty_vdelay1L_rate); + vdelay1R.setRate(dirty_vdelay1R_rate); + vdelay1L.setDepth(dirty_vdelay1L_depth); + vdelay1R.setDepth(dirty_vdelay1R_depth); + vdelay1L.setFeedBack(dirty_vdelay1L_feedback); + vdelay1R.setFeedBack(dirty_vdelay1R_feedback); + vdelay1L.setReverbSendGain(dirty_vdelay1L_reverbsendgain); + vdelay1R.setReverbSendGain(dirty_vdelay1R_reverbsendgain); + } + } + double silentcounter = 1000; + + public void processAudio() { + + if (inputA.isSilent()) { + silentcounter += 1 / controlrate; + + if (silentcounter > 1) { + if (!mix) { + left.clear(); + right.clear(); + } + return; + } + } else + silentcounter = 0; + + float[] inputA = this.inputA.array(); + float[] left = this.left.array(); + float[] right = this.right == null ? null : this.right.array(); + float[] reverb = rgain != 0 ? this.reverb.array() : null; + + if (mix) { + vdelay1L.processMix(inputA, left, reverb); + if (right != null) + vdelay1R.processMix(inputA, right, reverb); + } else { + vdelay1L.processReplace(inputA, left, reverb); + if (right != null) + vdelay1R.processReplace(inputA, right, reverb); + } + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + inputA = input; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + left = output; + if (pin == 1) + right = output; + if (pin == 2) + reverb = output; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftControl.java b/jdk/src/share/classes/com/sun/media/sound/SoftControl.java new file mode 100644 index 00000000000..7b521f39196 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftControl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * SoftControl are the basic controls + * used for control-rate processing. + * + * @author Karl Helgason + */ +public interface SoftControl { + + public double[] get(int instance, String name); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java new file mode 100644 index 00000000000..cc994111012 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftCubicResampler.java @@ -0,0 +1,87 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A resampler that uses third-order (cubic) interpolation. + * + * @author Karl Helgason + */ +public class SoftCubicResampler extends SoftAbstractResampler { + + public int getPadding() { + return 3; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float y0 = in[iix - 1]; + float y1 = in[iix]; + float y2 = in[iix + 1]; + float y3 = in[iix + 2]; + float a0 = y3 - y2 + y1 - y0; + float a1 = y0 - y1 - a0; + float a2 = y2 - y0; + float a3 = y1; + //float fix2 = fix * fix; + //out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3); + out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float y0 = in[iix - 1]; + float y1 = in[iix]; + float y2 = in[iix + 1]; + float y3 = in[iix + 2]; + float a0 = y3 - y2 + y1 - y0; + float a1 = y0 - y1 - a0; + float a2 = y2 - y0; + float a3 = y1; + //float fix2 = fix * fix; + //out[ox++] = (a0 * fix + a1) * fix2 + (a2 * fix + a3); + out[ox++] = ((a0 * fix + a1) * fix + a2) * fix + a3; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java b/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java new file mode 100644 index 00000000000..c5462ab91d2 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftEnvelopeGenerator.java @@ -0,0 +1,298 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * AHDSR control signal envelope generator. + * + * @author Karl Helgason + */ +public class SoftEnvelopeGenerator implements SoftProcess { + + public final static int EG_OFF = 0; + public final static int EG_DELAY = 1; + public final static int EG_ATTACK = 2; + public final static int EG_HOLD = 3; + public final static int EG_DECAY = 4; + public final static int EG_SUSTAIN = 5; + public final static int EG_RELEASE = 6; + public final static int EG_SHUTDOWN = 7; + public final static int EG_END = 8; + int max_count = 10; + int used_count = 0; + private int[] stage = new int[max_count]; + private int[] stage_ix = new int[max_count]; + private double[] stage_v = new double[max_count]; + private int[] stage_count = new int[max_count]; + private double[][] on = new double[max_count][1]; + private double[][] active = new double[max_count][1]; + private double[][] out = new double[max_count][1]; + private double[][] delay = new double[max_count][1]; + private double[][] attack = new double[max_count][1]; + private double[][] hold = new double[max_count][1]; + private double[][] decay = new double[max_count][1]; + private double[][] sustain = new double[max_count][1]; + private double[][] release = new double[max_count][1]; + private double[][] shutdown = new double[max_count][1]; + private double[][] release2 = new double[max_count][1]; + private double[][] attack2 = new double[max_count][1]; + private double[][] decay2 = new double[max_count][1]; + private double control_time = 0; + + public void reset() { + for (int i = 0; i < used_count; i++) { + stage[i] = 0; + on[i][0] = 0; + out[i][0] = 0; + delay[i][0] = 0; + attack[i][0] = 0; + hold[i][0] = 0; + decay[i][0] = 0; + sustain[i][0] = 0; + release[i][0] = 0; + shutdown[i][0] = 0; + attack2[i][0] = 0; + decay2[i][0] = 0; + release2[i][0] = 0; + } + used_count = 0; + } + + public void init(SoftSynthesizer synth) { + control_time = 1.0 / synth.getControlRate(); + processControlLogic(); + } + + public double[] get(int instance, String name) { + if (instance >= used_count) + used_count = instance + 1; + if (name == null) + return out[instance]; + if (name.equals("on")) + return on[instance]; + if (name.equals("active")) + return active[instance]; + if (name.equals("delay")) + return delay[instance]; + if (name.equals("attack")) + return attack[instance]; + if (name.equals("hold")) + return hold[instance]; + if (name.equals("decay")) + return decay[instance]; + if (name.equals("sustain")) + return sustain[instance]; + if (name.equals("release")) + return release[instance]; + if (name.equals("shutdown")) + return shutdown[instance]; + if (name.equals("attack2")) + return attack2[instance]; + if (name.equals("decay2")) + return decay2[instance]; + if (name.equals("release2")) + return release2[instance]; + + return null; + } + + public void processControlLogic() { + for (int i = 0; i < used_count; i++) { + + if (stage[i] == EG_END) + continue; + + if ((stage[i] > EG_OFF) && (stage[i] < EG_RELEASE)) { + if (on[i][0] < 0.5) { + if (on[i][0] < -0.5) { + stage_count[i] = (int)(Math.pow(2, + this.shutdown[i][0] / 1200.0) / control_time); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_v[i] = out[i][0]; + stage_ix[i] = 0; + stage[i] = EG_SHUTDOWN; + } else { + if ((release2[i][0] < 0.000001) && release[i][0] < 0 + && Double.isInfinite(release[i][0])) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + continue; + } + + stage_count[i] = (int)(Math.pow(2, + this.release[i][0] / 1200.0) / control_time); + stage_count[i] + += (int)(this.release2[i][0]/(control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + // stage_v[i] = out[i][0]; + stage_ix[i] = 0; + + double m = 1 - out[i][0]; + stage_ix[i] = (int)(stage_count[i] * m); + + stage[i] = EG_RELEASE; + } + } + } + + switch (stage[i]) { + case EG_OFF: + active[i][0] = 1; + if (on[i][0] < 0.5) + break; + stage[i] = EG_DELAY; + stage_ix[i] = (int)(Math.pow(2, + this.delay[i][0] / 1200.0) / control_time); + if (stage_ix[i] < 0) + stage_ix[i] = 0; + case EG_DELAY: + if (stage_ix[i] == 0) { + double attack = this.attack[i][0]; + double attack2 = this.attack2[i][0]; + + if (attack2 < 0.000001 + && (attack < 0 && Double.isInfinite(attack))) { + out[i][0] = 1; + stage[i] = EG_HOLD; + stage_count[i] = (int)(Math.pow(2, + this.hold[i][0] / 1200.0) / control_time); + stage_ix[i] = 0; + } else { + stage[i] = EG_ATTACK; + stage_count[i] = (int)(Math.pow(2, + attack / 1200.0) / control_time); + stage_count[i] += (int)(attack2 / (control_time * 1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_ix[i] = 0; + } + } else + stage_ix[i]--; + break; + case EG_ATTACK: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 1; + stage[i] = EG_HOLD; + } else { + // CONVEX attack + double a = ((double)stage_ix[i]) / ((double)stage_count[i]); + a = 1 + ((40.0 / 96.0) / Math.log(10)) * Math.log(a); + if (a < 0) + a = 0; + else if (a > 1) + a = 1; + out[i][0] = a; + } + break; + case EG_HOLD: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + stage[i] = EG_DECAY; + stage_count[i] = (int)(Math.pow(2, + this.decay[i][0] / 1200.0) / control_time); + stage_count[i] += (int)(this.decay2[i][0]/(control_time*1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_ix[i] = 0; + } + break; + case EG_DECAY: + stage_ix[i]++; + double sustain = this.sustain[i][0] * (1.0 / 1000.0); + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = sustain; + stage[i] = EG_SUSTAIN; + if (sustain < 0.001) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } + } else { + double m = ((double)stage_ix[i]) / ((double)stage_count[i]); + out[i][0] = (1 - m) + sustain * m; + } + break; + case EG_SUSTAIN: + break; + case EG_RELEASE: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } else { + double m = ((double)stage_ix[i]) / ((double)stage_count[i]); + out[i][0] = (1 - m); // *stage_v[i]; + + if (on[i][0] < -0.5) { + stage_count[i] = (int)(Math.pow(2, + this.shutdown[i][0] / 1200.0) / control_time); + if (stage_count[i] < 0) + stage_count[i] = 0; + stage_v[i] = out[i][0]; + stage_ix[i] = 0; + stage[i] = EG_SHUTDOWN; + } + + // re-damping + if (on[i][0] > 0.5) { + sustain = this.sustain[i][0] * (1.0 / 1000.0); + if (out[i][0] > sustain) { + stage[i] = EG_DECAY; + stage_count[i] = (int)(Math.pow(2, + this.decay[i][0] / 1200.0) / control_time); + stage_count[i] += + (int)(this.decay2[i][0]/(control_time*1000)); + if (stage_count[i] < 0) + stage_count[i] = 0; + m = (out[i][0] - 1) / (sustain - 1); + stage_ix[i] = (int) (stage_count[i] * m); + } + } + + } + break; + case EG_SHUTDOWN: + stage_ix[i]++; + if (stage_ix[i] >= stage_count[i]) { + out[i][0] = 0; + active[i][0] = 0; + stage[i] = EG_END; + } else { + double m = ((double)stage_ix[i]) / ((double)stage_count[i]); + out[i][0] = (1 - m) * stage_v[i]; + } + break; + default: + break; + } + } + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java b/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java new file mode 100644 index 00000000000..0468f15bec0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftFilter.java @@ -0,0 +1,614 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Infinite impulse response (IIR) filter class. + * + * The filters where implemented and adapted using algorithms from musicdsp.org + * archive: 1-RC and C filter, Simple 2-pole LP LP and HP filter, biquad, + * tweaked butterworth RBJ Audio-EQ-Cookbook, EQ filter kookbook + * + * @author Karl Helgason + */ +public class SoftFilter { + + public final static int FILTERTYPE_LP6 = 0x00; + public final static int FILTERTYPE_LP12 = 0x01; + public final static int FILTERTYPE_HP12 = 0x11; + public final static int FILTERTYPE_BP12 = 0x21; + public final static int FILTERTYPE_NP12 = 0x31; + public final static int FILTERTYPE_LP24 = 0x03; + public final static int FILTERTYPE_HP24 = 0x13; + + // + // 0x0 = 1st-order, 6 dB/oct + // 0x1 = 2nd-order, 12 dB/oct + // 0x2 = 3rd-order, 18 dB/oct + // 0x3 = 4th-order, 24 db/oct + // + // 0x00 = LP, Low Pass Filter + // 0x10 = HP, High Pass Filter + // 0x20 = BP, Band Pass Filter + // 0x30 = NP, Notch or Band Elimination Filter + // + private int filtertype = FILTERTYPE_LP6; + private float samplerate; + private float x1; + private float x2; + private float y1; + private float y2; + private float xx1; + private float xx2; + private float yy1; + private float yy2; + private float a0; + private float a1; + private float a2; + private float b1; + private float b2; + private float q; + private float gain = 1; + private float wet = 0; + private float last_wet = 0; + private float last_a0; + private float last_a1; + private float last_a2; + private float last_b1; + private float last_b2; + private float last_q; + private float last_gain; + private boolean last_set = false; + private double cutoff = 44100; + private double resonancedB = 0; + private boolean dirty = true; + + public SoftFilter(float samplerate) { + this.samplerate = samplerate; + dirty = true; + } + + public void setFrequency(double cent) { + if (cutoff == cent) + return; + cutoff = cent; + dirty = true; + } + + public void setResonance(double db) { + if (resonancedB == db) + return; + resonancedB = db; + dirty = true; + } + + public void reset() { + dirty = true; + last_set = false; + x1 = 0; + x2 = 0; + y1 = 0; + y2 = 0; + xx1 = 0; + xx2 = 0; + yy1 = 0; + yy2 = 0; + wet = 0.0f; + gain = 1.0f; + a0 = 0; + a1 = 0; + a2 = 0; + b1 = 0; + b2 = 0; + } + + public void setFilterType(int filtertype) { + this.filtertype = filtertype; + } + + public void processAudio(SoftAudioBuffer sbuffer) { + if (filtertype == FILTERTYPE_LP6) + filter1(sbuffer); + if (filtertype == FILTERTYPE_LP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_HP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_BP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_NP12) + filter2(sbuffer); + if (filtertype == FILTERTYPE_LP24) + filter4(sbuffer); + if (filtertype == FILTERTYPE_HP24) + filter4(sbuffer); + } + + public void filter4(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter2calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_a1 = a1; + last_a2 = a2; + last_b1 = b1; + last_b2 = b2; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float a1 = this.last_a1; + float a2 = this.last_a2; + float b1 = this.last_b1; + float b2 = this.last_b2; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float a1_delta = (this.a1 - this.last_a1) / len; + float a2_delta = (this.a2 - this.last_a2) / len; + float b1_delta = (this.b1 - this.last_b1) / len; + float b2_delta = (this.b2 - this.last_b2) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float x1 = this.x1; + float x2 = this.x2; + float y1 = this.y1; + float y2 = this.y2; + float xx1 = this.xx1; + float xx2 = this.xx2; + float yy1 = this.yy1; + float yy2 = this.yy2; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + wet += wet_delta; + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0*xx + a1*xx1 + a2*xx2 - b1*yy1 - b2*yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0 + && b1_delta == 0 && b2_delta == 0) { + for (int i = 0; i < len; i++) { + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0*xx + a1*xx1 + a2*xx2 - b1*yy1 - b2*yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + float xx = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + float yy = (a0*xx + a1*xx1 + a2*xx2 - b1*yy1 - b2*yy2); + buffer[i] = (yy * gain) * wet + (xx) * (1 - wet); + xx2 = xx1; + xx1 = xx; + yy2 = yy1; + yy1 = yy; + } + } + + if (Math.abs(x1) < 1.0E-8) + x1 = 0; + if (Math.abs(x2) < 1.0E-8) + x2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + this.xx1 = xx1; + this.xx2 = xx2; + this.yy1 = yy1; + this.yy2 = yy2; + } + + this.last_a0 = this.a0; + this.last_a1 = this.a1; + this.last_a2 = this.a2; + this.last_b1 = this.b1; + this.last_b2 = this.b2; + this.last_gain = this.gain; + this.last_wet = this.wet; + + } + + private double sinh(double x) { + return (Math.exp(x) - Math.exp(-x)) * 0.5; + } + + public void filter2calc() { + + double resonancedB = this.resonancedB; + if (resonancedB < 0) + resonancedB = 0; // Negative dB are illegal. + if (resonancedB > 30) + resonancedB = 30; // At least 22.5 dB is needed. + if (filtertype == FILTERTYPE_LP24 || filtertype == FILTERTYPE_HP24) + resonancedB *= 0.6; + + if (filtertype == FILTERTYPE_BP12) { + wet = 1; + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + + double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20)); + + double omega = 2 * Math.PI * r; + double cs = Math.cos(omega); + double sn = Math.sin(omega); + double alpha = sn * sinh((Math.log(2)*bandwidth*omega) / (sn * 2)); + + double b0 = alpha; + double b1 = 0; + double b2 = -alpha; + double a0 = 1 + alpha; + double a1 = -2 * cs; + double a2 = 1 - alpha; + + double cf = 1.0 / a0; + this.b1 = (float) (a1 * cf); + this.b2 = (float) (a2 * cf); + this.a0 = (float) (b0 * cf); + this.a1 = (float) (b1 * cf); + this.a2 = (float) (b2 * cf); + } + + if (filtertype == FILTERTYPE_NP12) { + wet = 1; + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + + double bandwidth = Math.PI * Math.pow(10.0, -(resonancedB / 20)); + + double omega = 2 * Math.PI * r; + double cs = Math.cos(omega); + double sn = Math.sin(omega); + double alpha = sn * sinh((Math.log(2)*bandwidth*omega) / (sn*2)); + + double b0 = 1; + double b1 = -2 * cs; + double b2 = 1; + double a0 = 1 + alpha; + double a1 = -2 * cs; + double a2 = 1 - alpha; + + double cf = 1.0 / a0; + this.b1 = (float)(a1 * cf); + this.b2 = (float)(a2 * cf); + this.a0 = (float)(b0 * cf); + this.a1 = (float)(b1 * cf); + this.a2 = (float)(b2 * cf); + } + + if (filtertype == FILTERTYPE_LP12 || filtertype == FILTERTYPE_LP24) { + double r = (cutoff / samplerate); + if (r > 0.45) { + if (wet == 0) { + if (resonancedB < 0.00001) + wet = 0.0f; + else + wet = 1.0f; + } + r = 0.45; + } else + wet = 1.0f; + + double c = 1.0 / (Math.tan(Math.PI * r)); + double csq = c * c; + double resonance = Math.pow(10.0, -(resonancedB / 20)); + double q = Math.sqrt(2.0f) * resonance; + double a0 = 1.0 / (1.0 + (q * c) + (csq)); + double a1 = 2.0 * a0; + double a2 = a0; + double b1 = (2.0 * a0) * (1.0 - csq); + double b2 = a0 * (1.0 - (q * c) + csq); + + this.a0 = (float)a0; + this.a1 = (float)a1; + this.a2 = (float)a2; + this.b1 = (float)b1; + this.b2 = (float)b2; + + } + + if (filtertype == FILTERTYPE_HP12 || filtertype == FILTERTYPE_HP24) { + double r = (cutoff / samplerate); + if (r > 0.45) + r = 0.45; + if (r < 0.0001) + r = 0.0001; + wet = 1.0f; + double c = (Math.tan(Math.PI * (r))); + double csq = c * c; + double resonance = Math.pow(10.0, -(resonancedB / 20)); + double q = Math.sqrt(2.0f) * resonance; + double a0 = 1.0 / (1.0 + (q * c) + (csq)); + double a1 = -2.0 * a0; + double a2 = a0; + double b1 = (2.0 * a0) * (csq - 1.0); + double b2 = a0 * (1.0 - (q * c) + csq); + + this.a0 = (float)a0; + this.a1 = (float)a1; + this.a2 = (float)a2; + this.b1 = (float)b1; + this.b2 = (float)b2; + + } + + } + + public void filter2(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter2calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_a1 = a1; + last_a2 = a2; + last_b1 = b1; + last_b2 = b2; + last_q = q; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float a1 = this.last_a1; + float a2 = this.last_a2; + float b1 = this.last_b1; + float b2 = this.last_b2; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float a1_delta = (this.a1 - this.last_a1) / len; + float a2_delta = (this.a2 - this.last_a2) / len; + float b1_delta = (this.b1 - this.last_b1) / len; + float b2_delta = (this.b2 - this.last_b2) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float x1 = this.x1; + float x2 = this.x2; + float y1 = this.y1; + float y2 = this.y2; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + wet += wet_delta; + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + buffer[i] = (y * gain) * wet + (x) * (1 - wet); + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } else if (a0_delta == 0 && a1_delta == 0 && a2_delta == 0 + && b1_delta == 0 && b2_delta == 0) { + for (int i = 0; i < len; i++) { + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + buffer[i] = y * gain; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + a1 += a1_delta; + a2 += a2_delta; + b1 += b1_delta; + b2 += b2_delta; + gain += gain_delta; + float x = buffer[i]; + float y = (a0*x + a1*x1 + a2*x2 - b1*y1 - b2*y2); + buffer[i] = y * gain; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } + } + + if (Math.abs(x1) < 1.0E-8) + x1 = 0; + if (Math.abs(x2) < 1.0E-8) + x2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + } + + this.last_a0 = this.a0; + this.last_a1 = this.a1; + this.last_a2 = this.a2; + this.last_b1 = this.b1; + this.last_b2 = this.b2; + this.last_q = this.q; + this.last_gain = this.gain; + this.last_wet = this.wet; + + } + + public void filter1calc() { + if (cutoff < 120) + cutoff = 120; + double c = (7.0 / 6.0) * Math.PI * 2 * cutoff / samplerate; + if (c > 1) + c = 1; + a0 = (float)(Math.sqrt(1 - Math.cos(c)) * Math.sqrt(0.5 * Math.PI)); + if (resonancedB < 0) + resonancedB = 0; + if (resonancedB > 20) + resonancedB = 20; + q = (float)(Math.sqrt(0.5) * Math.pow(10.0, -(resonancedB / 20))); + gain = (float)Math.pow(10, -((resonancedB)) / 40.0); + if (wet == 0.0f) + if (resonancedB > 0.00001 || c < 0.9999999) + wet = 1.0f; + } + + public void filter1(SoftAudioBuffer sbuffer) { + + float[] buffer = sbuffer.array(); + + if (dirty) { + filter1calc(); + dirty = false; + } + if (!last_set) { + last_a0 = a0; + last_q = q; + last_gain = gain; + last_wet = wet; + last_set = true; + } + + if (wet > 0 || last_wet > 0) { + + int len = buffer.length; + float a0 = this.last_a0; + float q = this.last_q; + float gain = this.last_gain; + float wet = this.last_wet; + float a0_delta = (this.a0 - this.last_a0) / len; + float q_delta = (this.q - this.last_q) / len; + float gain_delta = (this.gain - this.last_gain) / len; + float wet_delta = (this.wet - this.last_wet) / len; + float y2 = this.y2; + float y1 = this.y1; + + if (wet_delta != 0) { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + q += q_delta; + gain += gain_delta; + wet += wet_delta; + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain * wet + buffer[i] * (1 - wet); + } + } else if (a0_delta == 0 && q_delta == 0) { + for (int i = 0; i < len; i++) { + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain; + } + } else { + for (int i = 0; i < len; i++) { + a0 += a0_delta; + q += q_delta; + gain += gain_delta; + y1 = (1 - q * a0) * y1 - (a0) * y2 + (a0) * buffer[i]; + y2 = (1 - q * a0) * y2 + (a0) * y1; + buffer[i] = y2 * gain; + } + } + + if (Math.abs(y2) < 1.0E-8) + y2 = 0; + if (Math.abs(y1) < 1.0E-8) + y1 = 0; + this.y2 = y2; + this.y1 = y1; + } + + this.last_a0 = this.a0; + this.last_q = this.q; + this.last_gain = this.gain; + this.last_wet = this.wet; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java b/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java new file mode 100644 index 00000000000..fbeaf6b8d3e --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftInstrument.java @@ -0,0 +1,82 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; + +/** + * Software synthesizer internal instrument. + * + * @author Karl Helgason + */ +public class SoftInstrument extends Instrument { + + private SoftPerformer[] performers; + private ModelPerformer[] modelperformers; + private Object data; + private ModelInstrument ins; + + public SoftInstrument(ModelInstrument ins) { + super(ins.getSoundbank(), ins.getPatch(), ins.getName(), + ins.getDataClass()); + data = ins.getData(); + this.ins = ins; + initPerformers(((ModelInstrument)ins).getPerformers()); + } + + public SoftInstrument(ModelInstrument ins, + ModelPerformer[] overrideperformers) { + super(ins.getSoundbank(), ins.getPatch(), ins.getName(), + ins.getDataClass()); + data = ins.getData(); + this.ins = ins; + initPerformers(overrideperformers); + } + + private void initPerformers(ModelPerformer[] modelperformers) { + this.modelperformers = modelperformers; + performers = new SoftPerformer[modelperformers.length]; + for (int i = 0; i < modelperformers.length; i++) + performers[i] = new SoftPerformer(modelperformers[i]); + } + + public ModelDirector getDirector(MidiChannel channel, + ModelDirectedPlayer player) { + return ins.getDirector(modelperformers, channel, player); + } + + public ModelInstrument getSourceInstrument() { + return ins; + } + + public Object getData() { + return data; + } + + public SoftPerformer[] getPerformers() { + return performers; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java new file mode 100644 index 00000000000..98d205b6deb --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftJitterCorrector.java @@ -0,0 +1,276 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; + +/** + * A jitter corrector to be used with SoftAudioPusher. + * + * @author Karl Helgason + */ +public class SoftJitterCorrector extends AudioInputStream { + + private static class JitterStream extends InputStream { + + static int MAX_BUFFER_SIZE = 1048576; + boolean active = true; + Thread thread; + AudioInputStream stream; + // Cyclic buffer + int writepos = 0; + int readpos = 0; + byte[][] buffers; + Object buffers_mutex = new Object(); + + // Adapative Drift Statistics + int w_count = 1000; + int w_min_tol = 2; + int w_max_tol = 10; + int w = 0; + int w_min = -1; + // Current read buffer + int bbuffer_pos = 0; + int bbuffer_max = 0; + byte[] bbuffer = null; + + public byte[] nextReadBuffer() { + synchronized (buffers_mutex) { + if (writepos > readpos) { + int w_m = writepos - readpos; + if (w_m < w_min) + w_min = w_m; + + int buffpos = readpos; + readpos++; + return buffers[buffpos % buffers.length]; + } + w_min = -1; + w = w_count - 1; + } + while (true) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + //e.printStackTrace(); + return null; + } + synchronized (buffers_mutex) { + if (writepos > readpos) { + w = 0; + w_min = -1; + w = w_count - 1; + int buffpos = readpos; + readpos++; + return buffers[buffpos % buffers.length]; + } + } + } + } + + public byte[] nextWriteBuffer() { + synchronized (buffers_mutex) { + return buffers[writepos % buffers.length]; + } + } + + public void commit() { + synchronized (buffers_mutex) { + writepos++; + if ((writepos - readpos) > buffers.length) { + int newsize = (writepos - readpos) + 10; + newsize = Math.max(buffers.length * 2, newsize); + buffers = new byte[newsize][buffers[0].length]; + } + } + } + + public JitterStream(AudioInputStream s, int buffersize, + int smallbuffersize) { + this.w_count = 10 * (buffersize / smallbuffersize); + if (w_count < 100) + w_count = 100; + this.buffers + = new byte[(buffersize/smallbuffersize)+10][smallbuffersize]; + this.bbuffer_max = MAX_BUFFER_SIZE / smallbuffersize; + this.stream = s; + + + Runnable runnable = new Runnable() { + + public void run() { + AudioFormat format = stream.getFormat(); + int bufflen = buffers[0].length; + int frames = bufflen / format.getFrameSize(); + long nanos = (long) (frames * 1000000000.0 + / format.getSampleRate()); + long now = System.nanoTime(); + long next = now + nanos; + int correction = 0; + while (true) { + synchronized (JitterStream.this) { + if (!active) + break; + } + int curbuffsize; + synchronized (buffers) { + curbuffsize = writepos - readpos; + if (correction == 0) { + w++; + if (w_min != Integer.MAX_VALUE) { + if (w == w_count) { + correction = 0; + if (w_min < w_min_tol) { + correction = (w_min_tol + w_max_tol) + / 2 - w_min; + } + if (w_min > w_max_tol) { + correction = (w_min_tol + w_max_tol) + / 2 - w_min; + } + w = 0; + w_min = Integer.MAX_VALUE; + } + } + } + } + while (curbuffsize > bbuffer_max) { + synchronized (buffers) { + curbuffsize = writepos - readpos; + } + synchronized (JitterStream.this) { + if (!active) + break; + } + try { + Thread.sleep(1); + } catch (InterruptedException e) { + //e.printStackTrace(); + } + } + + if (correction < 0) + correction++; + else { + byte[] buff = nextWriteBuffer(); + try { + int n = 0; + while (n != buff.length) { + int s = stream.read(buff, n, buff.length + - n); + if (s < 0) + throw new EOFException(); + if (s == 0) + Thread.yield(); + n += s; + } + } catch (IOException e1) { + //e1.printStackTrace(); + } + commit(); + } + + if (correction > 0) { + correction--; + next = System.nanoTime() + nanos; + continue; + } + long wait = next - System.nanoTime(); + if (wait > 0) { + try { + Thread.sleep(wait / 1000000L); + } catch (InterruptedException e) { + //e.printStackTrace(); + } + } + next += nanos; + } + } + }; + + thread = new Thread(runnable); + thread.setPriority(Thread.MAX_PRIORITY); + thread.start(); + } + + public void close() throws IOException { + synchronized (this) { + active = false; + } + try { + thread.join(); + } catch (InterruptedException e) { + //e.printStackTrace(); + } + stream.close(); + } + + public int read() throws IOException { + byte[] b = new byte[1]; + if (read(b) == -1) + return -1; + return b[0] & 0xFF; + } + + public void fillBuffer() { + bbuffer = nextReadBuffer(); + bbuffer_pos = 0; + } + + public int read(byte[] b, int off, int len) { + if (bbuffer == null) + fillBuffer(); + int bbuffer_len = bbuffer.length; + int offlen = off + len; + while (off < offlen) { + if (available() == 0) + fillBuffer(); + else { + byte[] bbuffer = this.bbuffer; + int bbuffer_pos = this.bbuffer_pos; + while (off < offlen && bbuffer_pos < bbuffer_len) + b[off++] = bbuffer[bbuffer_pos++]; + this.bbuffer_pos = bbuffer_pos; + } + } + return len; + } + + public int available() { + return bbuffer.length - bbuffer_pos; + } + } + + public SoftJitterCorrector(AudioInputStream stream, int buffersize, + int smallbuffersize) { + super(new JitterStream(stream, buffersize, smallbuffersize), + stream.getFormat(), stream.getFrameLength()); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java new file mode 100644 index 00000000000..526cd4327df --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftLanczosResampler.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Lanczos interpolation resampler. + * + * @author Karl Helgason + */ +public class SoftLanczosResampler extends SoftAbstractResampler { + + float[][] sinc_table; + int sinc_table_fsize = 2000; + int sinc_table_size = 5; + int sinc_table_center = sinc_table_size / 2; + + public SoftLanczosResampler() { + super(); + sinc_table = new float[sinc_table_fsize][]; + for (int i = 0; i < sinc_table_fsize; i++) { + sinc_table[i] = sincTable(sinc_table_size, -i + / ((float) sinc_table_fsize)); + } + } + + // Normalized sinc function + public static double sinc(double x) { + return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x); + } + + // Generate sinc table + public static float[] sincTable(int size, float offset) { + int center = size / 2; + float[] w = new float[size]; + for (int k = 0; k < size; k++) { + float x = (-center + k + offset); + if (x < -2 || x > 2) + w[k] = 0; + else if (x == 0) + w[k] = 1; + else { + w[k] = (float)(2.0 * Math.sin(Math.PI * x) + * Math.sin(Math.PI * x / 2.0) + / ((Math.PI * x) * (Math.PI * x))); + } + } + return w; + } + + public int getPadding() // must be at least half of sinc_table_size + { + return sinc_table_size / 2 + 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table + = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table + = this.sinc_table[(int) ((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java b/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java new file mode 100644 index 00000000000..7ba0ac66002 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftLimiter.java @@ -0,0 +1,191 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A simple look-ahead volume limiter with very fast attack and fast release. + * This filter is used for preventing clipping. + * + * @author Karl Helgason + */ +public class SoftLimiter implements SoftAudioProcessor { + + float lastmax = 0; + float gain = 1; + float[] temp_bufferL; + float[] temp_bufferR; + boolean mix = false; + SoftAudioBuffer bufferL; + SoftAudioBuffer bufferR; + SoftAudioBuffer bufferLout; + SoftAudioBuffer bufferRout; + float controlrate; + + public void init(float samplerate, float controlrate) { + this.controlrate = controlrate; + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + bufferL = input; + if (pin == 1) + bufferR = input; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + bufferLout = output; + if (pin == 1) + bufferRout = output; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + } + + double silentcounter = 0; + + public void processAudio() { + if (this.bufferL.isSilent() + && (this.bufferR == null || this.bufferR.isSilent())) { + silentcounter += 1 / controlrate; + + if (silentcounter > 60) { + if (!mix) { + bufferLout.clear(); + bufferRout.clear(); + } + return; + } + } else + silentcounter = 0; + + float[] bufferL = this.bufferL.array(); + float[] bufferR = this.bufferR == null ? null : this.bufferR.array(); + float[] bufferLout = this.bufferLout.array(); + float[] bufferRout = this.bufferRout == null + ? null : this.bufferRout.array(); + + if (temp_bufferL == null || temp_bufferL.length < bufferL.length) + temp_bufferL = new float[bufferL.length]; + if (bufferR != null) + if (temp_bufferR == null || temp_bufferR.length < bufferR.length) + temp_bufferR = new float[bufferR.length]; + + float max = 0; + int len = bufferL.length; + + if (bufferR == null) { + for (int i = 0; i < len; i++) { + if (bufferL[i] > max) + max = bufferL[i]; + if (-bufferL[i] > max) + max = -bufferL[i]; + } + } else { + for (int i = 0; i < len; i++) { + if (bufferL[i] > max) + max = bufferL[i]; + if (bufferR[i] > max) + max = bufferR[i]; + if (-bufferL[i] > max) + max = -bufferL[i]; + if (-bufferR[i] > max) + max = -bufferR[i]; + } + } + + float lmax = lastmax; + lastmax = max; + if (lmax > max) + max = lmax; + + float newgain = 1; + if (max > 0.99f) + newgain = 0.99f / max; + else + newgain = 1; + + if (newgain > gain) + newgain = (newgain + gain * 9) / 10f; + + float gaindelta = (newgain - gain) / len; + if (mix) { + if (bufferR == null) { + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float tL = temp_bufferL[i]; + temp_bufferL[i] = bL; + bufferLout[i] += tL * gain; + } + } else { + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float bR = bufferR[i]; + float tL = temp_bufferL[i]; + float tR = temp_bufferR[i]; + temp_bufferL[i] = bL; + temp_bufferR[i] = bR; + bufferLout[i] += tL * gain; + bufferRout[i] += tR * gain; + } + } + + } else { + if (bufferR == null) { + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float tL = temp_bufferL[i]; + temp_bufferL[i] = bL; + bufferLout[i] = tL * gain; + } + } else { + for (int i = 0; i < len; i++) { + gain += gaindelta; + float bL = bufferL[i]; + float bR = bufferR[i]; + float tL = temp_bufferL[i]; + float tR = temp_bufferR[i]; + temp_bufferL[i] = bL; + temp_bufferR[i] = bR; + bufferLout[i] = tL * gain; + bufferRout[i] = tR * gain; + } + } + + } + gain = newgain; + } + + public void processControlLogic() { + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java new file mode 100644 index 00000000000..29f714ad40b --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler.java @@ -0,0 +1,70 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A resampler that uses first-order (linear) interpolation. + * + * @author Karl Helgason + */ +public class SoftLinearResampler extends SoftAbstractResampler { + + public int getPadding() { + return 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java b/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java new file mode 100644 index 00000000000..1838b4cfae1 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftLinearResampler2.java @@ -0,0 +1,108 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A resampler that uses first-order (linear) interpolation. + * + * This one doesn't perform float to int casting inside the processing loop. + * + * @author Karl Helgason + */ +public class SoftLinearResampler2 extends SoftAbstractResampler { + + public int getPadding() { + return 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + + // Check if we have do anything + if (!(ix < ix_end && ox < ox_end)) + return; + + // 15 bit shift was choosed because + // it resulted in no drift between p_ix and ix. + int p_ix = (int) (ix * (1 << 15)); + int p_ix_end = (int) (ix_end * (1 << 15)); + int p_pitch = (int) (pitch * (1 << 15)); + // Pitch needs to recalculated + // to ensure no drift between p_ix and ix. + pitch = p_pitch * (1f / (1 << 15)); + + if (pitchstep == 0f) { + + // To reduce + // while (p_ix < p_ix_end && ox < ox_end) + // into + // while (ox < ox_end) + // We need to calculate new ox_end value. + int p_ix_len = p_ix_end - p_ix; + int p_mod = p_ix_len % p_pitch; + if (p_mod != 0) + p_ix_len += p_pitch - p_mod; + int ox_end2 = ox + p_ix_len / p_pitch; + if (ox_end2 < ox_end) + ox_end = ox_end2; + + while (ox < ox_end) { + int iix = p_ix >> 15; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + p_ix += p_pitch; + ix += pitch; + } + + } else { + + int p_pitchstep = (int) (pitchstep * (1 << 15)); + pitchstep = p_pitchstep * (1f / (1 << 15)); + + while (p_ix < p_ix_end && ox < ox_end) { + int iix = p_ix >> 15; + float fix = ix - iix; + float i = in[iix]; + out[ox++] = i + (in[iix + 1] - i) * fix; + ix += pitch; + p_ix += p_pitch; + pitch += pitchstep; + p_pitch += p_pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java b/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java new file mode 100644 index 00000000000..adfe9e08de3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftLowFrequencyOscillator.java @@ -0,0 +1,122 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * LFO control signal generator. + * + * @author Karl Helgason + */ +public class SoftLowFrequencyOscillator implements SoftProcess { + + private int max_count = 10; + private int used_count = 0; + private double[][] out = new double[max_count][1]; + private double[][] delay = new double[max_count][1]; + private double[][] delay2 = new double[max_count][1]; + private double[][] freq = new double[max_count][1]; + private int[] delay_counter = new int[max_count]; + private double[] sin_phase = new double[max_count]; + private double[] sin_stepfreq = new double[max_count]; + private double[] sin_step = new double[max_count]; + private double control_time = 0; + private double sin_factor = 0; + private static double PI2 = 2.0 * Math.PI; + + public void reset() { + for (int i = 0; i < used_count; i++) { + out[i][0] = 0; + delay[i][0] = 0; + delay2[i][0] = 0; + freq[i][0] = 0; + delay_counter[i] = 0; + sin_phase[i] = 0; + sin_stepfreq[i] = 0; + sin_step[i] = 0; + } + used_count = 0; + } + + public void init(SoftSynthesizer synth) { + control_time = 1.0 / synth.getControlRate(); + sin_factor = control_time * 2 * Math.PI; + for (int i = 0; i < used_count; i++) { + delay_counter[i] = (int)(Math.pow(2, + this.delay[i][0] / 1200.0) / control_time); + delay_counter[i] += (int)(delay2[i][0] / (control_time * 1000)); + } + processControlLogic(); + } + + public void processControlLogic() { + for (int i = 0; i < used_count; i++) { + if (delay_counter[i] > 0) { + delay_counter[i]--; + out[i][0] = 0.5; + } else { + double f = freq[i][0]; + + if (sin_stepfreq[i] != f) { + sin_stepfreq[i] = f; + double fr = 440.0 * Math.exp( + (f - 6900.0) * (Math.log(2) / 1200.0)); + sin_step[i] = fr * sin_factor; + } + /* + double fr = 440.0 * Math.pow(2.0, + (freq[i][0] - 6900.0) / 1200.0); + sin_phase[i] += fr * sin_factor; + */ + /* + sin_phase[i] += sin_step[i]; + while (sin_phase[i] > PI2) + sin_phase[i] -= PI2; + out[i][0] = 0.5 + Math.sin(sin_phase[i]) * 0.5; + */ + double p = sin_phase[i]; + p += sin_step[i]; + while (p > PI2) + p -= PI2; + out[i][0] = 0.5 + Math.sin(p) * 0.5; + sin_phase[i] = p; + + } + } + } + + public double[] get(int instance, String name) { + if (instance >= used_count) + used_count = instance + 1; + if (name == null) + return out[instance]; + if (name.equals("delay")) + return delay[instance]; + if (name.equals("delay2")) + return delay2[instance]; + if (name.equals("freq")) + return freq[instance]; + return null; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java b/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java new file mode 100644 index 00000000000..1f38058b052 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMainMixer.java @@ -0,0 +1,982 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeMap; +import java.util.Map.Entry; + +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Patch; +import javax.sound.midi.ShortMessage; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * Software synthesizer main audio mixer. + * + * @author Karl Helgason + */ +public class SoftMainMixer { + + public final static int CHANNEL_LEFT = 0; + public final static int CHANNEL_RIGHT = 1; + public final static int CHANNEL_EFFECT1 = 2; + public final static int CHANNEL_EFFECT2 = 3; + public final static int CHANNEL_EFFECT3 = 4; + public final static int CHANNEL_EFFECT4 = 5; + public final static int CHANNEL_LEFT_DRY = 10; + public final static int CHANNEL_RIGHT_DRY = 11; + public final static int CHANNEL_SCRATCH1 = 12; + public final static int CHANNEL_SCRATCH2 = 13; + public final static int CHANNEL_CHANNELMIXER_LEFT = 14; + public final static int CHANNEL_CHANNELMIXER_RIGHT = 15; + protected boolean active_sensing_on = false; + private long msec_last_activity = -1; + private boolean pusher_silent = false; + private int pusher_silent_count = 0; + private long msec_pos = 0; + protected boolean readfully = true; + private Object control_mutex; + private SoftSynthesizer synth; + private int nrofchannels = 2; + private SoftVoice[] voicestatus = null; + private SoftAudioBuffer[] buffers; + private SoftReverb reverb; + private SoftAudioProcessor chorus; + private SoftAudioProcessor agc; + private long msec_buffer_len = 0; + protected TreeMap midimessages = new TreeMap(); + double last_volume_left = 1.0; + double last_volume_right = 1.0; + private double[] co_master_balance = new double[1]; + private double[] co_master_volume = new double[1]; + private double[] co_master_coarse_tuning = new double[1]; + private double[] co_master_fine_tuning = new double[1]; + private AudioInputStream ais; + private Set registeredMixers = null; + private Set stoppedMixers = null; + private ModelChannelMixer[] cur_registeredMixers = null; + protected SoftControl co_master = new SoftControl() { + + double[] balance = co_master_balance; + double[] volume = co_master_volume; + double[] coarse_tuning = co_master_coarse_tuning; + double[] fine_tuning = co_master_fine_tuning; + + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("balance")) + return balance; + if (name.equals("volume")) + return volume; + if (name.equals("coarse_tuning")) + return coarse_tuning; + if (name.equals("fine_tuning")) + return fine_tuning; + return null; + } + }; + + private void processSystemExclusiveMessage(byte[] data) { + synchronized (synth.control_mutex) { + activity(); + + // Universal Non-Real-Time SysEx + if ((data[1] & 0xFF) == 0x7E) { + int deviceID = data[2] & 0xFF; + if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + int subid1 = data[3] & 0xFF; + int subid2; + switch (subid1) { + case 0x08: // MIDI Tuning Standard + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // BULK TUNING DUMP + { + // http://www.midi.org/about-midi/tuning.shtml + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + break; + } + case 0x04: // KEY-BASED TUNING DUMP + case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format + case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format + case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) + // (BANK) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); + break; + } + case 0x08: // scale/octave tuning 1-byte form (Non + // Real-Time) + case 0x09: // scale/octave tuning 2-byte form (Non + // Real-Time) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + break; + } + default: + break; + } + break; + case 0x09: // General Midi Message + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // General Midi 1 On + synth.setGeneralMidiMode(1); + reset(); + break; + case 0x02: // General Midi Off + synth.setGeneralMidiMode(0); + reset(); + break; + case 0x03: // General MidI Level 2 On + synth.setGeneralMidiMode(2); + reset(); + break; + default: + break; + } + break; + case 0x0A: // DLS Message + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // DLS On + if (synth.getGeneralMidiMode() == 0) + synth.setGeneralMidiMode(1); + synth.voice_allocation_mode = 1; + reset(); + break; + case 0x02: // DLS Off + synth.setGeneralMidiMode(0); + synth.voice_allocation_mode = 0; + reset(); + break; + case 0x03: // DLS Static Voice Allocation Off + synth.voice_allocation_mode = 0; + break; + case 0x04: // DLS Static Voice Allocation On + synth.voice_allocation_mode = 1; + break; + default: + break; + } + break; + + default: + break; + } + } + } + + // Universal Real-Time SysEx + if ((data[1] & 0xFF) == 0x7F) { + int deviceID = data[2] & 0xFF; + if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + int subid1 = data[3] & 0xFF; + int subid2; + switch (subid1) { + case 0x04: // Device Control + + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Master Volume + case 0x02: // Master Balane + case 0x03: // Master fine tuning + case 0x04: // Master coarse tuning + int val = (data[5] & 0x7F) + + ((data[6] & 0x7F) * 128); + if (subid2 == 0x01) + setVolume(val); + else if (subid2 == 0x02) + setBalance(val); + else if (subid2 == 0x03) + setFineTuning(val); + else if (subid2 == 0x04) + setCoarseTuning(val); + break; + case 0x05: // Global Parameter Control + int ix = 5; + int slotPathLen = (data[ix++] & 0xFF); + int paramWidth = (data[ix++] & 0xFF); + int valueWidth = (data[ix++] & 0xFF); + int[] slotPath = new int[slotPathLen]; + for (int i = 0; i < slotPathLen; i++) { + int msb = (data[ix++] & 0xFF); + int lsb = (data[ix++] & 0xFF); + slotPath[i] = msb * 128 + lsb; + } + int paramCount = (data.length - 1 - ix) + / (paramWidth + valueWidth); + long[] params = new long[paramCount]; + long[] values = new long[paramCount]; + for (int i = 0; i < paramCount; i++) { + values[i] = 0; + for (int j = 0; j < paramWidth; j++) + params[i] = params[i] * 128 + + (data[ix++] & 0xFF); + for (int j = 0; j < valueWidth; j++) + values[i] = values[i] * 128 + + (data[ix++] & 0xFF); + + } + globalParameterControlChange(slotPath, params, values); + break; + default: + break; + } + break; + + case 0x08: // MIDI Tuning Standard + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + break; + } + case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + // (BANK) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + break; + } + case 0x08: // scale/octave tuning 1-byte form + //(Real-Time) + case 0x09: // scale/octave tuning 2-byte form + // (Real-Time) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if ((channelmask & (1 << (voices[i].channel))) != 0) + voices[i].updateTuning(tuning); + break; + } + default: + break; + } + break; + case 0x09: // Control Destination Settings + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Channel Pressure + { + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapChannelPressureToDestination( + destinations, ranges); + break; + } + case 0x02: // Poly Pressure + { + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapPolyPressureToDestination( + destinations, ranges); + break; + } + case 0x03: // Control Change + { + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 7; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + int control = data[6] & 0xFF; + softchannel.mapControlToDestination(control, + destinations, ranges); + break; + } + default: + break; + } + break; + + case 0x0A: // Key Based Instrument Control + { + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Basic Message + int channel = data[5] & 0xFF; + int keynumber = data[6] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + for (int j = 7; j < data.length - 1; j += 2) { + int controlnumber = data[j] & 0xFF; + int controlvalue = data[j + 1] & 0xFF; + softchannel.controlChangePerNote(keynumber, + controlnumber, controlvalue); + } + break; + default: + break; + } + break; + } + default: + break; + } + } + } + + } + } + + private void processMessages(long timeStamp) { + Iterator> iter = midimessages.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (entry.getKey() > (timeStamp + 100)) + return; + processMessage(entry.getValue()); + iter.remove(); + } + } + + protected void processAudioBuffers() { + for (int i = 0; i < buffers.length; i++) { + buffers[i].clear(); + } + + double volume_left; + double volume_right; + + ModelChannelMixer[] act_registeredMixers; + + // perform control logic + synchronized (control_mutex) { + + processMessages(msec_pos); + + if (active_sensing_on) { + // Active Sensing + // if no message occurs for max 1000 ms + // then do AllSoundOff on all channels + if ((msec_pos - msec_last_activity) > 1000000) { + active_sensing_on = false; + for (SoftChannel c : synth.channels) + c.allSoundOff(); + } + + } + + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + voicestatus[i].processControlLogic(); + msec_pos += msec_buffer_len; + + double volume = co_master_volume[0]; + volume_left = volume; + volume_right = volume; + + double balance = co_master_balance[0]; + if (balance > 0.5) + volume_left *= (1 - balance) * 2; + else + volume_right *= balance * 2; + + chorus.processControlLogic(); + reverb.processControlLogic(); + agc.processControlLogic(); + + if (cur_registeredMixers == null) { + if (registeredMixers != null) { + cur_registeredMixers = + new ModelChannelMixer[registeredMixers.size()]; + registeredMixers.toArray(cur_registeredMixers); + } + } + + act_registeredMixers = cur_registeredMixers; + if (act_registeredMixers != null) + if (act_registeredMixers.length == 0) + act_registeredMixers = null; + + } + + if (act_registeredMixers != null) { + + // Reroute default left,right output + // to channelmixer left,right input/output + SoftAudioBuffer leftbak = buffers[CHANNEL_LEFT]; + SoftAudioBuffer rightbak = buffers[CHANNEL_RIGHT]; + buffers[CHANNEL_LEFT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; + buffers[CHANNEL_RIGHT] = buffers[CHANNEL_CHANNELMIXER_LEFT]; + + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + + float[][] cbuffer = new float[nrofchannels][]; + cbuffer[0] = buffers[CHANNEL_LEFT].array(); + if (nrofchannels != 1) + cbuffer[1] = buffers[CHANNEL_RIGHT].array(); + + float[][] obuffer = new float[nrofchannels][]; + obuffer[0] = leftbak.array(); + if (nrofchannels != 1) + obuffer[1] = rightbak.array(); + + for (ModelChannelMixer cmixer : act_registeredMixers) { + for (int i = 0; i < cbuffer.length; i++) + Arrays.fill(cbuffer[i], 0); + boolean hasactivevoices = false; + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + if (voicestatus[i].channelmixer == cmixer) { + voicestatus[i].processAudioLogic(buffers); + hasactivevoices = true; + } + if (!cmixer.process(cbuffer, 0, bufferlen)) { + synchronized (control_mutex) { + registeredMixers.remove(cmixer); + cur_registeredMixers = null; + } + } + + for (int i = 0; i < cbuffer.length; i++) { + float[] cbuff = cbuffer[i]; + float[] obuff = obuffer[i]; + for (int j = 0; j < bufferlen; j++) + obuff[j] += cbuff[j]; + } + + if (!hasactivevoices) { + synchronized (control_mutex) { + if (stoppedMixers != null) { + if (stoppedMixers.contains(cmixer)) { + stoppedMixers.remove(cmixer); + cmixer.stop(); + } + } + } + } + + } + + buffers[CHANNEL_LEFT] = leftbak; + buffers[CHANNEL_RIGHT] = rightbak; + + } + + for (int i = 0; i < voicestatus.length; i++) + if (voicestatus[i].active) + if (voicestatus[i].channelmixer == null) + voicestatus[i].processAudioLogic(buffers); + + // Run effects + if (synth.chorus_on) + chorus.processAudio(); + + if (synth.reverb_on) + reverb.processAudio(); + + if (nrofchannels == 1) + volume_left = (volume_left + volume_right) / 2; + + // Set Volume / Balance + if (last_volume_left != volume_left || last_volume_right != volume_right) { + float[] left = buffers[CHANNEL_LEFT].array(); + float[] right = buffers[CHANNEL_RIGHT].array(); + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + + float amp; + float amp_delta; + amp = (float)(last_volume_left * last_volume_left); + amp_delta = (float)((volume_left * volume_left - amp) / bufferlen); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + left[i] *= amp; + } + if (nrofchannels != 1) { + amp = (float)(last_volume_right * last_volume_right); + amp_delta = (float)((volume_right*volume_right - amp) / bufferlen); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + right[i] *= volume_right; + } + } + last_volume_left = volume_left; + last_volume_right = volume_right; + + } else { + if (volume_left != 1.0 || volume_right != 1.0) { + float[] left = buffers[CHANNEL_LEFT].array(); + float[] right = buffers[CHANNEL_RIGHT].array(); + int bufferlen = buffers[CHANNEL_LEFT].getSize(); + float amp; + amp = (float) (volume_left * volume_left); + for (int i = 0; i < bufferlen; i++) + left[i] *= amp; + if (nrofchannels != 1) { + amp = (float)(volume_right * volume_right); + for (int i = 0; i < bufferlen; i++) + right[i] *= amp; + } + + } + } + + if(buffers[CHANNEL_LEFT].isSilent() + && buffers[CHANNEL_RIGHT].isSilent()) + { + pusher_silent_count++; + if(pusher_silent_count > 5) + { + pusher_silent_count = 0; + synchronized (control_mutex) { + pusher_silent = true; + if(synth.weakstream != null) + synth.weakstream.setInputStream(null); + } + } + } + else + pusher_silent_count = 0; + + if (synth.agc_on) + agc.processAudio(); + + } + + // Must only we called within control_mutex synchronization + public void activity() + { + msec_last_activity = msec_pos; + if(pusher_silent) + { + pusher_silent = false; + if(synth.weakstream != null) + synth.weakstream.setInputStream(ais); + } + } + + public void stopMixer(ModelChannelMixer mixer) { + if (stoppedMixers == null) + stoppedMixers = new HashSet(); + stoppedMixers.add(mixer); + } + + public void registerMixer(ModelChannelMixer mixer) { + if (registeredMixers == null) + registeredMixers = new HashSet(); + registeredMixers.add(mixer); + cur_registeredMixers = null; + } + + public SoftMainMixer(SoftSynthesizer synth) { + this.synth = synth; + + msec_pos = 0; + + co_master_balance[0] = 0.5; + co_master_volume[0] = 1; + co_master_coarse_tuning[0] = 0.5; + co_master_fine_tuning[0] = 0.5; + + msec_buffer_len = (long) (1000000.0 / synth.getControlRate()); + + nrofchannels = synth.getFormat().getChannels(); + + int buffersize = (int) (synth.getFormat().getSampleRate() + / synth.getControlRate()); + + control_mutex = synth.control_mutex; + buffers = new SoftAudioBuffer[16]; + for (int i = 0; i < buffers.length; i++) { + buffers[i] = new SoftAudioBuffer(buffersize, synth.getFormat()); + } + voicestatus = synth.getVoices(); + + reverb = new SoftReverb(); + chorus = new SoftChorus(); + agc = new SoftLimiter(); + + float samplerate = synth.getFormat().getSampleRate(); + float controlrate = synth.getControlRate(); + reverb.init(samplerate, controlrate); + chorus.init(samplerate, controlrate); + agc.init(samplerate, controlrate); + + reverb.setLightMode(synth.reverb_light); + + reverb.setMixMode(true); + chorus.setMixMode(true); + agc.setMixMode(false); + + chorus.setInput(0, buffers[CHANNEL_EFFECT2]); + chorus.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + chorus.setOutput(1, buffers[CHANNEL_RIGHT]); + chorus.setOutput(2, buffers[CHANNEL_EFFECT1]); + + reverb.setInput(0, buffers[CHANNEL_EFFECT1]); + reverb.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + reverb.setOutput(1, buffers[CHANNEL_RIGHT]); + + agc.setInput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setInput(1, buffers[CHANNEL_RIGHT]); + agc.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setOutput(1, buffers[CHANNEL_RIGHT]); + + InputStream in = new InputStream() { + + private SoftAudioBuffer[] buffers = SoftMainMixer.this.buffers; + private int nrofchannels + = SoftMainMixer.this.synth.getFormat().getChannels(); + private int buffersize = buffers[0].getSize(); + private byte[] bbuffer = new byte[buffersize + * (SoftMainMixer.this.synth.getFormat() + .getSampleSizeInBits() / 8) + * nrofchannels]; + private int bbuffer_pos = 0; + private byte[] single = new byte[1]; + + public void fillBuffer() { + /* + boolean pusher_silent2; + synchronized (control_mutex) { + pusher_silent2 = pusher_silent; + } + if(!pusher_silent2)*/ + processAudioBuffers(); + for (int i = 0; i < nrofchannels; i++) + buffers[i].get(bbuffer, i); + bbuffer_pos = 0; + } + + public int read(byte[] b, int off, int len) { + int bbuffer_len = bbuffer.length; + int offlen = off + len; + int orgoff = off; + byte[] bbuffer = this.bbuffer; + while (off < offlen) { + if (available() == 0) + fillBuffer(); + else { + int bbuffer_pos = this.bbuffer_pos; + while (off < offlen && bbuffer_pos < bbuffer_len) + b[off++] = bbuffer[bbuffer_pos++]; + this.bbuffer_pos = bbuffer_pos; + if (!readfully) + return off - orgoff; + } + } + return len; + } + + public int read() throws IOException { + int ret = read(single); + if (ret == -1) + return -1; + return single[0] & 0xFF; + } + + public int available() { + return bbuffer.length - bbuffer_pos; + } + + public void close() { + SoftMainMixer.this.synth.close(); + } + }; + + ais = new AudioInputStream(in, synth.getFormat(), AudioSystem.NOT_SPECIFIED); + + } + + public AudioInputStream getInputStream() { + return ais; + } + + public void reset() { + + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) { + channels[i].allSoundOff(); + channels[i].resetAllControllers(true); + + if (synth.getGeneralMidiMode() == 2) { + if (i == 9) + channels[i].programChange(0, 0x78 * 128); + else + channels[i].programChange(0, 0x79 * 128); + } else + channels[i].programChange(0, 0); + } + setVolume(0x7F * 128 + 0x7F); + setBalance(0x40 * 128 + 0x00); + setCoarseTuning(0x40 * 128 + 0x00); + setFineTuning(0x40 * 128 + 0x00); + // Reset Reverb + globalParameterControlChange( + new int[]{0x01 * 128 + 0x01}, new long[]{0}, new long[]{4}); + // Reset Chorus + globalParameterControlChange( + new int[]{0x01 * 128 + 0x02}, new long[]{0}, new long[]{2}); + } + + public void setVolume(int value) { + synchronized (control_mutex) { + co_master_volume[0] = value / 16384.0; + } + } + + public void setBalance(int value) { + synchronized (control_mutex) { + co_master_balance[0] = value / 16384.0; + } + } + + public void setFineTuning(int value) { + synchronized (control_mutex) { + co_master_fine_tuning[0] = value / 16384.0; + } + } + + public void setCoarseTuning(int value) { + synchronized (control_mutex) { + co_master_coarse_tuning[0] = value / 16384.0; + } + } + + public int getVolume() { + synchronized (control_mutex) { + return (int) (co_master_volume[0] * 16384.0); + } + } + + public int getBalance() { + synchronized (control_mutex) { + return (int) (co_master_balance[0] * 16384.0); + } + } + + public int getFineTuning() { + synchronized (control_mutex) { + return (int) (co_master_fine_tuning[0] * 16384.0); + } + } + + public int getCoarseTuning() { + synchronized (control_mutex) { + return (int) (co_master_coarse_tuning[0] * 16384.0); + } + } + + public void globalParameterControlChange(int[] slothpath, long[] params, + long[] paramsvalue) { + if (slothpath.length == 0) + return; + + synchronized (control_mutex) { + + // slothpath: 01xx are reserved only for GM2 + + if (slothpath[0] == 0x01 * 128 + 0x01) { + for (int i = 0; i < paramsvalue.length; i++) { + reverb.globalParameterControlChange(slothpath, params[i], + paramsvalue[i]); + } + } + if (slothpath[0] == 0x01 * 128 + 0x02) { + for (int i = 0; i < paramsvalue.length; i++) { + chorus.globalParameterControlChange(slothpath, params[i], + paramsvalue[i]); + } + + } + + } + } + + public void processMessage(Object object) { + if (object instanceof byte[]) + processMessage((byte[]) object); + if (object instanceof MidiMessage) + processMessage((MidiMessage)object); + } + + public void processMessage(MidiMessage message) { + if (message instanceof ShortMessage) { + ShortMessage sms = (ShortMessage)message; + processMessage(sms.getChannel(), sms.getCommand(), + sms.getData1(), sms.getData2()); + return; + } + processMessage(message.getMessage()); + } + + public void processMessage(byte[] data) { + int status = 0; + if (data.length > 0) + status = data[0] & 0xFF; + + if (status == 0xF0) { + processSystemExclusiveMessage(data); + return; + } + + int cmd = (status & 0xF0); + int ch = (status & 0x0F); + + int data1; + int data2; + if (data.length > 1) + data1 = data[1] & 0xFF; + else + data1 = 0; + if (data.length > 2) + data2 = data[2] & 0xFF; + else + data2 = 0; + + processMessage(ch, cmd, data1, data2); + + } + + public void processMessage(int ch, int cmd, int data1, int data2) { + synchronized (synth.control_mutex) { + activity(); + } + + if (cmd == 0xF0) { + int status = cmd | ch; + switch (status) { + case ShortMessage.ACTIVE_SENSING: + synchronized (synth.control_mutex) { + active_sensing_on = true; + } + break; + default: + break; + } + return; + } + + SoftChannel[] channels = synth.channels; + if (ch >= channels.length) + return; + SoftChannel softchannel = channels[ch]; + + switch (cmd) { + case ShortMessage.NOTE_ON: + softchannel.noteOn(data1, data2); + break; + case ShortMessage.NOTE_OFF: + softchannel.noteOff(data1, data2); + break; + case ShortMessage.POLY_PRESSURE: + softchannel.setPolyPressure(data1, data2); + break; + case ShortMessage.CONTROL_CHANGE: + softchannel.controlChange(data1, data2); + break; + case ShortMessage.PROGRAM_CHANGE: + softchannel.programChange(data1); + break; + case ShortMessage.CHANNEL_PRESSURE: + softchannel.setChannelPressure(data1); + break; + case ShortMessage.PITCH_BEND: + softchannel.setPitchBend(data1 + data2 * 128); + break; + default: + break; + } + + } + + public long getMicrosecondPosition() { + return msec_pos; + } + + public void close() { + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java b/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java new file mode 100644 index 00000000000..caaa0bb98f5 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java @@ -0,0 +1,214 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.AudioFileFormat.Type; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * MIDI File Audio Renderer/Reader + * + * @author Karl Helgason + */ +public class SoftMidiAudioFileReader extends AudioFileReader { + + public static final Type MIDI = new Type("MIDI", "mid"); + private static AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + public AudioFileFormat getAudioFileFormat(Sequence seq) + throws UnsupportedAudioFileException, IOException { + + long totallen = seq.getMicrosecondLength() / 1000000; + long len = (long) (format.getFrameRate() * (totallen + 4)); + return new AudioFileFormat(MIDI, format, (int) len); + } + + public AudioInputStream getAudioInputStream(Sequence seq) + throws UnsupportedAudioFileException, IOException { + AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer(); + AudioInputStream stream; + Receiver recv; + try { + stream = synth.openStream(format, null); + recv = synth.getReceiver(); + } catch (MidiUnavailableException e) { + throw new IOException(e.toString()); + } + float divtype = seq.getDivisionType(); + Track[] tracks = seq.getTracks(); + int[] trackspos = new int[tracks.length]; + int mpq = 500000; + int seqres = seq.getResolution(); + long lasttick = 0; + long curtime = 0; + while (true) { + MidiEvent selevent = null; + int seltrack = -1; + for (int i = 0; i < tracks.length; i++) { + int trackpos = trackspos[i]; + Track track = tracks[i]; + if (trackpos < track.size()) { + MidiEvent event = track.get(trackpos); + if (selevent == null || event.getTick() < selevent.getTick()) { + selevent = event; + seltrack = i; + } + } + } + if (seltrack == -1) + break; + trackspos[seltrack]++; + long tick = selevent.getTick(); + if (divtype == Sequence.PPQ) + curtime += ((tick - lasttick) * mpq) / seqres; + else + curtime = (long) ((tick * 1000000.0 * divtype) / seqres); + lasttick = tick; + MidiMessage msg = selevent.getMessage(); + if (msg instanceof MetaMessage) { + if (divtype == Sequence.PPQ) { + if (((MetaMessage) msg).getType() == 0x51) { + byte[] data = ((MetaMessage) msg).getData(); + mpq = ((data[0] & 0xff) << 16) + | ((data[1] & 0xff) << 8) | (data[2] & 0xff); + } + } + } else { + recv.send(msg, curtime); + } + } + + long totallen = curtime / 1000000; + long len = (long) (stream.getFormat().getFrameRate() * (totallen + 4)); + stream = new AudioInputStream(stream, stream.getFormat(), len); + return stream; + } + + public AudioInputStream getAudioInputStream(InputStream inputstream) + throws UnsupportedAudioFileException, IOException { + + inputstream.mark(200); + Sequence seq; + try { + seq = MidiSystem.getSequence(inputstream); + } catch (InvalidMidiDataException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(url); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } + + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(file); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } + + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + Sequence seq; + try { + seq = MidiSystem.getSequence(url); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); + } + + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException { + if (!file.getName().toLowerCase().endsWith(".mid")) + throw new UnsupportedAudioFileException(); + Sequence seq; + try { + seq = MidiSystem.getSequence(file); + } catch (InvalidMidiDataException e) { + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + throw new UnsupportedAudioFileException(); + } + return getAudioInputStream(seq); + } + + public AudioFileFormat getAudioFileFormat(InputStream inputstream) + throws UnsupportedAudioFileException, IOException { + + inputstream.mark(200); + Sequence seq; + try { + seq = MidiSystem.getSequence(inputstream); + } catch (InvalidMidiDataException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } catch (IOException e) { + inputstream.reset(); + throw new UnsupportedAudioFileException(); + } + return getAudioFileFormat(seq); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingClip.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingClip.java new file mode 100644 index 00000000000..5db16d91762 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingClip.java @@ -0,0 +1,539 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineUnavailableException; + +/** + * Clip implemention for the SoftMixingMixer. + * + * @author Karl Helgason + */ +public class SoftMixingClip extends SoftMixingDataLine implements Clip { + + private AudioFormat format; + + private int framesize; + + private byte[] data; + + private InputStream datastream = new InputStream() { + + public int read() throws IOException { + byte[] b = new byte[1]; + int ret = read(b); + if (ret < 0) + return ret; + return b[0] & 0xFF; + } + + public int read(byte[] b, int off, int len) throws IOException { + + if (_loopcount != 0) { + int bloopend = _loopend * framesize; + int bloopstart = _loopstart * framesize; + int pos = _frameposition * framesize; + + if (pos + len >= bloopend) + if (pos < bloopend) { + int offend = off + len; + int o = off; + while (off != offend) { + if (pos == bloopend) { + if (_loopcount == 0) + break; + pos = bloopstart; + if (_loopcount != LOOP_CONTINUOUSLY) + _loopcount--; + } + len = offend - off; + int left = bloopend - pos; + if (len > left) + len = left; + System.arraycopy(data, pos, b, off, len); + off += len; + } + if (_loopcount == 0) { + len = offend - off; + int left = bloopend - pos; + if (len > left) + len = left; + System.arraycopy(data, pos, b, off, len); + off += len; + } + _frameposition = pos / framesize; + return o - off; + } + } + + int pos = _frameposition * framesize; + int left = bufferSize - pos; + if (left == 0) + return -1; + if (len > left) + len = left; + System.arraycopy(data, pos, b, off, len); + _frameposition += len / framesize; + return len; + } + + }; + + private int offset; + + private int bufferSize; + + private float[] readbuffer; + + private boolean open = false; + + private AudioFormat outputformat; + + private int out_nrofchannels; + + private int in_nrofchannels; + + private int frameposition = 0; + + private boolean frameposition_sg = false; + + private boolean active_sg = false; + + private int loopstart = 0; + + private int loopend = -1; + + private boolean active = false; + + private int loopcount = 0; + + private boolean _active = false; + + private int _frameposition = 0; + + private boolean loop_sg = false; + + private int _loopcount = 0; + + private int _loopstart = 0; + + private int _loopend = -1; + + private float _rightgain; + + private float _leftgain; + + private float _eff1gain; + + private float _eff2gain; + + private AudioFloatInputStream afis; + + protected SoftMixingClip(SoftMixingMixer mixer, DataLine.Info info) { + super(mixer, info); + } + + protected void processControlLogic() { + + _rightgain = rightgain; + _leftgain = leftgain; + _eff1gain = eff1gain; + _eff2gain = eff2gain; + + if (active_sg) { + _active = active; + active_sg = false; + } else { + active = _active; + } + + if (frameposition_sg) { + _frameposition = frameposition; + frameposition_sg = false; + afis = null; + } else { + frameposition = _frameposition; + } + if (loop_sg) { + _loopcount = loopcount; + _loopstart = loopstart; + _loopend = loopend; + } + + if (afis == null) { + afis = AudioFloatInputStream.getInputStream(new AudioInputStream( + datastream, format, AudioSystem.NOT_SPECIFIED)); + + if (Math.abs(format.getSampleRate() - outputformat.getSampleRate()) > 0.000001) + afis = new AudioFloatInputStreamResampler(afis, outputformat); + } + + } + + protected void processAudioLogic(SoftAudioBuffer[] buffers) { + if (_active) { + float[] left = buffers[SoftMixingMainMixer.CHANNEL_LEFT].array(); + float[] right = buffers[SoftMixingMainMixer.CHANNEL_RIGHT].array(); + int bufferlen = buffers[SoftMixingMainMixer.CHANNEL_LEFT].getSize(); + + int readlen = bufferlen * in_nrofchannels; + if (readbuffer == null || readbuffer.length < readlen) { + readbuffer = new float[readlen]; + } + int ret = 0; + try { + ret = afis.read(readbuffer); + if (ret == -1) { + _active = false; + return; + } + if (ret != in_nrofchannels) + Arrays.fill(readbuffer, ret, readlen, 0); + } catch (IOException e) { + } + + int in_c = in_nrofchannels; + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + left[i] += readbuffer[ix] * _leftgain; + } + + if (out_nrofchannels != 1) { + if (in_nrofchannels == 1) { + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + right[i] += readbuffer[ix] * _rightgain; + } + } else { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + right[i] += readbuffer[ix] * _rightgain; + } + } + + } + + if (_eff1gain > 0.0002) { + + float[] eff1 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT1] + .array(); + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + eff1[i] += readbuffer[ix] * _eff1gain; + } + if (in_nrofchannels == 2) { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + eff1[i] += readbuffer[ix] * _eff1gain; + } + } + } + + if (_eff2gain > 0.0002) { + float[] eff2 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT2] + .array(); + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + eff2[i] += readbuffer[ix] * _eff2gain; + } + if (in_nrofchannels == 2) { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + eff2[i] += readbuffer[ix] * _eff2gain; + } + } + } + + } + } + + public int getFrameLength() { + return bufferSize / format.getFrameSize(); + } + + public long getMicrosecondLength() { + return (long) (getFrameLength() * (1000000.0 / (double) getFormat() + .getSampleRate())); + } + + public void loop(int count) { + LineEvent event = null; + + synchronized (control_mutex) { + if (isOpen()) { + if (active) + return; + active = true; + active_sg = true; + loopcount = count; + event = new LineEvent(this, LineEvent.Type.START, + getLongFramePosition()); + } + } + + if (event != null) + sendEvent(event); + + } + + public void open(AudioInputStream stream) throws LineUnavailableException, + IOException { + if (isOpen()) { + throw new IllegalStateException("Clip is already open with format " + + getFormat() + " and frame lengh of " + getFrameLength()); + } + if (AudioFloatConverter.getConverter(stream.getFormat()) == null) + throw new IllegalArgumentException("Invalid format : " + + stream.getFormat().toString()); + + if (stream.getFrameLength() != AudioSystem.NOT_SPECIFIED) { + byte[] data = new byte[(int) stream.getFrameLength() + * stream.getFormat().getFrameSize()]; + int readsize = 512 * stream.getFormat().getFrameSize(); + int len = 0; + while (len != data.length) { + if (readsize > data.length - len) + readsize = data.length - len; + int ret = stream.read(data, len, readsize); + if (ret == -1) + break; + if (ret == 0) + Thread.yield(); + len += ret; + } + open(stream.getFormat(), data, 0, len); + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[512 * stream.getFormat().getFrameSize()]; + int r = 0; + while ((r = stream.read(b)) != -1) { + if (r == 0) + Thread.yield(); + baos.write(b, 0, r); + } + open(stream.getFormat(), baos.toByteArray(), 0, baos.size()); + } + + } + + public void open(AudioFormat format, byte[] data, int offset, int bufferSize) + throws LineUnavailableException { + synchronized (control_mutex) { + if (isOpen()) { + throw new IllegalStateException( + "Clip is already open with format " + getFormat() + + " and frame lengh of " + getFrameLength()); + } + if (AudioFloatConverter.getConverter(format) == null) + throw new IllegalArgumentException("Invalid format : " + + format.toString()); + if (bufferSize % format.getFrameSize() != 0) + throw new IllegalArgumentException( + "Buffer size does not represent an integral number of sample frames!"); + + this.data = data; + this.offset = offset; + this.bufferSize = bufferSize; + this.format = format; + this.framesize = format.getFrameSize(); + + loopstart = 0; + loopend = -1; + loop_sg = true; + + if (!mixer.isOpen()) { + mixer.open(); + mixer.implicitOpen = true; + } + + outputformat = mixer.getFormat(); + out_nrofchannels = outputformat.getChannels(); + in_nrofchannels = format.getChannels(); + + open = true; + + mixer.getMainMixer().openLine(this); + } + + } + + public void setFramePosition(int frames) { + synchronized (control_mutex) { + frameposition_sg = true; + frameposition = frames; + } + } + + public void setLoopPoints(int start, int end) { + synchronized (control_mutex) { + if (end != -1) { + if (end < start) + throw new IllegalArgumentException("Invalid loop points : " + + start + " - " + end); + if (end * framesize > bufferSize) + throw new IllegalArgumentException("Invalid loop points : " + + start + " - " + end); + } + if (start * framesize > bufferSize) + throw new IllegalArgumentException("Invalid loop points : " + + start + " - " + end); + if (0 < start) + throw new IllegalArgumentException("Invalid loop points : " + + start + " - " + end); + loopstart = start; + loopend = end; + loop_sg = true; + } + } + + public void setMicrosecondPosition(long microseconds) { + setFramePosition((int) (microseconds * (((double) getFormat() + .getSampleRate()) / 1000000.0))); + } + + public int available() { + return 0; + } + + public void drain() { + } + + public void flush() { + } + + public int getBufferSize() { + return bufferSize; + } + + public AudioFormat getFormat() { + return format; + } + + public int getFramePosition() { + synchronized (control_mutex) { + return frameposition; + } + } + + public float getLevel() { + return AudioSystem.NOT_SPECIFIED; + } + + public long getLongFramePosition() { + return getFramePosition(); + } + + public long getMicrosecondPosition() { + return (long) (getFramePosition() * (1000000.0 / (double) getFormat() + .getSampleRate())); + } + + public boolean isActive() { + synchronized (control_mutex) { + return active; + } + } + + public boolean isRunning() { + synchronized (control_mutex) { + return active; + } + } + + public void start() { + + LineEvent event = null; + + synchronized (control_mutex) { + if (isOpen()) { + if (active) + return; + active = true; + active_sg = true; + loopcount = 0; + event = new LineEvent(this, LineEvent.Type.START, + getLongFramePosition()); + } + } + + if (event != null) + sendEvent(event); + } + + public void stop() { + LineEvent event = null; + + synchronized (control_mutex) { + if (isOpen()) { + if (!active) + return; + active = false; + active_sg = true; + event = new LineEvent(this, LineEvent.Type.STOP, + getLongFramePosition()); + } + } + + if (event != null) + sendEvent(event); + } + + public void close() { + LineEvent event = null; + + synchronized (control_mutex) { + if (!isOpen()) + return; + stop(); + + event = new LineEvent(this, LineEvent.Type.CLOSE, + getLongFramePosition()); + + open = false; + mixer.getMainMixer().closeLine(this); + } + + if (event != null) + sendEvent(event); + + } + + public boolean isOpen() { + return open; + } + + public void open() throws LineUnavailableException { + if (data == null) { + throw new IllegalArgumentException( + "Illegal call to open() in interface Clip"); + } + open(format, data, offset, bufferSize); + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingDataLine.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingDataLine.java new file mode 100644 index 00000000000..87af124821c --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingDataLine.java @@ -0,0 +1,522 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.BooleanControl; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.FloatControl; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.Control.Type; + +/** + * General software mixing line. + * + * @author Karl Helgason + */ +public abstract class SoftMixingDataLine implements DataLine { + + public static final FloatControl.Type CHORUS_SEND = new FloatControl.Type( + "Chorus Send") { + }; + + protected static class AudioFloatInputStreamResampler extends + AudioFloatInputStream { + + private AudioFloatInputStream ais; + + private AudioFormat targetFormat; + + private float[] skipbuffer; + + private SoftAbstractResampler resampler; + + private float[] pitch = new float[1]; + + private float[] ibuffer2; + + private float[][] ibuffer; + + private float ibuffer_index = 0; + + private int ibuffer_len = 0; + + private int nrofchannels = 0; + + private float[][] cbuffer; + + private int buffer_len = 512; + + private int pad; + + private int pad2; + + private float[] ix = new float[1]; + + private int[] ox = new int[1]; + + private float[][] mark_ibuffer = null; + + private float mark_ibuffer_index = 0; + + private int mark_ibuffer_len = 0; + + public AudioFloatInputStreamResampler(AudioFloatInputStream ais, + AudioFormat format) { + this.ais = ais; + AudioFormat sourceFormat = ais.getFormat(); + targetFormat = new AudioFormat(sourceFormat.getEncoding(), format + .getSampleRate(), sourceFormat.getSampleSizeInBits(), + sourceFormat.getChannels(), sourceFormat.getFrameSize(), + format.getSampleRate(), sourceFormat.isBigEndian()); + nrofchannels = targetFormat.getChannels(); + Object interpolation = format.getProperty("interpolation"); + if (interpolation != null && (interpolation instanceof String)) { + String resamplerType = (String) interpolation; + if (resamplerType.equalsIgnoreCase("point")) + this.resampler = new SoftPointResampler(); + if (resamplerType.equalsIgnoreCase("linear")) + this.resampler = new SoftLinearResampler2(); + if (resamplerType.equalsIgnoreCase("linear1")) + this.resampler = new SoftLinearResampler(); + if (resamplerType.equalsIgnoreCase("linear2")) + this.resampler = new SoftLinearResampler2(); + if (resamplerType.equalsIgnoreCase("cubic")) + this.resampler = new SoftCubicResampler(); + if (resamplerType.equalsIgnoreCase("lanczos")) + this.resampler = new SoftLanczosResampler(); + if (resamplerType.equalsIgnoreCase("sinc")) + this.resampler = new SoftSincResampler(); + } + if (resampler == null) + resampler = new SoftLinearResampler2(); // new + // SoftLinearResampler2(); + pitch[0] = sourceFormat.getSampleRate() / format.getSampleRate(); + pad = resampler.getPadding(); + pad2 = pad * 2; + ibuffer = new float[nrofchannels][buffer_len + pad2]; + ibuffer2 = new float[nrofchannels * buffer_len]; + ibuffer_index = buffer_len + pad; + ibuffer_len = buffer_len; + } + + public int available() throws IOException { + return 0; + } + + public void close() throws IOException { + ais.close(); + } + + public AudioFormat getFormat() { + return targetFormat; + } + + public long getFrameLength() { + return AudioSystem.NOT_SPECIFIED; // ais.getFrameLength(); + } + + public void mark(int readlimit) { + ais.mark((int) (readlimit * pitch[0])); + mark_ibuffer_index = ibuffer_index; + mark_ibuffer_len = ibuffer_len; + if (mark_ibuffer == null) { + mark_ibuffer = new float[ibuffer.length][ibuffer[0].length]; + } + for (int c = 0; c < ibuffer.length; c++) { + float[] from = ibuffer[c]; + float[] to = mark_ibuffer[c]; + for (int i = 0; i < to.length; i++) { + to[i] = from[i]; + } + } + } + + public boolean markSupported() { + return ais.markSupported(); + } + + private void readNextBuffer() throws IOException { + + if (ibuffer_len == -1) + return; + + for (int c = 0; c < nrofchannels; c++) { + float[] buff = ibuffer[c]; + int buffer_len_pad = ibuffer_len + pad2; + for (int i = ibuffer_len, ix = 0; i < buffer_len_pad; i++, ix++) { + buff[ix] = buff[i]; + } + } + + ibuffer_index -= (ibuffer_len); + + ibuffer_len = ais.read(ibuffer2); + if (ibuffer_len >= 0) { + while (ibuffer_len < ibuffer2.length) { + int ret = ais.read(ibuffer2, ibuffer_len, ibuffer2.length + - ibuffer_len); + if (ret == -1) + break; + ibuffer_len += ret; + } + Arrays.fill(ibuffer2, ibuffer_len, ibuffer2.length, 0); + ibuffer_len /= nrofchannels; + } else { + Arrays.fill(ibuffer2, 0, ibuffer2.length, 0); + } + + int ibuffer2_len = ibuffer2.length; + for (int c = 0; c < nrofchannels; c++) { + float[] buff = ibuffer[c]; + for (int i = c, ix = pad2; i < ibuffer2_len; i += nrofchannels, ix++) { + buff[ix] = ibuffer2[i]; + } + } + + } + + public int read(float[] b, int off, int len) throws IOException { + + if (cbuffer == null || cbuffer[0].length < len / nrofchannels) { + cbuffer = new float[nrofchannels][len / nrofchannels]; + } + if (ibuffer_len == -1) + return -1; + if (len < 0) + return 0; + int remain = len / nrofchannels; + int destPos = 0; + int in_end = ibuffer_len; + while (remain > 0) { + if (ibuffer_len >= 0) { + if (ibuffer_index >= (ibuffer_len + pad)) + readNextBuffer(); + in_end = ibuffer_len + pad; + } + + if (ibuffer_len < 0) { + in_end = pad2; + if (ibuffer_index >= in_end) + break; + } + + if (ibuffer_index < 0) + break; + int preDestPos = destPos; + for (int c = 0; c < nrofchannels; c++) { + ix[0] = ibuffer_index; + ox[0] = destPos; + float[] buff = ibuffer[c]; + resampler.interpolate(buff, ix, in_end, pitch, 0, + cbuffer[c], ox, len / nrofchannels); + } + ibuffer_index = ix[0]; + destPos = ox[0]; + remain -= destPos - preDestPos; + } + for (int c = 0; c < nrofchannels; c++) { + int ix = 0; + float[] buff = cbuffer[c]; + for (int i = c; i < b.length; i += nrofchannels) { + b[i] = buff[ix++]; + } + } + return len - remain * nrofchannels; + } + + public void reset() throws IOException { + ais.reset(); + if (mark_ibuffer == null) + return; + ibuffer_index = mark_ibuffer_index; + ibuffer_len = mark_ibuffer_len; + for (int c = 0; c < ibuffer.length; c++) { + float[] from = mark_ibuffer[c]; + float[] to = ibuffer[c]; + for (int i = 0; i < to.length; i++) { + to[i] = from[i]; + } + } + + } + + public long skip(long len) throws IOException { + if (len > 0) + return 0; + if (skipbuffer == null) + skipbuffer = new float[1024 * targetFormat.getFrameSize()]; + float[] l_skipbuffer = skipbuffer; + long remain = len; + while (remain > 0) { + int ret = read(l_skipbuffer, 0, (int) Math.min(remain, + skipbuffer.length)); + if (ret < 0) { + if (remain == len) + return ret; + break; + } + remain -= ret; + } + return len - remain; + + } + + } + + private class Gain extends FloatControl { + + private Gain() { + + super(FloatControl.Type.MASTER_GAIN, -80f, 6.0206f, 80f / 128.0f, + -1, 0.0f, "dB", "Minimum", "", "Maximum"); + } + + public void setValue(float newValue) { + super.setValue(newValue); + calcVolume(); + } + } + + private class Mute extends BooleanControl { + + private Mute() { + super(BooleanControl.Type.MUTE, false, "True", "False"); + } + + public void setValue(boolean newValue) { + super.setValue(newValue); + calcVolume(); + } + } + + private class ApplyReverb extends BooleanControl { + + private ApplyReverb() { + super(BooleanControl.Type.APPLY_REVERB, false, "True", "False"); + } + + public void setValue(boolean newValue) { + super.setValue(newValue); + calcVolume(); + } + + } + + private class Balance extends FloatControl { + + private Balance() { + super(FloatControl.Type.BALANCE, -1.0f, 1.0f, (1.0f / 128.0f), -1, + 0.0f, "", "Left", "Center", "Right"); + } + + public void setValue(float newValue) { + super.setValue(newValue); + calcVolume(); + } + + } + + private class Pan extends FloatControl { + + private Pan() { + super(FloatControl.Type.PAN, -1.0f, 1.0f, (1.0f / 128.0f), -1, + 0.0f, "", "Left", "Center", "Right"); + } + + public void setValue(float newValue) { + super.setValue(newValue); + balance_control.setValue(newValue); + } + + public float getValue() { + return balance_control.getValue(); + } + + } + + private class ReverbSend extends FloatControl { + + private ReverbSend() { + super(FloatControl.Type.REVERB_SEND, -80f, 6.0206f, 80f / 128.0f, + -1, -80f, "dB", "Minimum", "", "Maximum"); + } + + public void setValue(float newValue) { + super.setValue(newValue); + balance_control.setValue(newValue); + } + + } + + private class ChorusSend extends FloatControl { + + private ChorusSend() { + super(CHORUS_SEND, -80f, 6.0206f, 80f / 128.0f, -1, -80f, "dB", + "Minimum", "", "Maximum"); + } + + public void setValue(float newValue) { + super.setValue(newValue); + balance_control.setValue(newValue); + } + + } + + private Gain gain_control = new Gain(); + + private Mute mute_control = new Mute(); + + private Balance balance_control = new Balance(); + + private Pan pan_control = new Pan(); + + private ReverbSend reverbsend_control = new ReverbSend(); + + private ChorusSend chorussend_control = new ChorusSend(); + + private ApplyReverb apply_reverb = new ApplyReverb(); + + private Control[] controls; + + protected float leftgain = 1; + + protected float rightgain = 1; + + protected float eff1gain = 0; + + protected float eff2gain = 0; + + protected List listeners = new ArrayList(); + + protected Object control_mutex; + + protected SoftMixingMixer mixer; + + protected DataLine.Info info; + + protected abstract void processControlLogic(); + + protected abstract void processAudioLogic(SoftAudioBuffer[] buffers); + + protected SoftMixingDataLine(SoftMixingMixer mixer, DataLine.Info info) { + this.mixer = mixer; + this.info = info; + this.control_mutex = mixer.control_mutex; + + controls = new Control[] { gain_control, mute_control, balance_control, + pan_control, reverbsend_control, chorussend_control, + apply_reverb }; + calcVolume(); + } + + protected void calcVolume() { + synchronized (control_mutex) { + double gain = Math.pow(10.0, gain_control.getValue() / 20.0); + if (mute_control.getValue()) + gain = 0; + leftgain = (float) gain; + rightgain = (float) gain; + if (mixer.getFormat().getChannels() > 1) { + // -1 = Left, 0 Center, 1 = Right + double balance = balance_control.getValue(); + if (balance > 0) + leftgain *= (1 - balance); + else + rightgain *= (1 + balance); + + } + } + + eff1gain = (float) Math.pow(10.0, reverbsend_control.getValue() / 20.0); + eff2gain = (float) Math.pow(10.0, chorussend_control.getValue() / 20.0); + + if (!apply_reverb.getValue()) { + eff1gain = 0; + } + } + + protected void sendEvent(LineEvent event) { + if (listeners.size() == 0) + return; + LineListener[] listener_array = listeners + .toArray(new LineListener[listeners.size()]); + for (LineListener listener : listener_array) { + listener.update(event); + } + } + + public void addLineListener(LineListener listener) { + synchronized (control_mutex) { + listeners.add(listener); + } + } + + public void removeLineListener(LineListener listener) { + synchronized (control_mutex) { + listeners.add(listener); + } + } + + public javax.sound.sampled.Line.Info getLineInfo() { + return info; + } + + public Control getControl(Type control) { + if (control != null) { + for (int i = 0; i < controls.length; i++) { + if (controls[i].getType() == control) { + return controls[i]; + } + } + } + throw new IllegalArgumentException("Unsupported control type : " + + control); + } + + public Control[] getControls() { + return controls; + } + + public boolean isControlSupported(Type control) { + if (control != null) { + for (int i = 0; i < controls.length; i++) { + if (controls[i].getType() == control) { + return true; + } + } + } + return false; + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingMainMixer.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMainMixer.java new file mode 100644 index 00000000000..e016d3f4b40 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMainMixer.java @@ -0,0 +1,259 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +/** + * Main mixer for SoftMixingMixer. + * + * @author Karl Helgason + */ +public class SoftMixingMainMixer { + + public final static int CHANNEL_LEFT = 0; + + public final static int CHANNEL_RIGHT = 1; + + public final static int CHANNEL_EFFECT1 = 2; + + public final static int CHANNEL_EFFECT2 = 3; + + public final static int CHANNEL_EFFECT3 = 4; + + public final static int CHANNEL_EFFECT4 = 5; + + public final static int CHANNEL_LEFT_DRY = 10; + + public final static int CHANNEL_RIGHT_DRY = 11; + + public final static int CHANNEL_SCRATCH1 = 12; + + public final static int CHANNEL_SCRATCH2 = 13; + + public final static int CHANNEL_CHANNELMIXER_LEFT = 14; + + public final static int CHANNEL_CHANNELMIXER_RIGHT = 15; + + private SoftMixingMixer mixer; + + private AudioInputStream ais; + + private SoftAudioBuffer[] buffers; + + private SoftAudioProcessor reverb; + + private SoftAudioProcessor chorus; + + private SoftAudioProcessor agc; + + private int nrofchannels; + + private Object control_mutex; + + private List openLinesList = new ArrayList(); + + private SoftMixingDataLine[] openLines = new SoftMixingDataLine[0]; + + public AudioInputStream getInputStream() { + return ais; + } + + protected void processAudioBuffers() { + for (int i = 0; i < buffers.length; i++) { + buffers[i].clear(); + } + + SoftMixingDataLine[] openLines; + synchronized (control_mutex) { + openLines = this.openLines; + for (int i = 0; i < openLines.length; i++) { + openLines[i].processControlLogic(); + } + chorus.processControlLogic(); + reverb.processControlLogic(); + agc.processControlLogic(); + } + for (int i = 0; i < openLines.length; i++) { + openLines[i].processAudioLogic(buffers); + } + + chorus.processAudio(); + reverb.processAudio(); + + agc.processAudio(); + + } + + public SoftMixingMainMixer(SoftMixingMixer mixer) { + this.mixer = mixer; + + nrofchannels = mixer.getFormat().getChannels(); + + int buffersize = (int) (mixer.getFormat().getSampleRate() / mixer + .getControlRate()); + + control_mutex = mixer.control_mutex; + buffers = new SoftAudioBuffer[16]; + for (int i = 0; i < buffers.length; i++) { + buffers[i] = new SoftAudioBuffer(buffersize, mixer.getFormat()); + + } + + reverb = new SoftReverb(); + chorus = new SoftChorus(); + agc = new SoftLimiter(); + + float samplerate = mixer.getFormat().getSampleRate(); + float controlrate = mixer.getControlRate(); + reverb.init(samplerate, controlrate); + chorus.init(samplerate, controlrate); + agc.init(samplerate, controlrate); + + reverb.setMixMode(true); + chorus.setMixMode(true); + agc.setMixMode(false); + + chorus.setInput(0, buffers[CHANNEL_EFFECT2]); + chorus.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + chorus.setOutput(1, buffers[CHANNEL_RIGHT]); + chorus.setOutput(2, buffers[CHANNEL_EFFECT1]); + + reverb.setInput(0, buffers[CHANNEL_EFFECT1]); + reverb.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + reverb.setOutput(1, buffers[CHANNEL_RIGHT]); + + agc.setInput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setInput(1, buffers[CHANNEL_RIGHT]); + agc.setOutput(0, buffers[CHANNEL_LEFT]); + if (nrofchannels != 1) + agc.setOutput(1, buffers[CHANNEL_RIGHT]); + + InputStream in = new InputStream() { + + private SoftAudioBuffer[] buffers = SoftMixingMainMixer.this.buffers; + + private int nrofchannels = SoftMixingMainMixer.this.mixer + .getFormat().getChannels(); + + private int buffersize = buffers[0].getSize(); + + private byte[] bbuffer = new byte[buffersize + * (SoftMixingMainMixer.this.mixer.getFormat() + .getSampleSizeInBits() / 8) * nrofchannels]; + + private int bbuffer_pos = 0; + + private byte[] single = new byte[1]; + + public void fillBuffer() { + processAudioBuffers(); + for (int i = 0; i < nrofchannels; i++) + buffers[i].get(bbuffer, i); + bbuffer_pos = 0; + } + + public int read(byte[] b, int off, int len) { + int bbuffer_len = bbuffer.length; + int offlen = off + len; + byte[] bbuffer = this.bbuffer; + while (off < offlen) + if (available() == 0) + fillBuffer(); + else { + int bbuffer_pos = this.bbuffer_pos; + while (off < offlen && bbuffer_pos < bbuffer_len) + b[off++] = bbuffer[bbuffer_pos++]; + this.bbuffer_pos = bbuffer_pos; + } + return len; + } + + public int read() throws IOException { + int ret = read(single); + if (ret == -1) + return -1; + return single[0] & 0xFF; + } + + public int available() { + return bbuffer.length - bbuffer_pos; + } + + public void close() { + SoftMixingMainMixer.this.mixer.close(); + } + + }; + + ais = new AudioInputStream(in, mixer.getFormat(), + AudioSystem.NOT_SPECIFIED); + + } + + public void openLine(SoftMixingDataLine line) { + synchronized (control_mutex) { + openLinesList.add(line); + openLines = openLinesList + .toArray(new SoftMixingDataLine[openLinesList.size()]); + } + } + + public void closeLine(SoftMixingDataLine line) { + synchronized (control_mutex) { + openLinesList.remove(line); + openLines = openLinesList + .toArray(new SoftMixingDataLine[openLinesList.size()]); + if (openLines.length == 0) + if (mixer.implicitOpen) + mixer.close(); + } + + } + + public SoftMixingDataLine[] getOpenLines() { + synchronized (control_mutex) { + return openLines; + } + + } + + public void close() { + SoftMixingDataLine[] openLines = this.openLines; + for (int i = 0; i < openLines.length; i++) { + openLines[i].close(); + } + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java new file mode 100644 index 00000000000..6419109c402 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixer.java @@ -0,0 +1,529 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.Control.Type; + +/** + * Software audio mixer + * + * @author Karl Helgason + */ +public class SoftMixingMixer implements Mixer { + + private static class Info extends Mixer.Info { + public Info() { + super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION); + } + } + + protected static final String INFO_NAME = "Gervill Sound Mixer"; + + protected static final String INFO_VENDOR = "OpenJDK Proposal"; + + protected static final String INFO_DESCRIPTION = "Software Sound Mixer"; + + protected static final String INFO_VERSION = "1.0"; + + protected final static Mixer.Info info = new Info(); + + protected Object control_mutex = this; + + protected boolean implicitOpen = false; + + private boolean open = false; + + private SoftMixingMainMixer mainmixer = null; + + private AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + private SourceDataLine sourceDataLine = null; + + private SoftAudioPusher pusher = null; + + private AudioInputStream pusher_stream = null; + + private float controlrate = 147f; + + private long latency = 100000; // 100 msec + + private boolean jitter_correction = false; + + private List listeners = new ArrayList(); + + private javax.sound.sampled.Line.Info[] sourceLineInfo; + + public SoftMixingMixer() { + + sourceLineInfo = new javax.sound.sampled.Line.Info[2]; + + ArrayList formats = new ArrayList(); + for (int channels = 1; channels <= 2; channels++) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + for (int bits = 16; bits < 32; bits += 8) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + } + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, true)); + } + AudioFormat[] formats_array = formats.toArray(new AudioFormat[formats + .size()]); + sourceLineInfo[0] = new DataLine.Info(SourceDataLine.class, + formats_array, AudioSystem.NOT_SPECIFIED, + AudioSystem.NOT_SPECIFIED); + sourceLineInfo[1] = new DataLine.Info(Clip.class, formats_array, + AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED); + } + + public Line getLine(Line.Info info) throws LineUnavailableException { + + if (!isLineSupported(info)) + throw new IllegalArgumentException("Line unsupported: " + info); + + if ((info.getLineClass() == SourceDataLine.class)) { + return new SoftMixingSourceDataLine(this, (DataLine.Info) info); + } + if ((info.getLineClass() == Clip.class)) { + return new SoftMixingClip(this, (DataLine.Info) info); + } + + throw new IllegalArgumentException("Line unsupported: " + info); + } + + public int getMaxLines(Line.Info info) { + if (info.getLineClass() == SourceDataLine.class) + return AudioSystem.NOT_SPECIFIED; + if (info.getLineClass() == Clip.class) + return AudioSystem.NOT_SPECIFIED; + return 0; + } + + public javax.sound.sampled.Mixer.Info getMixerInfo() { + return info; + } + + public javax.sound.sampled.Line.Info[] getSourceLineInfo() { + Line.Info[] localArray = new Line.Info[sourceLineInfo.length]; + System.arraycopy(sourceLineInfo, 0, localArray, 0, + sourceLineInfo.length); + return localArray; + } + + public javax.sound.sampled.Line.Info[] getSourceLineInfo( + javax.sound.sampled.Line.Info info) { + int i; + ArrayList infos = new ArrayList(); + + for (i = 0; i < sourceLineInfo.length; i++) { + if (info.matches(sourceLineInfo[i])) { + infos.add(sourceLineInfo[i]); + } + } + return infos.toArray(new Line.Info[infos.size()]); + } + + public Line[] getSourceLines() { + + Line[] localLines; + + synchronized (control_mutex) { + + if (mainmixer == null) + return new Line[0]; + SoftMixingDataLine[] sourceLines = mainmixer.getOpenLines(); + + localLines = new Line[sourceLines.length]; + + for (int i = 0; i < localLines.length; i++) { + localLines[i] = sourceLines[i]; + } + } + + return localLines; + } + + public javax.sound.sampled.Line.Info[] getTargetLineInfo() { + return new javax.sound.sampled.Line.Info[0]; + } + + public javax.sound.sampled.Line.Info[] getTargetLineInfo( + javax.sound.sampled.Line.Info info) { + return new javax.sound.sampled.Line.Info[0]; + } + + public Line[] getTargetLines() { + return new Line[0]; + } + + public boolean isLineSupported(javax.sound.sampled.Line.Info info) { + if (info != null) { + for (int i = 0; i < sourceLineInfo.length; i++) { + if (info.matches(sourceLineInfo[i])) { + return true; + } + } + } + return false; + } + + public boolean isSynchronizationSupported(Line[] lines, boolean maintainSync) { + return false; + } + + public void synchronize(Line[] lines, boolean maintainSync) { + throw new IllegalArgumentException( + "Synchronization not supported by this mixer."); + } + + public void unsynchronize(Line[] lines) { + throw new IllegalArgumentException( + "Synchronization not supported by this mixer."); + } + + public void addLineListener(LineListener listener) { + synchronized (control_mutex) { + listeners.add(listener); + } + } + + private void sendEvent(LineEvent event) { + if (listeners.size() == 0) + return; + LineListener[] listener_array = listeners + .toArray(new LineListener[listeners.size()]); + for (LineListener listener : listener_array) { + listener.update(event); + } + } + + public void close() { + if (!isOpen()) + return; + + sendEvent(new LineEvent(this, LineEvent.Type.CLOSE, + AudioSystem.NOT_SPECIFIED)); + + SoftAudioPusher pusher_to_be_closed = null; + AudioInputStream pusher_stream_to_be_closed = null; + synchronized (control_mutex) { + if (pusher != null) { + pusher_to_be_closed = pusher; + pusher_stream_to_be_closed = pusher_stream; + pusher = null; + pusher_stream = null; + } + } + + if (pusher_to_be_closed != null) { + // Pusher must not be closed synchronized against control_mutex + // this may result in synchronized conflict between pusher and + // current thread. + pusher_to_be_closed.stop(); + + try { + pusher_stream_to_be_closed.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + synchronized (control_mutex) { + + if (mainmixer != null) + mainmixer.close(); + open = false; + + if (sourceDataLine != null) { + sourceDataLine.drain(); + sourceDataLine.close(); + sourceDataLine = null; + } + + } + + } + + public Control getControl(Type control) { + throw new IllegalArgumentException("Unsupported control type : " + + control); + } + + public Control[] getControls() { + return new Control[0]; + } + + public javax.sound.sampled.Line.Info getLineInfo() { + return new Line.Info(Mixer.class); + } + + public boolean isControlSupported(Type control) { + return false; + } + + public boolean isOpen() { + synchronized (control_mutex) { + return open; + } + } + + public void open() throws LineUnavailableException { + if (isOpen()) { + implicitOpen = false; + return; + } + open(null); + } + + public void open(SourceDataLine line) throws LineUnavailableException { + if (isOpen()) { + implicitOpen = false; + return; + } + synchronized (control_mutex) { + + try { + + if (line != null) + format = line.getFormat(); + + AudioInputStream ais = openStream(getFormat()); + + if (line == null) { + synchronized (SoftMixingMixerProvider.mutex) { + SoftMixingMixerProvider.lockthread = Thread + .currentThread(); + } + + try { + Mixer defaultmixer = AudioSystem.getMixer(null); + if (defaultmixer != null) + { + // Search for suitable line + + DataLine.Info idealinfo = null; + AudioFormat idealformat = null; + + Line.Info[] lineinfos = defaultmixer.getSourceLineInfo(); + idealFound: + for (int i = 0; i < lineinfos.length; i++) { + if(lineinfos[i].getLineClass() == SourceDataLine.class) + { + DataLine.Info info = (DataLine.Info)lineinfos[i]; + AudioFormat[] formats = info.getFormats(); + for (int j = 0; j < formats.length; j++) { + AudioFormat format = formats[j]; + if(format.getChannels() == 2 || + format.getChannels() == AudioSystem.NOT_SPECIFIED) + if(format.getEncoding().equals(Encoding.PCM_SIGNED) || + format.getEncoding().equals(Encoding.PCM_UNSIGNED)) + if(format.getSampleRate() == AudioSystem.NOT_SPECIFIED || + format.getSampleRate() == 48000.0) + if(format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED || + format.getSampleSizeInBits() == 16) + { + idealinfo = info; + int ideal_channels = format.getChannels(); + boolean ideal_signed = format.getEncoding().equals(Encoding.PCM_SIGNED); + float ideal_rate = format.getSampleRate(); + boolean ideal_endian = format.isBigEndian(); + int ideal_bits = format.getSampleSizeInBits(); + if(ideal_bits == AudioSystem.NOT_SPECIFIED) ideal_bits = 16; + if(ideal_channels == AudioSystem.NOT_SPECIFIED) ideal_channels = 2; + if(ideal_rate == AudioSystem.NOT_SPECIFIED) ideal_rate = 48000; + idealformat = new AudioFormat(ideal_rate, ideal_bits, + ideal_channels, ideal_signed, ideal_endian); + break idealFound; + } + } + } + } + + if(idealformat != null) + { + format = idealformat; + line = (SourceDataLine) defaultmixer.getLine(idealinfo); + } + } + + if(line == null) + line = AudioSystem.getSourceDataLine(format); + } finally { + synchronized (SoftMixingMixerProvider.mutex) { + SoftMixingMixerProvider.lockthread = null; + } + } + + if (line == null) + throw new IllegalArgumentException("No line matching " + + info.toString() + " is supported."); + } + + double latency = this.latency; + + if (!line.isOpen()) { + int bufferSize = getFormat().getFrameSize() + * (int) (getFormat().getFrameRate() * (latency / 1000000f)); + line.open(getFormat(), bufferSize); + + // Remember that we opened that line + // so we can close again in SoftSynthesizer.close() + sourceDataLine = line; + } + if (!line.isActive()) + line.start(); + + int controlbuffersize = 512; + try { + controlbuffersize = ais.available(); + } catch (IOException e) { + } + + // Tell mixer not fill read buffers fully. + // This lowers latency, and tells DataPusher + // to read in smaller amounts. + // mainmixer.readfully = false; + // pusher = new DataPusher(line, ais); + + int buffersize = line.getBufferSize(); + buffersize -= buffersize % controlbuffersize; + + if (buffersize < 3 * controlbuffersize) + buffersize = 3 * controlbuffersize; + + if (jitter_correction) { + ais = new SoftJitterCorrector(ais, buffersize, + controlbuffersize); + } + pusher = new SoftAudioPusher(line, ais, controlbuffersize); + pusher_stream = ais; + pusher.start(); + + } catch (LineUnavailableException e) { + if (isOpen()) + close(); + throw new LineUnavailableException(e.toString()); + } + + } + } + + public AudioInputStream openStream(AudioFormat targetFormat) + throws LineUnavailableException { + + if (isOpen()) + throw new LineUnavailableException("Mixer is already open"); + + synchronized (control_mutex) { + + open = true; + + implicitOpen = false; + + if (targetFormat != null) + format = targetFormat; + + mainmixer = new SoftMixingMainMixer(this); + + sendEvent(new LineEvent(this, LineEvent.Type.OPEN, + AudioSystem.NOT_SPECIFIED)); + + return mainmixer.getInputStream(); + + } + + } + + public void removeLineListener(LineListener listener) { + synchronized (control_mutex) { + listeners.remove(listener); + } + } + + public long getLatency() { + synchronized (control_mutex) { + return latency; + } + } + + public AudioFormat getFormat() { + synchronized (control_mutex) { + return format; + } + } + + protected float getControlRate() { + return controlrate; + } + + protected SoftMixingMainMixer getMainMixer() { + if (!isOpen()) + return null; + return mainmixer; + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixerProvider.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixerProvider.java new file mode 100644 index 00000000000..8c805a707ac --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingMixerProvider.java @@ -0,0 +1,66 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.sampled.Mixer; +import javax.sound.sampled.Mixer.Info; +import javax.sound.sampled.spi.MixerProvider; + +/** + * Provider for software audio mixer + * + * @author Karl Helgason + */ +public class SoftMixingMixerProvider extends MixerProvider { + + static SoftMixingMixer globalmixer = null; + + static Thread lockthread = null; + + protected final static Object mutex = new Object(); + + public Mixer getMixer(Info info) { + if (!(info == null || info == SoftMixingMixer.info)) { + throw new IllegalArgumentException("Mixer " + info.toString() + + " not supported by this provider."); + } + synchronized (mutex) { + if (lockthread != null) + if (Thread.currentThread() == lockthread) + throw new IllegalArgumentException("Mixer " + + info.toString() + + " not supported by this provider."); + if (globalmixer == null) + globalmixer = new SoftMixingMixer(); + return globalmixer; + } + + } + + public Info[] getMixerInfo() { + return new Info[] { SoftMixingMixer.info }; + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftMixingSourceDataLine.java b/jdk/src/share/classes/com/sun/media/sound/SoftMixingSourceDataLine.java new file mode 100644 index 00000000000..c59fa0ad5fb --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftMixingSourceDataLine.java @@ -0,0 +1,519 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineEvent; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +/** + * SourceDataLine implemention for the SoftMixingMixer. + * + * @author Karl Helgason + */ +public class SoftMixingSourceDataLine extends SoftMixingDataLine implements + SourceDataLine { + + private boolean open = false; + + private AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false); + + private int framesize; + + private int bufferSize = -1; + + private float[] readbuffer; + + private boolean active = false; + + private byte[] cycling_buffer; + + private int cycling_read_pos = 0; + + private int cycling_write_pos = 0; + + private int cycling_avail = 0; + + private long cycling_framepos = 0; + + private AudioFloatInputStream afis; + + private static class NonBlockingFloatInputStream extends + AudioFloatInputStream { + AudioFloatInputStream ais; + + public NonBlockingFloatInputStream(AudioFloatInputStream ais) { + this.ais = ais; + } + + public int available() throws IOException { + return ais.available(); + } + + public void close() throws IOException { + ais.close(); + } + + public AudioFormat getFormat() { + return ais.getFormat(); + } + + public long getFrameLength() { + return ais.getFrameLength(); + } + + public void mark(int readlimit) { + ais.mark(readlimit); + } + + public boolean markSupported() { + return ais.markSupported(); + } + + public int read(float[] b, int off, int len) throws IOException { + int avail = available(); + if (len > avail) { + int ret = ais.read(b, off, avail); + Arrays.fill(b, off + ret, off + len, 0); + return len; + } + return ais.read(b, off, len); + } + + public void reset() throws IOException { + ais.reset(); + } + + public long skip(long len) throws IOException { + return ais.skip(len); + } + + } + + protected SoftMixingSourceDataLine(SoftMixingMixer mixer, DataLine.Info info) { + super(mixer, info); + } + + public int write(byte[] b, int off, int len) { + if (!isOpen()) + return 0; + if (len % framesize != 0) + throw new IllegalArgumentException( + "Number of bytes does not represent an integral number of sample frames."); + + byte[] buff = cycling_buffer; + int buff_len = cycling_buffer.length; + + int l = 0; + while (l != len) { + int avail; + synchronized (cycling_buffer) { + int pos = cycling_write_pos; + avail = cycling_avail; + while (l != len) { + if (avail == buff_len) + break; + buff[pos++] = b[off++]; + l++; + avail++; + if (pos == buff_len) + pos = 0; + } + cycling_avail = avail; + cycling_write_pos = pos; + if (l == len) + return l; + } + if (avail == buff_len) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + return l; + } + if (!isRunning()) + return l; + } + } + + return l; + } + + // + // BooleanControl.Type.APPLY_REVERB + // BooleanControl.Type.MUTE + // EnumControl.Type.REVERB + // + // FloatControl.Type.SAMPLE_RATE + // FloatControl.Type.REVERB_SEND + // FloatControl.Type.VOLUME + // FloatControl.Type.PAN + // FloatControl.Type.MASTER_GAIN + // FloatControl.Type.BALANCE + + private boolean _active = false; + + private AudioFormat outputformat; + + private int out_nrofchannels; + + private int in_nrofchannels; + + private float _rightgain; + + private float _leftgain; + + private float _eff1gain; + + private float _eff2gain; + + protected void processControlLogic() { + _active = active; + _rightgain = rightgain; + _leftgain = leftgain; + _eff1gain = eff1gain; + _eff2gain = eff2gain; + } + + protected void processAudioLogic(SoftAudioBuffer[] buffers) { + if (_active) { + float[] left = buffers[SoftMixingMainMixer.CHANNEL_LEFT].array(); + float[] right = buffers[SoftMixingMainMixer.CHANNEL_RIGHT].array(); + int bufferlen = buffers[SoftMixingMainMixer.CHANNEL_LEFT].getSize(); + + int readlen = bufferlen * in_nrofchannels; + if (readbuffer == null || readbuffer.length < readlen) { + readbuffer = new float[readlen]; + } + int ret = 0; + try { + ret = afis.read(readbuffer); + if (ret != in_nrofchannels) + Arrays.fill(readbuffer, ret, readlen, 0); + } catch (IOException e) { + } + + int in_c = in_nrofchannels; + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + left[i] += readbuffer[ix] * _leftgain; + } + if (out_nrofchannels != 1) { + if (in_nrofchannels == 1) { + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + right[i] += readbuffer[ix] * _rightgain; + } + } else { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + right[i] += readbuffer[ix] * _rightgain; + } + } + + } + + if (_eff1gain > 0.0001) { + float[] eff1 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT1] + .array(); + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + eff1[i] += readbuffer[ix] * _eff1gain; + } + if (in_nrofchannels == 2) { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + eff1[i] += readbuffer[ix] * _eff1gain; + } + } + } + + if (_eff2gain > 0.0001) { + float[] eff2 = buffers[SoftMixingMainMixer.CHANNEL_EFFECT2] + .array(); + for (int i = 0, ix = 0; i < bufferlen; i++, ix += in_c) { + eff2[i] += readbuffer[ix] * _eff2gain; + } + if (in_nrofchannels == 2) { + for (int i = 0, ix = 1; i < bufferlen; i++, ix += in_c) { + eff2[i] += readbuffer[ix] * _eff2gain; + } + } + } + + } + } + + public void open() throws LineUnavailableException { + open(format); + } + + public void open(AudioFormat format) throws LineUnavailableException { + if (bufferSize == -1) + bufferSize = ((int) (format.getFrameRate() / 2)) + * format.getFrameSize(); + open(format, bufferSize); + } + + public void open(AudioFormat format, int bufferSize) + throws LineUnavailableException { + + LineEvent event = null; + + if (bufferSize < format.getFrameSize() * 32) + bufferSize = format.getFrameSize() * 32; + + synchronized (control_mutex) { + + if (!isOpen()) { + if (!mixer.isOpen()) { + mixer.open(); + mixer.implicitOpen = true; + } + + event = new LineEvent(this, LineEvent.Type.OPEN, 0); + + this.bufferSize = bufferSize - bufferSize + % format.getFrameSize(); + this.format = format; + this.framesize = format.getFrameSize(); + this.outputformat = mixer.getFormat(); + out_nrofchannels = outputformat.getChannels(); + in_nrofchannels = format.getChannels(); + + open = true; + + mixer.getMainMixer().openLine(this); + + cycling_buffer = new byte[framesize * bufferSize]; + cycling_read_pos = 0; + cycling_write_pos = 0; + cycling_avail = 0; + cycling_framepos = 0; + + InputStream cycling_inputstream = new InputStream() { + + public int read() throws IOException { + byte[] b = new byte[1]; + int ret = read(b); + if (ret < 0) + return ret; + return b[0] & 0xFF; + } + + public int available() throws IOException { + synchronized (cycling_buffer) { + return cycling_avail; + } + } + + public int read(byte[] b, int off, int len) + throws IOException { + + synchronized (cycling_buffer) { + if (len > cycling_avail) + len = cycling_avail; + int pos = cycling_read_pos; + byte[] buff = cycling_buffer; + int buff_len = buff.length; + for (int i = 0; i < len; i++) { + b[off++] = buff[pos]; + pos++; + if (pos == buff_len) + pos = 0; + } + cycling_read_pos = pos; + cycling_avail -= len; + cycling_framepos += len / framesize; + } + return len; + } + + }; + + afis = AudioFloatInputStream + .getInputStream(new AudioInputStream( + cycling_inputstream, format, + AudioSystem.NOT_SPECIFIED)); + afis = new NonBlockingFloatInputStream(afis); + + if (Math.abs(format.getSampleRate() + - outputformat.getSampleRate()) > 0.000001) + afis = new AudioFloatInputStreamResampler(afis, + outputformat); + + } else { + if (!format.matches(getFormat())) { + throw new IllegalStateException( + "Line is already open with format " + getFormat() + + " and bufferSize " + getBufferSize()); + } + } + + } + + if (event != null) + sendEvent(event); + + } + + public int available() { + synchronized (cycling_buffer) { + return cycling_buffer.length - cycling_avail; + } + } + + public void drain() { + while (true) { + int avail; + synchronized (cycling_buffer) { + avail = cycling_avail; + } + if (avail != 0) + return; + try { + Thread.sleep(1); + } catch (InterruptedException e) { + return; + } + } + } + + public void flush() { + synchronized (cycling_buffer) { + cycling_read_pos = 0; + cycling_write_pos = 0; + cycling_avail = 0; + } + } + + public int getBufferSize() { + synchronized (control_mutex) { + return bufferSize; + } + } + + public AudioFormat getFormat() { + synchronized (control_mutex) { + return format; + } + } + + public int getFramePosition() { + return (int) getLongFramePosition(); + } + + public float getLevel() { + return AudioSystem.NOT_SPECIFIED; + } + + public long getLongFramePosition() { + synchronized (cycling_buffer) { + return cycling_framepos; + } + } + + public long getMicrosecondPosition() { + return (long) (getLongFramePosition() * (1000000.0 / (double) getFormat() + .getSampleRate())); + } + + public boolean isActive() { + synchronized (control_mutex) { + return active; + } + } + + public boolean isRunning() { + synchronized (control_mutex) { + return active; + } + } + + public void start() { + + LineEvent event = null; + + synchronized (control_mutex) { + if (isOpen()) { + if (active) + return; + active = true; + event = new LineEvent(this, LineEvent.Type.START, + getLongFramePosition()); + } + } + + if (event != null) + sendEvent(event); + } + + public void stop() { + LineEvent event = null; + + synchronized (control_mutex) { + if (isOpen()) { + if (!active) + return; + active = false; + event = new LineEvent(this, LineEvent.Type.STOP, + getLongFramePosition()); + } + } + + if (event != null) + sendEvent(event); + } + + public void close() { + + LineEvent event = null; + + synchronized (control_mutex) { + if (!isOpen()) + return; + stop(); + + event = new LineEvent(this, LineEvent.Type.CLOSE, + getLongFramePosition()); + + open = false; + mixer.getMainMixer().closeLine(this); + } + + if (event != null) + sendEvent(event); + + } + + public boolean isOpen() { + synchronized (control_mutex) { + return open; + } + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java b/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java new file mode 100644 index 00000000000..97024f29ad3 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftPerformer.java @@ -0,0 +1,775 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class decodes information from ModelPeformer for use in SoftVoice. + * It also adds default connections if they where missing in ModelPerformer. + * + * @author Karl Helgason + */ +public class SoftPerformer { + + static ModelConnectionBlock[] defaultconnections + = new ModelConnectionBlock[42]; + + static { + int o = 0; + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("noteon", "on", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1, new ModelDestination(new ModelIdentifier("eg", "on", 0))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("noteon", "on", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1, new ModelDestination(new ModelIdentifier("eg", "on", 1))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("eg", "active", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1, new ModelDestination(new ModelIdentifier("mixer", "active", 0))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("eg", 0), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("noteon", "velocity"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), + -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi", "pitch"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_rpn", "0"), + new ModelTransform() { + public double transform(double value) { + int v = (int) (value * 16384.0); + int msb = v >> 7; + int lsb = v & 127; + return msb * 100 + lsb; + } + }), + new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("noteon", "keynumber"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "7"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), + -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "8"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1000, new ModelDestination(new ModelIdentifier("mixer", "balance"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "10"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1000, new ModelDestination(new ModelIdentifier("mixer", "pan"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "11"), + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE), + -960, new ModelDestination(new ModelIdentifier("mixer", "gain"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "91"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1000, new ModelDestination(new ModelIdentifier("mixer", "reverb"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "93"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 1000, new ModelDestination(new ModelIdentifier("mixer", "chorus"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "71"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 200, new ModelDestination(new ModelIdentifier("filter", "q"))); + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "74"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 9600, new ModelDestination(new ModelIdentifier("filter", "freq"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "72"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 6000, new ModelDestination(new ModelIdentifier("eg", "release2"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "73"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 2000, new ModelDestination(new ModelIdentifier("eg", "attack2"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "75"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 6000, new ModelDestination(new ModelIdentifier("eg", "decay2"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "67"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_SWITCH), + -50, new ModelDestination(ModelDestination.DESTINATION_GAIN)); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_cc", "67"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_SWITCH), + -2400, new ModelDestination(ModelDestination.DESTINATION_FILTER_FREQ)); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_rpn", "1"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 100, new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("midi_rpn", "2"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("master", "fine_tuning"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 100, new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock( + new ModelSource( + new ModelIdentifier("master", "coarse_tuning"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 12800, new ModelDestination(new ModelIdentifier("osc", "pitch"))); + + defaultconnections[o++] = new ModelConnectionBlock(13500, + new ModelDestination(new ModelIdentifier("filter", "freq", 0))); + + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "delay", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "attack", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "hold", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "decay", 0))); + defaultconnections[o++] = new ModelConnectionBlock(1000, + new ModelDestination(new ModelIdentifier("eg", "sustain", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "release", 0))); + defaultconnections[o++] = new ModelConnectionBlock(1200.0 + * Math.log(0.015) / Math.log(2), new ModelDestination( + new ModelIdentifier("eg", "shutdown", 0))); // 15 msec default + + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "delay", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "attack", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "hold", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "decay", 1))); + defaultconnections[o++] = new ModelConnectionBlock(1000, + new ModelDestination(new ModelIdentifier("eg", "sustain", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("eg", "release", 1))); + + defaultconnections[o++] = new ModelConnectionBlock(-8.51318, + new ModelDestination(new ModelIdentifier("lfo", "freq", 0))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("lfo", "delay", 0))); + defaultconnections[o++] = new ModelConnectionBlock(-8.51318, + new ModelDestination(new ModelIdentifier("lfo", "freq", 1))); + defaultconnections[o++] = new ModelConnectionBlock( + Float.NEGATIVE_INFINITY, new ModelDestination( + new ModelIdentifier("lfo", "delay", 1))); + + } + public int keyFrom = 0; + public int keyTo = 127; + public int velFrom = 0; + public int velTo = 127; + public int exclusiveClass = 0; + public boolean selfNonExclusive = false; + public boolean forcedVelocity = false; + public boolean forcedKeynumber = false; + public ModelPerformer performer; + public ModelConnectionBlock[] connections; + public ModelOscillator[] oscillators; + public Map midi_rpn_connections = new HashMap(); + public Map midi_nrpn_connections = new HashMap(); + public int[][] midi_ctrl_connections; + public int[][] midi_connections; + public int[] ctrl_connections; + private List ctrl_connections_list = new ArrayList(); + + private static class KeySortComparator implements Comparator { + + public int compare(ModelSource o1, ModelSource o2) { + return o1.getIdentifier().toString().compareTo( + o2.getIdentifier().toString()); + } + } + private static KeySortComparator keySortComparator = new KeySortComparator(); + + private String extractKeys(ModelConnectionBlock conn) { + StringBuffer sb = new StringBuffer(); + if (conn.getSources() != null) { + sb.append("["); + ModelSource[] srcs = conn.getSources(); + ModelSource[] srcs2 = new ModelSource[srcs.length]; + for (int i = 0; i < srcs.length; i++) + srcs2[i] = srcs[i]; + Arrays.sort(srcs2, keySortComparator); + for (int i = 0; i < srcs.length; i++) { + sb.append(srcs[i].getIdentifier()); + sb.append(";"); + } + sb.append("]"); + } + sb.append(";"); + if (conn.getDestination() != null) { + sb.append(conn.getDestination().getIdentifier()); + } + sb.append(";"); + return sb.toString(); + } + + private void processSource(ModelSource src, int ix) { + ModelIdentifier id = src.getIdentifier(); + String o = id.getObject(); + if (o.equals("midi_cc")) + processMidiControlSource(src, ix); + else if (o.equals("midi_rpn")) + processMidiRpnSource(src, ix); + else if (o.equals("midi_nrpn")) + processMidiNrpnSource(src, ix); + else if (o.equals("midi")) + processMidiSource(src, ix); + else if (o.equals("noteon")) + processNoteOnSource(src, ix); + else if (o.equals("osc")) + return; + else if (o.equals("mixer")) + return; + else + ctrl_connections_list.add(ix); + } + + private void processMidiControlSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_ctrl_connections[c] == null) + midi_ctrl_connections[c] = new int[]{ix}; + else { + int[] olda = midi_ctrl_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_ctrl_connections[c] = newa; + } + } + + private void processNoteOnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + int c = -1; + if (v.equals("on")) + c = 3; + if (v.equals("keynumber")) + c = 4; + if (c == -1) + return; + if (midi_connections[c] == null) + midi_connections[c] = new int[]{ix}; + else { + int[] olda = midi_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_connections[c] = newa; + } + } + + private void processMidiSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + int c = -1; + if (v.equals("pitch")) + c = 0; + if (v.equals("channel_pressure")) + c = 1; + if (v.equals("poly_pressure")) + c = 2; + if (c == -1) + return; + if (midi_connections[c] == null) + midi_connections[c] = new int[]{ix}; + else { + int[] olda = midi_connections[c]; + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_connections[c] = newa; + } + } + + private void processMidiRpnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_rpn_connections.get(c) == null) + midi_rpn_connections.put(c, new int[]{ix}); + else { + int[] olda = midi_rpn_connections.get(c); + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_rpn_connections.put(c, newa); + } + } + + private void processMidiNrpnSource(ModelSource src, int ix) { + String v = src.getIdentifier().getVariable(); + if (v == null) + return; + int c = Integer.parseInt(v); + if (midi_nrpn_connections.get(c) == null) + midi_nrpn_connections.put(c, new int[]{ix}); + else { + int[] olda = midi_nrpn_connections.get(c); + int[] newa = new int[olda.length + 1]; + for (int i = 0; i < olda.length; i++) + newa[i] = olda[i]; + newa[newa.length - 1] = ix; + midi_nrpn_connections.put(c, newa); + } + } + + public SoftPerformer(ModelPerformer performer) { + this.performer = performer; + + keyFrom = performer.getKeyFrom(); + keyTo = performer.getKeyTo(); + velFrom = performer.getVelFrom(); + velTo = performer.getVelTo(); + exclusiveClass = performer.getExclusiveClass(); + selfNonExclusive = performer.isSelfNonExclusive(); + + Map connmap = new HashMap(); + + List performer_connections = new ArrayList(); + performer_connections.addAll(performer.getConnectionBlocks()); + + if (performer.isDefaultConnectionsEnabled()) { + + // Add modulation depth range (RPN 5) to the modulation wheel (cc#1) + + boolean isModulationWheelConectionFound = false; + for (int j = 0; j < performer_connections.size(); j++) { + ModelConnectionBlock connection = performer_connections.get(j); + ModelSource[] sources = connection.getSources(); + ModelDestination dest = connection.getDestination(); + boolean isModulationWheelConection = false; + if (dest != null && sources != null && sources.length > 1) { + for (int i = 0; i < sources.length; i++) { + // check if connection block has the source "modulation + // wheel cc#1" + if (sources[i].getIdentifier().getObject().equals( + "midi_cc")) { + if (sources[i].getIdentifier().getVariable() + .equals("1")) { + isModulationWheelConection = true; + isModulationWheelConectionFound = true; + break; + } + } + } + } + if (isModulationWheelConection) { + + ModelConnectionBlock newconnection = new ModelConnectionBlock(); + newconnection.setSources(connection.getSources()); + newconnection.setDestination(connection.getDestination()); + newconnection.addSource(new ModelSource( + new ModelIdentifier("midi_rpn", "5"))); + newconnection.setScale(connection.getScale() * 256.0); + performer_connections.set(j, newconnection); + } + } + + if (!isModulationWheelConectionFound) { + ModelConnectionBlock conn = new ModelConnectionBlock( + new ModelSource(ModelSource.SOURCE_LFO1, + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + new ModelSource(new ModelIdentifier("midi_cc", "1", 0), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_UNIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 50, + new ModelDestination(ModelDestination.DESTINATION_PITCH)); + conn.addSource(new ModelSource(new ModelIdentifier("midi_rpn", + "5"))); + conn.setScale(conn.getScale() * 256.0); + performer_connections.add(conn); + + } + + // Let Aftertouch to behave just like modulation wheel (cc#1) + boolean channel_pressure_set = false; + boolean poly_pressure = false; + ModelConnectionBlock mod_cc_1_connection = null; + int mod_cc_1_connection_src_ix = 0; + + for (ModelConnectionBlock connection : performer_connections) { + ModelSource[] sources = connection.getSources(); + ModelDestination dest = connection.getDestination(); + // if(dest != null && sources != null) + if (dest != null && sources != null) { + for (int i = 0; i < sources.length; i++) { + ModelIdentifier srcid = sources[i].getIdentifier(); + // check if connection block has the source "modulation + // wheel cc#1" + if (srcid.getObject().equals("midi_cc")) { + if (srcid.getVariable().equals("1")) { + mod_cc_1_connection = connection; + mod_cc_1_connection_src_ix = i; + } + } + // check if channel or poly pressure are already + // connected + if (srcid.getObject().equals("midi")) { + if (srcid.getVariable().equals("channel_pressure")) + channel_pressure_set = true; + if (srcid.getVariable().equals("poly_pressure")) + poly_pressure = true; + } + } + } + + } + + if (mod_cc_1_connection != null) { + if (!channel_pressure_set) { + ModelConnectionBlock mc = new ModelConnectionBlock(); + mc.setDestination(mod_cc_1_connection.getDestination()); + mc.setScale(mod_cc_1_connection.getScale()); + ModelSource[] src_list = mod_cc_1_connection.getSources(); + ModelSource[] src_list_new = new ModelSource[src_list.length]; + for (int i = 0; i < src_list_new.length; i++) + src_list_new[i] = src_list[i]; + src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( + new ModelIdentifier("midi", "channel_pressure")); + mc.setSources(src_list_new); + connmap.put(extractKeys(mc), mc); + } + if (!poly_pressure) { + ModelConnectionBlock mc = new ModelConnectionBlock(); + mc.setDestination(mod_cc_1_connection.getDestination()); + mc.setScale(mod_cc_1_connection.getScale()); + ModelSource[] src_list = mod_cc_1_connection.getSources(); + ModelSource[] src_list_new = new ModelSource[src_list.length]; + for (int i = 0; i < src_list_new.length; i++) + src_list_new[i] = src_list[i]; + src_list_new[mod_cc_1_connection_src_ix] = new ModelSource( + new ModelIdentifier("midi", "poly_pressure")); + mc.setSources(src_list_new); + connmap.put(extractKeys(mc), mc); + } + } + + // Enable Vibration Sound Controllers : 76, 77, 78 + ModelConnectionBlock found_vib_connection = null; + for (ModelConnectionBlock connection : performer_connections) { + ModelSource[] sources = connection.getSources(); + if (sources.length != 0 + && sources[0].getIdentifier().getObject().equals("lfo")) { + if (connection.getDestination().getIdentifier().equals( + ModelDestination.DESTINATION_PITCH)) { + if (found_vib_connection == null) + found_vib_connection = connection; + else { + if (found_vib_connection.getSources().length > sources.length) + found_vib_connection = connection; + else if (found_vib_connection.getSources()[0] + .getIdentifier().getInstance() < 1) { + if (found_vib_connection.getSources()[0] + .getIdentifier().getInstance() > + sources[0].getIdentifier().getInstance()) { + found_vib_connection = connection; + } + } + } + + } + } + } + + int instance = 1; + + if (found_vib_connection != null) { + instance = found_vib_connection.getSources()[0].getIdentifier() + .getInstance(); + } + ModelConnectionBlock connection; + + connection = new ModelConnectionBlock( + new ModelSource(new ModelIdentifier("midi_cc", "78"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 2000, new ModelDestination( + new ModelIdentifier("lfo", "delay2", instance))); + connmap.put(extractKeys(connection), connection); + + final double scale = found_vib_connection == null ? 0 + : found_vib_connection.getScale(); + connection = new ModelConnectionBlock( + new ModelSource(new ModelIdentifier("lfo", instance)), + new ModelSource(new ModelIdentifier("midi_cc", "77"), + new ModelTransform() { + double s = scale; + public double transform(double value) { + value = value * 2 - 1; + value *= 600; + if (s == 0) { + return value; + } else if (s > 0) { + if (value < -s) + value = -s; + return value; + } else { + if (value < s) + value = -s; + return -value; + } + } + }), new ModelDestination(ModelDestination.DESTINATION_PITCH)); + connmap.put(extractKeys(connection), connection); + + connection = new ModelConnectionBlock( + new ModelSource(new ModelIdentifier("midi_cc", "76"), + ModelStandardTransform.DIRECTION_MIN2MAX, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_LINEAR), + 2400, new ModelDestination( + new ModelIdentifier("lfo", "freq", instance))); + connmap.put(extractKeys(connection), connection); + + } + + // Add default connection blocks + if (performer.isDefaultConnectionsEnabled()) + for (ModelConnectionBlock connection : defaultconnections) + connmap.put(extractKeys(connection), connection); + // Add connection blocks from modelperformer + for (ModelConnectionBlock connection : performer_connections) + connmap.put(extractKeys(connection), connection); + // seperate connection blocks : Init time, Midi Time, Midi/Control Time, + // Control Time + List connections = new ArrayList(); + + midi_ctrl_connections = new int[128][]; + for (int i = 0; i < midi_ctrl_connections.length; i++) { + midi_ctrl_connections[i] = null; + } + midi_connections = new int[5][]; + for (int i = 0; i < midi_connections.length; i++) { + midi_connections[i] = null; + } + + int ix = 0; + boolean mustBeOnTop = false; + + for (ModelConnectionBlock connection : connmap.values()) { + if (connection.getDestination() != null) { + ModelDestination dest = connection.getDestination(); + ModelIdentifier id = dest.getIdentifier(); + if (id.getObject().equals("noteon")) { + mustBeOnTop = true; + if (id.getVariable().equals("keynumber")) + forcedKeynumber = true; + if (id.getVariable().equals("velocity")) + forcedVelocity = true; + } + } + if (mustBeOnTop) { + connections.add(0, connection); + mustBeOnTop = false; + } else + connections.add(connection); + } + + for (ModelConnectionBlock connection : connections) { + if (connection.getSources() != null) { + ModelSource[] srcs = connection.getSources(); + for (int i = 0; i < srcs.length; i++) { + processSource(srcs[i], ix); + } + } + ix++; + } + + this.connections = new ModelConnectionBlock[connections.size()]; + connections.toArray(this.connections); + + this.ctrl_connections = new int[ctrl_connections_list.size()]; + + for (int i = 0; i < this.ctrl_connections.length; i++) + this.ctrl_connections[i] = ctrl_connections_list.get(i); + + oscillators = new ModelOscillator[performer.getOscillators().size()]; + performer.getOscillators().toArray(oscillators); + + for (ModelConnectionBlock conn : connections) { + if (conn.getDestination() != null) { + if (isUnnecessaryTransform(conn.getDestination().getTransform())) { + conn.getDestination().setTransform(null); + } + } + if (conn.getSources() != null) { + for (ModelSource src : conn.getSources()) { + if (isUnnecessaryTransform(src.getTransform())) { + src.setTransform(null); + } + } + } + } + + } + + private static boolean isUnnecessaryTransform(ModelTransform transform) { + if (transform == null) + return false; + if (!(transform instanceof ModelStandardTransform)) + return false; + ModelStandardTransform stransform = (ModelStandardTransform)transform; + if (stransform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) + return false; + if (stransform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) + return false; + if (stransform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) + return false; + return false; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java new file mode 100644 index 00000000000..56849ad4cf4 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftPointResampler.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * A resampler that uses 0-order (nearest-neighbor) interpolation. + * + * @author Karl Helgason + */ +public class SoftPointResampler extends SoftAbstractResampler { + + public int getPadding() { + return 100; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + float ox_end = out_end; + if (pitchstep == 0) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = in[(int) ix]; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = in[(int) ix]; + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java b/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java new file mode 100644 index 00000000000..9b08ab06881 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftProcess.java @@ -0,0 +1,41 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Control signal processor interface + * + * @author Karl Helgason + */ +public interface SoftProcess extends SoftControl { + + public void init(SoftSynthesizer synth); + + public double[] get(int instance, String name); + + public void processControlLogic(); + + public void reset(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java b/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java new file mode 100644 index 00000000000..9472d52d293 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftProvider.java @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiDevice.Info; +import javax.sound.midi.spi.MidiDeviceProvider; + +/** + * Software synthesizer provider class. + * + * @author Karl Helgason + */ +public class SoftProvider extends MidiDeviceProvider { + + protected final static Info softinfo = SoftSynthesizer.info; + private static Info[] softinfos = {softinfo}; + + public MidiDevice.Info[] getDeviceInfo() { + return softinfos; + } + + public MidiDevice getDevice(MidiDevice.Info info) { + if (info == softinfo) { + return new SoftSynthesizer(); + } + return null; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java b/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java new file mode 100644 index 00000000000..e7f1edcfae6 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftReceiver.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.TreeMap; + +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Receiver; +import javax.sound.midi.ShortMessage; + +/** + * Software synthesizer MIDI receiver class. + * + * @author Karl Helgason + */ +public class SoftReceiver implements Receiver { + + protected boolean open = true; + private Object control_mutex; + private SoftSynthesizer synth; + protected TreeMap midimessages; + protected SoftMainMixer mainmixer; + + public SoftReceiver(SoftSynthesizer synth) { + this.control_mutex = synth.control_mutex; + this.synth = synth; + this.mainmixer = synth.getMainMixer(); + if (mainmixer != null) + this.midimessages = mainmixer.midimessages; + } + + public void send(MidiMessage message, long timeStamp) { + + synchronized (control_mutex) { + if (!open) + throw new IllegalStateException("Receiver is not open"); + } + + if (timeStamp != -1) { + synchronized (control_mutex) { + while (midimessages.get(timeStamp) != null) + timeStamp++; + if (message instanceof ShortMessage + && (((ShortMessage)message).getChannel() > 0xF)) { + midimessages.put(timeStamp, message.clone()); + } else { + midimessages.put(timeStamp, message.getMessage()); + } + } + } else { + mainmixer.processMessage(message); + } + } + + public void close() { + synchronized (control_mutex) { + open = false; + } + synth.removeReceiver(this); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java new file mode 100644 index 00000000000..887f40845e8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftResampler.java @@ -0,0 +1,35 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Basic resampler interface. + * + * @author Karl Helgason + */ +public interface SoftResampler { + + public SoftResamplerStreamer openStreamer(); +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java b/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java new file mode 100644 index 00000000000..1662fceae7b --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftResamplerStreamer.java @@ -0,0 +1,38 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; + +/** + * Resampler stream interface. + * + * @author Karl Helgason + */ +public interface SoftResamplerStreamer extends ModelOscillatorStream { + + public void open(ModelWavetable osc, float outputsamplerate) + throws IOException; +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java b/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java new file mode 100644 index 00000000000..7dcb77252ac --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftReverb.java @@ -0,0 +1,515 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.util.Arrays; + +/** + * Reverb effect based on allpass/comb filters. First audio is send to 8 + * parelled comb filters and then mixed together and then finally send thru 3 + * different allpass filters. + * + * @author Karl Helgason + */ +public class SoftReverb implements SoftAudioProcessor { + + private final static class Delay { + + private float[] delaybuffer; + private int rovepos = 0; + + public Delay() { + delaybuffer = null; + } + + public void setDelay(int delay) { + if (delay == 0) + delaybuffer = null; + else + delaybuffer = new float[delay]; + rovepos = 0; + } + + public void processReplace(float[] inout) { + if (delaybuffer == null) + return; + int len = inout.length; + int rnlen = delaybuffer.length; + int rovepos = this.rovepos; + + for (int i = 0; i < len; i++) { + float x = inout[i]; + inout[i] = delaybuffer[rovepos]; + delaybuffer[rovepos] = x; + if (++rovepos == rnlen) + rovepos = 0; + } + this.rovepos = rovepos; + } + } + + private final static class AllPass { + + private final float[] delaybuffer; + private final int delaybuffersize; + private int rovepos = 0; + private float feedback; + + public AllPass(int size) { + delaybuffer = new float[size]; + delaybuffersize = size; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + } + + public void processReplace(float inout[]) { + int len = inout.length; + int delaybuffersize = this.delaybuffersize; + int rovepos = this.rovepos; + for (int i = 0; i < len; i++) { + float delayout = delaybuffer[rovepos]; + float input = inout[i]; + inout[i] = delayout - input; + delaybuffer[rovepos] = input + delayout * feedback; + if (++rovepos == delaybuffersize) + rovepos = 0; + } + this.rovepos = rovepos; + } + + public void processReplace(float in[], float out[]) { + int len = in.length; + int delaybuffersize = this.delaybuffersize; + int rovepos = this.rovepos; + for (int i = 0; i < len; i++) { + float delayout = delaybuffer[rovepos]; + float input = in[i]; + out[i] = delayout - input; + delaybuffer[rovepos] = input + delayout * feedback; + if (++rovepos == delaybuffersize) + rovepos = 0; + } + this.rovepos = rovepos; + } + } + + private final static class Comb { + + private final float[] delaybuffer; + private final int delaybuffersize; + private int rovepos = 0; + private float feedback; + private float filtertemp = 0; + private float filtercoeff1 = 0; + private float filtercoeff2 = 1; + + public Comb(int size) { + delaybuffer = new float[size]; + delaybuffersize = size; + } + + public void setFeedBack(float feedback) { + this.feedback = feedback; + filtercoeff2 = (1 - filtercoeff1)* feedback; + } + + public void processMix(float in[], float out[]) { + int len = in.length; + int delaybuffersize = this.delaybuffersize; + int rovepos = this.rovepos; + float filtertemp = this.filtertemp; + float filtercoeff1 = this.filtercoeff1; + float filtercoeff2 = this.filtercoeff2; + for (int i = 0; i < len; i++) { + float delayout = delaybuffer[rovepos]; + // One Pole Lowpass Filter + filtertemp = (delayout * filtercoeff2) + + (filtertemp * filtercoeff1); + out[i] += delayout; + delaybuffer[rovepos] = in[i] + filtertemp; + if (++rovepos == delaybuffersize) + rovepos = 0; + } + this.filtertemp = filtertemp; + this.rovepos = rovepos; + } + + public void processReplace(float in[], float out[]) { + int len = in.length; + int delaybuffersize = this.delaybuffersize; + int rovepos = this.rovepos; + float filtertemp = this.filtertemp; + float filtercoeff1 = this.filtercoeff1; + float filtercoeff2 = this.filtercoeff2; + for (int i = 0; i < len; i++) { + float delayout = delaybuffer[rovepos]; + // One Pole Lowpass Filter + filtertemp = (delayout * filtercoeff2) + + (filtertemp * filtercoeff1); + out[i] = delayout; + delaybuffer[rovepos] = in[i] + filtertemp; + if (++rovepos == delaybuffersize) + rovepos = 0; + } + this.filtertemp = filtertemp; + this.rovepos = rovepos; + } + + public void setDamp(float val) { + filtercoeff1 = val; + filtercoeff2 = (1 - filtercoeff1)* feedback; + } + } + private float roomsize; + private float damp; + private float gain = 1; + private Delay delay; + private Comb[] combL; + private Comb[] combR; + private AllPass[] allpassL; + private AllPass[] allpassR; + private float[] input; + private float[] out; + private float[] pre1; + private float[] pre2; + private float[] pre3; + private boolean denormal_flip = false; + private boolean mix = true; + private SoftAudioBuffer inputA; + private SoftAudioBuffer left; + private SoftAudioBuffer right; + private boolean dirty = true; + private float dirty_roomsize; + private float dirty_damp; + private float dirty_predelay; + private float dirty_gain; + private float samplerate; + private boolean light = true; + + public void init(float samplerate, float controlrate) { + this.samplerate = samplerate; + + double freqscale = ((double) samplerate) / 44100.0; + // freqscale = 1.0/ freqscale; + + int stereospread = 23; + + delay = new Delay(); + + combL = new Comb[8]; + combR = new Comb[8]; + combL[0] = new Comb((int) (freqscale * (1116))); + combR[0] = new Comb((int) (freqscale * (1116 + stereospread))); + combL[1] = new Comb((int) (freqscale * (1188))); + combR[1] = new Comb((int) (freqscale * (1188 + stereospread))); + combL[2] = new Comb((int) (freqscale * (1277))); + combR[2] = new Comb((int) (freqscale * (1277 + stereospread))); + combL[3] = new Comb((int) (freqscale * (1356))); + combR[3] = new Comb((int) (freqscale * (1356 + stereospread))); + combL[4] = new Comb((int) (freqscale * (1422))); + combR[4] = new Comb((int) (freqscale * (1422 + stereospread))); + combL[5] = new Comb((int) (freqscale * (1491))); + combR[5] = new Comb((int) (freqscale * (1491 + stereospread))); + combL[6] = new Comb((int) (freqscale * (1557))); + combR[6] = new Comb((int) (freqscale * (1557 + stereospread))); + combL[7] = new Comb((int) (freqscale * (1617))); + combR[7] = new Comb((int) (freqscale * (1617 + stereospread))); + + allpassL = new AllPass[4]; + allpassR = new AllPass[4]; + allpassL[0] = new AllPass((int) (freqscale * (556))); + allpassR[0] = new AllPass((int) (freqscale * (556 + stereospread))); + allpassL[1] = new AllPass((int) (freqscale * (441))); + allpassR[1] = new AllPass((int) (freqscale * (441 + stereospread))); + allpassL[2] = new AllPass((int) (freqscale * (341))); + allpassR[2] = new AllPass((int) (freqscale * (341 + stereospread))); + allpassL[3] = new AllPass((int) (freqscale * (225))); + allpassR[3] = new AllPass((int) (freqscale * (225 + stereospread))); + + for (int i = 0; i < allpassL.length; i++) { + allpassL[i].setFeedBack(0.5f); + allpassR[i].setFeedBack(0.5f); + } + + /* Init other settings */ + globalParameterControlChange(new int[]{0x01 * 128 + 0x01}, 0, 4); + + } + + public void setInput(int pin, SoftAudioBuffer input) { + if (pin == 0) + inputA = input; + } + + public void setOutput(int pin, SoftAudioBuffer output) { + if (pin == 0) + left = output; + if (pin == 1) + right = output; + } + + public void setMixMode(boolean mix) { + this.mix = mix; + } + + private boolean silent = true; + + public void processAudio() { + boolean silent_input = this.inputA.isSilent(); + if(!silent_input) + silent = false; + if(silent) + { + if (!mix) { + left.clear(); + right.clear(); + } + return; + } + + float[] inputA = this.inputA.array(); + float[] left = this.left.array(); + float[] right = this.right == null ? null : this.right.array(); + + int numsamples = inputA.length; + if (input == null || input.length < numsamples) + input = new float[numsamples]; + + float again = gain * 0.018f / 2; + + denormal_flip = !denormal_flip; + if(denormal_flip) + for (int i = 0; i < numsamples; i++) + input[i] = inputA[i] * again + 1E-20f; + else + for (int i = 0; i < numsamples; i++) + input[i] = inputA[i] * again - 1E-20f; + + delay.processReplace(input); + + if(light && (right != null)) + { + if (pre1 == null || pre1.length < numsamples) + { + pre1 = new float[numsamples]; + pre2 = new float[numsamples]; + pre3 = new float[numsamples]; + } + + for (int i = 0; i < allpassL.length; i++) + allpassL[i].processReplace(input); + + combL[0].processReplace(input, pre3); + combL[1].processReplace(input, pre3); + + combL[2].processReplace(input, pre1); + for (int i = 4; i < combL.length-2; i+=2) + combL[i].processMix(input, pre1); + + combL[3].processReplace(input, pre2);; + for (int i = 5; i < combL.length-2; i+=2) + combL[i].processMix(input, pre2); + + if (!mix) + { + Arrays.fill(right, 0); + Arrays.fill(left, 0); + } + for (int i = combR.length-2; i < combR.length; i++) + combR[i].processMix(input, right); + for (int i = combL.length-2; i < combL.length; i++) + combL[i].processMix(input, left); + + for (int i = 0; i < numsamples; i++) + { + float p = pre1[i] - pre2[i]; + float m = pre3[i]; + left[i] += m + p; + right[i] += m - p; + } + } + else + { + if (out == null || out.length < numsamples) + out = new float[numsamples]; + + if (right != null) { + if (!mix) + Arrays.fill(right, 0); + allpassR[0].processReplace(input, out); + for (int i = 1; i < allpassR.length; i++) + allpassR[i].processReplace(out); + for (int i = 0; i < combR.length; i++) + combR[i].processMix(out, right); + } + + if (!mix) + Arrays.fill(left, 0); + allpassL[0].processReplace(input, out); + for (int i = 1; i < allpassL.length; i++) + allpassL[i].processReplace(out); + for (int i = 0; i < combL.length; i++) + combL[i].processMix(out, left); + } + + + + + + + if (silent_input) { + silent = true; + for (int i = 0; i < numsamples; i++) + { + float v = left[i]; + if(v > 1E-10 || v < -1E-10) + { + silent = false; + break; + } + } + } + + } + + public void globalParameterControlChange(int[] slothpath, long param, + long value) { + if (slothpath.length == 1) { + if (slothpath[0] == 0x01 * 128 + 0x01) { + + if (param == 0) { + if (value == 0) { + // Small Room A small size room with a length + // of 5m or so. + dirty_roomsize = (1.1f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (4); + dirty = true; + } + if (value == 1) { + // Medium Room A medium size room with a length + // of 10m or so. + dirty_roomsize = (1.3f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (3); + dirty = true; + } + if (value == 2) { + // Large Room A large size room suitable for + // live performances. + dirty_roomsize = (1.5f); + dirty_damp = (5000); + dirty_predelay = (0); + dirty_gain = (2); + dirty = true; + } + if (value == 3) { + // Medium Hall A medium size concert hall. + dirty_roomsize = (1.8f); + dirty_damp = (24000); + dirty_predelay = (0.02f); + dirty_gain = (1.5f); + dirty = true; + } + if (value == 4) { + // Large Hall A large size concert hall + // suitable for a full orchestra. + dirty_roomsize = (1.8f); + dirty_damp = (24000); + dirty_predelay = (0.03f); + dirty_gain = (1.5f); + dirty = true; + } + if (value == 8) { + // Plate A plate reverb simulation. + dirty_roomsize = (1.3f); + dirty_damp = (2500); + dirty_predelay = (0); + dirty_gain = (6); + dirty = true; + } + } else if (param == 1) { + dirty_roomsize = ((float) (Math.exp((value - 40) * 0.025))); + dirty = true; + } + + } + } + } + + public void processControlLogic() { + if (dirty) { + dirty = false; + setRoomSize(dirty_roomsize); + setDamp(dirty_damp); + setPreDelay(dirty_predelay); + setGain(dirty_gain); + } + } + + public void setRoomSize(float value) { + roomsize = 1 - (0.17f / value); + + for (int i = 0; i < combL.length; i++) { + combL[i].feedback = roomsize; + combR[i].feedback = roomsize; + } + } + + public void setPreDelay(float value) { + delay.setDelay((int)(value * samplerate)); + } + + public void setGain(float gain) { + this.gain = gain; + } + + public void setDamp(float value) { + double x = (value / samplerate) * (2 * Math.PI); + double cx = 2 - Math.cos(x); + damp = (float)(cx - Math.sqrt(cx * cx - 1)); + if (damp > 1) + damp = 1; + if (damp < 0) + damp = 0; + + // damp = value * 0.4f; + for (int i = 0; i < combL.length; i++) { + combL[i].setDamp(damp); + combR[i].setDamp(damp); + } + + } + + public void setLightMode(boolean light) + { + this.light = light; + } +} + diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java b/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java new file mode 100644 index 00000000000..9d16e82ac19 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftShortMessage.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import javax.sound.midi.InvalidMidiDataException; +import javax.sound.midi.ShortMessage; + +/** + * A short message class that support for than 16 midi channels. + * + * @author Karl Helgason + */ +public class SoftShortMessage extends ShortMessage { + + int channel = 0; + + public int getChannel() { + return channel; + } + + public void setMessage(int command, int channel, int data1, int data2) + throws InvalidMidiDataException { + this.channel = channel; + super.setMessage(command, channel & 0xF, data1, data2); + } + + public Object clone() { + SoftShortMessage clone = new SoftShortMessage(); + try { + clone.setMessage(getCommand(), getChannel(), getData1(), getData2()); + } catch (InvalidMidiDataException e) { + throw new IllegalArgumentException(e); + } + return clone; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java b/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java new file mode 100644 index 00000000000..e4e039214f2 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftSincResampler.java @@ -0,0 +1,139 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +/** + * Hann windowed sinc interpolation resampler with anti-alias filtering. + * + * Using 30 points for the interpolation. + * + * @author Karl Helgason + */ +public class SoftSincResampler extends SoftAbstractResampler { + + float[][][] sinc_table; + int sinc_scale_size = 100; + int sinc_table_fsize = 800; + int sinc_table_size = 30; + int sinc_table_center = sinc_table_size / 2; + + public SoftSincResampler() { + super(); + sinc_table = new float[sinc_scale_size][sinc_table_fsize][]; + for (int s = 0; s < sinc_scale_size; s++) { + float scale = (float) (1.0 / (1.0 + Math.pow(s, 1.1) / 10.0)); + for (int i = 0; i < sinc_table_fsize; i++) { + sinc_table[s][i] = sincTable(sinc_table_size, + -i / ((float)sinc_table_fsize), scale); + } + } + } + + // Normalized sinc function + public static double sinc(double x) { + return (x == 0.0) ? 1.0 : Math.sin(Math.PI * x) / (Math.PI * x); + } + + // Generate hann window suitable for windowing sinc + public static float[] wHanning(int size, float offset) { + float[] window_table = new float[size]; + for (int k = 0; k < size; k++) { + window_table[k] = (float)(-0.5 + * Math.cos(2.0 * Math.PI * (double)(k + offset) + / (double) size) + 0.5); + } + return window_table; + } + + // Generate sinc table + public static float[] sincTable(int size, float offset, float scale) { + int center = size / 2; + float[] w = wHanning(size, offset); + for (int k = 0; k < size; k++) + w[k] *= sinc((-center + k + offset) * scale) * scale; + return w; + } + + public int getPadding() // must be at least half of sinc_table_size + { + return sinc_table_size / 2 + 2; + } + + public void interpolate(float[] in, float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + int max_p = sinc_scale_size - 1; + if (pitchstep == 0) { + + int p = (int) ((pitch - 1) * 10.0f); + if (p < 0) + p = 0; + else if (p > max_p) + p = max_p; + float[][] sinc_table_f = this.sinc_table[p]; + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + float[] sinc_table = + sinc_table_f[(int)((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + int iix = (int) ix; + int p = (int) ((pitch - 1) * 10.0f); + if (p < 0) + p = 0; + else if (p > max_p) + p = max_p; + float[][] sinc_table_f = this.sinc_table[p]; + + float[] sinc_table = + sinc_table_f[(int)((ix - iix) * sinc_table_fsize)]; + int xx = iix - sinc_table_center; + float y = 0; + for (int i = 0; i < sinc_table_size; i++, xx++) + y += in[xx] * sinc_table[i]; + out[ox++] = y; + + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java b/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java new file mode 100644 index 00000000000..3f6c12fc765 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -0,0 +1,1179 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.midi.Soundbank; +import javax.sound.midi.Transmitter; +import javax.sound.midi.VoiceStatus; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; + +/** + * The software synthesizer class. + * + * @author Karl Helgason + */ +public class SoftSynthesizer implements AudioSynthesizer, + ReferenceCountingDevice { + + protected static class WeakAudioStream extends InputStream + { + private volatile AudioInputStream stream; + public SoftAudioPusher pusher = null; + public AudioInputStream jitter_stream = null; + public SourceDataLine sourceDataLine = null; + private WeakReference weak_stream_link; + private AudioFloatConverter converter; + private float[] silentbuffer = null; + private int samplesize; + + public void setInputStream(AudioInputStream stream) + { + this.stream = stream; + } + + public int available() throws IOException { + AudioInputStream local_stream = stream; + if(local_stream != null) + return local_stream.available(); + return 0; + } + + public int read() throws IOException { + byte[] b = new byte[1]; + if (read(b) == -1) + return -1; + return b[0] & 0xFF; + } + + public int read(byte[] b, int off, int len) throws IOException { + AudioInputStream local_stream = stream; + if(local_stream != null) + return local_stream.read(b, off, len); + else + { + int flen = len / samplesize; + if(silentbuffer == null || silentbuffer.length < flen) + silentbuffer = new float[flen]; + converter.toByteArray(silentbuffer, flen, b, off); + + if(pusher != null) + if(weak_stream_link.get() == null) + { + Runnable runnable = new Runnable() + { + SoftAudioPusher _pusher = pusher; + AudioInputStream _jitter_stream = jitter_stream; + SourceDataLine _sourceDataLine = sourceDataLine; + public void run() + { + _pusher.stop(); + if(_jitter_stream != null) + try { + _jitter_stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + if(_sourceDataLine != null) + _sourceDataLine.close(); + } + }; + pusher = null; + jitter_stream = null; + sourceDataLine = null; + new Thread(runnable).start(); + } + return len; + } + } + + public WeakAudioStream(AudioInputStream stream) { + this.stream = stream; + weak_stream_link = new WeakReference(stream); + converter = AudioFloatConverter.getConverter(stream.getFormat()); + samplesize = stream.getFormat().getFrameSize() / stream.getFormat().getChannels(); + } + + public AudioInputStream getAudioInputStream() + { + return new AudioInputStream(this, stream.getFormat(), AudioSystem.NOT_SPECIFIED); + } + + public void close() throws IOException + { + AudioInputStream astream = weak_stream_link.get(); + if(astream != null) + astream.close(); + } + } + + private static class Info extends MidiDevice.Info { + public Info() { + super(INFO_NAME, INFO_VENDOR, INFO_DESCRIPTION, INFO_VERSION); + } + } + + protected static final String INFO_NAME = "Gervill"; + protected static final String INFO_VENDOR = "OpenJDK"; + protected static final String INFO_DESCRIPTION = "Software MIDI Synthesizer"; + protected static final String INFO_VERSION = "1.0"; + protected final static MidiDevice.Info info = new Info(); + + private static SourceDataLine testline = null; + + private static Soundbank defaultSoundBank = null; + + protected WeakAudioStream weakstream = null; + + protected Object control_mutex = this; + + protected int voiceIDCounter = 0; + + // 0: default + // 1: DLS Voice Allocation + protected int voice_allocation_mode = 0; + + protected boolean reverb_light = true; + protected boolean reverb_on = true; + protected boolean chorus_on = true; + protected boolean agc_on = true; + + protected SoftChannel[] channels; + protected SoftChannelProxy[] external_channels = null; + + private boolean largemode = false; + + // 0: GM Mode off (default) + // 1: GM Level 1 + // 2: GM Level 2 + private int gmmode = 0; + + private int deviceid = 0; + + private AudioFormat format = new AudioFormat(44100, 16, 2, true, false); + + private SourceDataLine sourceDataLine = null; + + private SoftAudioPusher pusher = null; + private AudioInputStream pusher_stream = null; + + private float controlrate = 147f; + + private boolean open = false; + private boolean implicitOpen = false; + + private String resamplerType = "linear"; + private SoftResampler resampler = new SoftLinearResampler(); + + private int number_of_midi_channels = 16; + private int maxpoly = 64; + private long latency = 200000; // 200 msec + private boolean jitter_correction = false; + + private SoftMainMixer mainmixer; + private SoftVoice[] voices; + + private Map tunings + = new HashMap(); + private Map inslist + = new HashMap(); + private Map availlist + = new HashMap(); + private Map loadedlist + = new HashMap(); + + private ArrayList recvslist = new ArrayList(); + + private void getBuffers(ModelInstrument instrument, + List buffers) { + for (ModelPerformer performer : instrument.getPerformers()) { + if (performer.getOscillators() != null) { + for (ModelOscillator osc : performer.getOscillators()) { + if (osc instanceof ModelByteBufferWavetable) { + ModelByteBufferWavetable w = (ModelByteBufferWavetable)osc; + ModelByteBuffer buff = w.getBuffer(); + if (buff != null) + buffers.add(buff); + buff = w.get8BitExtensionBuffer(); + if (buff != null) + buffers.add(buff); + } + } + } + } + } + + private boolean loadSamples(List instruments) { + if (largemode) + return true; + List buffers = new ArrayList(); + for (ModelInstrument instrument : instruments) + getBuffers(instrument, buffers); + try { + ModelByteBuffer.loadAll(buffers); + } catch (IOException e) { + return false; + } + return true; + } + + private boolean loadInstruments(List instruments) { + if (!isOpen()) + return false; + if (!loadSamples(instruments)) + return false; + + synchronized (control_mutex) { + if (channels != null) + for (SoftChannel c : channels) + c.current_instrument = null; + for (Instrument instrument : instruments) { + String pat = patchToString(instrument.getPatch()); + availlist.remove(pat); + SoftInstrument softins + = new SoftInstrument((ModelInstrument) instrument); + inslist.put(pat, softins); + loadedlist.put(pat, (ModelInstrument) instrument); + } + } + + return true; + } + + private void processPropertyInfo(Map info) { + AudioSynthesizerPropertyInfo[] items = getPropertyInfo(info); + + String resamplerType = (String)items[0].value; + if (resamplerType.equalsIgnoreCase("point")) + { + this.resampler = new SoftPointResampler(); + this.resamplerType = "point"; + } + else if (resamplerType.equalsIgnoreCase("linear")) + { + this.resampler = new SoftLinearResampler2(); + this.resamplerType = "linear"; + } + else if (resamplerType.equalsIgnoreCase("linear1")) + { + this.resampler = new SoftLinearResampler(); + this.resamplerType = "linear1"; + } + else if (resamplerType.equalsIgnoreCase("linear2")) + { + this.resampler = new SoftLinearResampler2(); + this.resamplerType = "linear2"; + } + else if (resamplerType.equalsIgnoreCase("cubic")) + { + this.resampler = new SoftCubicResampler(); + this.resamplerType = "cubic"; + } + else if (resamplerType.equalsIgnoreCase("lanczos")) + { + this.resampler = new SoftLanczosResampler(); + this.resamplerType = "lanczos"; + } + else if (resamplerType.equalsIgnoreCase("sinc")) + { + this.resampler = new SoftSincResampler(); + this.resamplerType = "sinc"; + } + + setFormat((AudioFormat)items[2].value); + controlrate = (Float)items[1].value; + latency = (Long)items[3].value; + deviceid = (Integer)items[4].value; + maxpoly = (Integer)items[5].value; + reverb_on = (Boolean)items[6].value; + chorus_on = (Boolean)items[7].value; + agc_on = (Boolean)items[8].value; + largemode = (Boolean)items[9].value; + number_of_midi_channels = (Integer)items[10].value; + jitter_correction = (Boolean)items[11].value; + reverb_light = (Boolean)items[12].value; + } + + private String patchToString(Patch patch) { + if (patch instanceof ModelPatch && ((ModelPatch) patch).isPercussion()) + return "p." + patch.getProgram() + "." + patch.getBank(); + else + return patch.getProgram() + "." + patch.getBank(); + } + + private void setFormat(AudioFormat format) { + if (format.getChannels() > 2) { + throw new IllegalArgumentException( + "Only mono and stereo audio supported."); + } + if (AudioFloatConverter.getConverter(format) == null) + throw new IllegalArgumentException("Audio format not supported."); + this.format = format; + } + + protected void removeReceiver(Receiver recv) { + boolean perform_close = false; + synchronized (control_mutex) { + if (recvslist.remove(recv)) { + if (implicitOpen && recvslist.isEmpty()) + perform_close = true; + } + } + if (perform_close) + close(); + } + + protected SoftMainMixer getMainMixer() { + if (!isOpen()) + return null; + return mainmixer; + } + + protected SoftInstrument findInstrument(int program, int bank, int channel) { + + // Add support for GM2 banks 0x78 and 0x79 + // as specified in DLS 2.2 in Section 1.4.6 + // which allows using percussion and melodic instruments + // on all channels + if (bank >> 7 == 0x78 || bank >> 7 == 0x79) { + SoftInstrument current_instrument + = inslist.get(program + "." + bank); + if (current_instrument != null) + return current_instrument; + + String p_plaf; + if (bank >> 7 == 0x78) + p_plaf = "p."; + else + p_plaf = ""; + + // Instrument not found fallback to MSB:bank, LSB:0 + current_instrument = inslist.get(p_plaf + program + "." + + ((bank & 128) << 7)); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:bank + current_instrument = inslist.get(p_plaf + program + "." + + (bank & 128)); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0 + current_instrument = inslist.get(p_plaf + program + ".0"); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0, program=0 + current_instrument = inslist.get(p_plaf + program + "0.0"); + if (current_instrument != null) + return current_instrument; + return null; + } + + // Channel 10 uses percussion instruments + String p_plaf; + if (channel == 9) + p_plaf = "p."; + else + p_plaf = ""; + + SoftInstrument current_instrument + = inslist.get(p_plaf + program + "." + bank); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0 + current_instrument = inslist.get(p_plaf + program + ".0"); + if (current_instrument != null) + return current_instrument; + // Instrument not found fallback to MSB:0, LSB:0, program=0 + current_instrument = inslist.get(p_plaf + "0.0"); + if (current_instrument != null) + return current_instrument; + return null; + } + + protected int getVoiceAllocationMode() { + return voice_allocation_mode; + } + + protected int getGeneralMidiMode() { + return gmmode; + } + + protected void setGeneralMidiMode(int gmmode) { + this.gmmode = gmmode; + } + + protected int getDeviceID() { + return deviceid; + } + + protected float getControlRate() { + return controlrate; + } + + protected SoftVoice[] getVoices() { + return voices; + } + + protected SoftTuning getTuning(Patch patch) { + String t_id = patchToString(patch); + SoftTuning tuning = tunings.get(t_id); + if (tuning == null) { + tuning = new SoftTuning(patch); + tunings.put(t_id, tuning); + } + return tuning; + } + + public long getLatency() { + synchronized (control_mutex) { + return latency; + } + } + + public AudioFormat getFormat() { + synchronized (control_mutex) { + return format; + } + } + + public int getMaxPolyphony() { + synchronized (control_mutex) { + return maxpoly; + } + } + + public MidiChannel[] getChannels() { + + synchronized (control_mutex) { + // if (external_channels == null) => the synthesizer is not open, + // create 16 proxy channels + // otherwise external_channels has the same length as channels array + if (external_channels == null) { + external_channels = new SoftChannelProxy[16]; + for (int i = 0; i < external_channels.length; i++) + external_channels[i] = new SoftChannelProxy(); + } + MidiChannel[] ret; + if (isOpen()) + ret = new MidiChannel[channels.length]; + else + ret = new MidiChannel[16]; + for (int i = 0; i < ret.length; i++) + ret[i] = external_channels[i]; + return ret; + } + } + + public VoiceStatus[] getVoiceStatus() { + if (!isOpen()) { + VoiceStatus[] tempVoiceStatusArray + = new VoiceStatus[getMaxPolyphony()]; + for (int i = 0; i < tempVoiceStatusArray.length; i++) { + VoiceStatus b = new VoiceStatus(); + b.active = false; + b.bank = 0; + b.channel = 0; + b.note = 0; + b.program = 0; + b.volume = 0; + tempVoiceStatusArray[i] = b; + } + return tempVoiceStatusArray; + } + + synchronized (control_mutex) { + VoiceStatus[] tempVoiceStatusArray = new VoiceStatus[voices.length]; + for (int i = 0; i < voices.length; i++) { + VoiceStatus a = voices[i]; + VoiceStatus b = new VoiceStatus(); + b.active = a.active; + b.bank = a.bank; + b.channel = a.channel; + b.note = a.note; + b.program = a.program; + b.volume = a.volume; + tempVoiceStatusArray[i] = b; + } + return tempVoiceStatusArray; + } + } + + public boolean isSoundbankSupported(Soundbank soundbank) { + for (Instrument ins: soundbank.getInstruments()) + if (!(ins instanceof ModelInstrument)) + return false; + return true; + } + + public boolean loadInstrument(Instrument instrument) { + if (instrument == null || (!(instrument instanceof ModelInstrument))) { + throw new IllegalArgumentException("Unsupported instrument: " + + instrument); + } + List instruments = new ArrayList(); + instruments.add((ModelInstrument)instrument); + return loadInstruments(instruments); + } + + public void unloadInstrument(Instrument instrument) { + if (instrument == null || (!(instrument instanceof ModelInstrument))) { + throw new IllegalArgumentException("Unsupported instrument: " + + instrument); + } + if (!isOpen()) + return; + + String pat = patchToString(instrument.getPatch()); + synchronized (control_mutex) { + for (SoftChannel c: channels) + c.current_instrument = null; + inslist.remove(pat); + loadedlist.remove(pat); + availlist.remove(pat); + } + } + + public boolean remapInstrument(Instrument from, Instrument to) { + + if (from == null) + throw new NullPointerException(); + if (to == null) + throw new NullPointerException(); + if (!(from instanceof ModelInstrument)) { + throw new IllegalArgumentException("Unsupported instrument: " + + from.toString()); + } + if (!(to instanceof ModelInstrument)) { + throw new IllegalArgumentException("Unsupported instrument: " + + to.toString()); + } + if (!isOpen()) + return false; + + synchronized (control_mutex) { + if (!loadedlist.containsValue(to) && !availlist.containsValue(to)) + throw new IllegalArgumentException("Instrument to is not loaded."); + unloadInstrument(from); + ModelMappedInstrument mfrom = new ModelMappedInstrument( + (ModelInstrument)to, from.getPatch()); + return loadInstrument(mfrom); + } + } + + public synchronized Soundbank getDefaultSoundbank() { + if (defaultSoundBank == null) { + try { + File javahome = new File(System.getProperties().getProperty( + "java.home")); + File libaudio = new File(new File(javahome, "lib"), "audio"); + + if (libaudio.exists()) { + File foundfile = null; + File[] files = libaudio.listFiles(); + if (files != null) { + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (file.isFile()) { + String lname = file.getName().toLowerCase(); + if (lname.endsWith(".sf2") || + lname.endsWith(".dls")) { + if (foundfile == null || (file.length() > + foundfile.length())) { + foundfile = file; + } + } + } + } + } + if (foundfile != null) { + try { + Soundbank sbk = MidiSystem.getSoundbank(foundfile); + defaultSoundBank = sbk; + return defaultSoundBank; + } catch (Exception e) { + //e.printStackTrace(); + } + } + } + + if (System.getProperties().getProperty("os.name") + .startsWith("Windows")) { + File gm_dls = new File(System.getenv("SystemRoot") + + "\\system32\\drivers\\gm.dls"); + if (gm_dls.exists()) { + try { + Soundbank sbk = MidiSystem.getSoundbank(gm_dls); + defaultSoundBank = sbk; + return defaultSoundBank; + } catch (Exception e) { + //e.printStackTrace(); + } + } + } + } catch (AccessControlException e) { + } catch (Exception e) { + //e.printStackTrace(); + } + + File userhome = null; + File emg_soundbank_file = null; + + /* + * Try to load saved generated soundbank + */ + try { + userhome = new File(System.getProperty("user.home"), + ".gervill"); + emg_soundbank_file = new File(userhome, "soundbank-emg.sf2"); + Soundbank sbk = MidiSystem.getSoundbank(emg_soundbank_file); + defaultSoundBank = sbk; + return defaultSoundBank; + } catch (AccessControlException e) { + } catch (Exception e) { + //e.printStackTrace(); + } + + try { + + /* + * Generate emergency soundbank + */ + defaultSoundBank = EmergencySoundbank.createSoundbank(); + + /* + * Save generated soundbank to disk for faster future use. + */ + if(defaultSoundBank != null) + { + if(!userhome.exists()) userhome.mkdirs(); + if(!emg_soundbank_file.exists()) + ((SF2Soundbank)defaultSoundBank).save(emg_soundbank_file); + } + } catch (Exception e) { + //e.printStackTrace(); + } + + } + return defaultSoundBank; + } + + public Instrument[] getAvailableInstruments() { + if (!isOpen()) { + Soundbank defsbk = getDefaultSoundbank(); + if (defsbk == null) + return new Instrument[0]; + return defsbk.getInstruments(); + } + + synchronized (control_mutex) { + ModelInstrument[] inslist_array = + new ModelInstrument[availlist.values().size()]; + availlist.values().toArray(inslist_array); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + } + + public Instrument[] getLoadedInstruments() { + if (!isOpen()) + return new Instrument[0]; + + synchronized (control_mutex) { + ModelInstrument[] inslist_array = + new ModelInstrument[loadedlist.values().size()]; + loadedlist.values().toArray(inslist_array); + Arrays.sort(inslist_array, new ModelInstrumentComparator()); + return inslist_array; + } + } + + public boolean loadAllInstruments(Soundbank soundbank) { + List instruments = new ArrayList(); + for (Instrument ins: soundbank.getInstruments()) { + if (ins == null || !(ins instanceof ModelInstrument)) { + throw new IllegalArgumentException( + "Unsupported instrument: " + ins); + } + instruments.add((ModelInstrument)ins); + } + return loadInstruments(instruments); + } + + public void unloadAllInstruments(Soundbank soundbank) { + if (soundbank == null || !isSoundbankSupported(soundbank)) + throw new IllegalArgumentException("Unsupported soundbank: " + soundbank); + + if (!isOpen()) + return; + + for (Instrument ins: soundbank.getInstruments()) { + if (ins instanceof ModelInstrument) { + unloadInstrument(ins); + } + } + } + + public boolean loadInstruments(Soundbank soundbank, Patch[] patchList) { + List instruments = new ArrayList(); + for (Patch patch: patchList) { + Instrument ins = soundbank.getInstrument(patch); + if (ins == null || !(ins instanceof ModelInstrument)) { + throw new IllegalArgumentException( + "Unsupported instrument: " + ins); + } + instruments.add((ModelInstrument)ins); + } + return loadInstruments(instruments); + } + + public void unloadInstruments(Soundbank soundbank, Patch[] patchList) { + if (soundbank == null || !isSoundbankSupported(soundbank)) + throw new IllegalArgumentException("Unsupported soundbank: " + soundbank); + + if (!isOpen()) + return; + + for (Patch pat: patchList) { + Instrument ins = soundbank.getInstrument(pat); + if (ins instanceof ModelInstrument) { + unloadInstrument(ins); + } + } + } + + public MidiDevice.Info getDeviceInfo() { + return info; + } + + public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map info) { + List list = + new ArrayList(); + + AudioSynthesizerPropertyInfo item; + + // If info != null or synthesizer is closed + // we return how the synthesizer will be set on next open + // If info == null and synthesizer is open + // we return current synthesizer properties. + boolean o = info == null && open; + + item = new AudioSynthesizerPropertyInfo("interpolation", o?resamplerType:"linear"); + item.choices = new String[]{"linear", "linear1", "linear2", "cubic", + "lanczos", "sinc", "point"}; + item.description = "Interpolation method"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("control rate", o?controlrate:147f); + item.description = "Control rate"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("format", + o?format:new AudioFormat(44100, 16, 2, true, false)); + item.description = "Default audio format"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("latency", o?latency:120000L); + item.description = "Default latency"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("device id", o?deviceid:0); + item.description = "Device ID for SysEx Messages"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("max polyphony", o?maxpoly:64); + item.description = "Maximum polyphony"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("reverb", o?reverb_on:true); + item.description = "Turn reverb effect on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("chorus", o?chorus_on:true); + item.description = "Turn chorus effect on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("auto gain control", o?agc_on:true); + item.description = "Turn auto gain control on or off"; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("large mode", o?largemode:false); + item.description = "Turn large mode on or off."; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("midi channels", o?channels.length:16); + item.description = "Number of midi channels."; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("jitter correction", o?jitter_correction:true); + item.description = "Turn jitter correction on or off."; + list.add(item); + + item = new AudioSynthesizerPropertyInfo("light reverb", o?reverb_light:true); + item.description = "Turn light reverb mode on or off"; + list.add(item); + + AudioSynthesizerPropertyInfo[] items; + items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]); + + if (info != null) + for (AudioSynthesizerPropertyInfo item2: items) { + Object v = info.get(item2.name); + Class c = (item2.valueClass); + if (v != null) + if (c.isInstance(v)) + item2.value = v; + } + + return items; + } + + public void open() throws MidiUnavailableException { + if (isOpen()) { + synchronized (control_mutex) { + implicitOpen = false; + } + return; + } + open(null, null); + } + + public void open(SourceDataLine line, Map info) throws MidiUnavailableException { + if (isOpen()) { + synchronized (control_mutex) { + implicitOpen = false; + } + return; + } + synchronized (control_mutex) { + try { + if (line != null) + setFormat(line.getFormat()); + + AudioInputStream ais = openStream(getFormat(), info); + + weakstream = new WeakAudioStream(ais); + ais = weakstream.getAudioInputStream(); + + if (line == null) + { + if(testline != null) + line = testline; + else + line = AudioSystem.getSourceDataLine(getFormat()); + } + + double latency = this.latency; + + if (!line.isOpen()) { + int bufferSize = getFormat().getFrameSize() + * (int)(getFormat().getFrameRate() * (latency/1000000f)); + line.open(getFormat(), bufferSize); + + // Remember that we opened that line + // so we can close again in SoftSynthesizer.close() + sourceDataLine = line; + } + if (!line.isActive()) + line.start(); + + int controlbuffersize = 512; + try { + controlbuffersize = ais.available(); + } catch (IOException e) { + } + + // Tell mixer not fill read buffers fully. + // This lowers latency, and tells DataPusher + // to read in smaller amounts. + //mainmixer.readfully = false; + //pusher = new DataPusher(line, ais); + + int buffersize = line.getBufferSize(); + buffersize -= buffersize % controlbuffersize; + + if (buffersize < 3 * controlbuffersize) + buffersize = 3 * controlbuffersize; + + if (jitter_correction) { + ais = new SoftJitterCorrector(ais, buffersize, + controlbuffersize); + if(weakstream != null) + weakstream.jitter_stream = ais; + } + pusher = new SoftAudioPusher(line, ais, controlbuffersize); + pusher_stream = ais; + pusher.start(); + + if(weakstream != null) + { + weakstream.pusher = pusher; + weakstream.sourceDataLine = sourceDataLine; + } + + + + } catch (LineUnavailableException e) { + if (isOpen()) + close(); + // am: need MidiUnavailableException(Throwable) ctor! + throw new MidiUnavailableException(e.toString()); + } + + } + } + + public AudioInputStream openStream(AudioFormat targetFormat, + Map info) throws MidiUnavailableException { + + if (isOpen()) + throw new MidiUnavailableException("Synthesizer is already open"); + + synchronized (control_mutex) { + + gmmode = 0; + voice_allocation_mode = 0; + + processPropertyInfo(info); + + open = true; + implicitOpen = false; + + if (targetFormat != null) + setFormat(targetFormat); + + Soundbank defbank = getDefaultSoundbank(); + if (defbank != null) { + loadAllInstruments(defbank); + availlist.putAll(loadedlist); + loadedlist.clear(); + } + + voices = new SoftVoice[maxpoly]; + for (int i = 0; i < maxpoly; i++) + voices[i] = new SoftVoice(this); + + mainmixer = new SoftMainMixer(this); + + channels = new SoftChannel[number_of_midi_channels]; + for (int i = 0; i < channels.length; i++) + channels[i] = new SoftChannel(this, i); + + if (external_channels == null) { + // Always create external_channels array + // with 16 or more channels + // so getChannels works correctly + // when the synhtesizer is closed. + if (channels.length < 16) + external_channels = new SoftChannelProxy[16]; + else + external_channels = new SoftChannelProxy[channels.length]; + for (int i = 0; i < external_channels.length; i++) + external_channels[i] = new SoftChannelProxy(); + } else { + // We must resize external_channels array + // but we must also copy the old SoftChannelProxy + // into the new one + if (channels.length > external_channels.length) { + SoftChannelProxy[] new_external_channels + = new SoftChannelProxy[channels.length]; + for (int i = 0; i < external_channels.length; i++) + new_external_channels[i] = external_channels[i]; + for (int i = external_channels.length; + i < new_external_channels.length; i++) { + new_external_channels[i] = new SoftChannelProxy(); + } + } + } + + for (int i = 0; i < channels.length; i++) + external_channels[i].setChannel(channels[i]); + + for (SoftVoice voice: getVoices()) + voice.resampler = resampler.openStreamer(); + + for (Receiver recv: getReceivers()) { + SoftReceiver srecv = ((SoftReceiver)recv); + srecv.open = open; + srecv.mainmixer = mainmixer; + srecv.midimessages = mainmixer.midimessages; + } + + return mainmixer.getInputStream(); + } + } + + public void close() { + + if (!isOpen()) + return; + + SoftAudioPusher pusher_to_be_closed = null; + AudioInputStream pusher_stream_to_be_closed = null; + synchronized (control_mutex) { + if (pusher != null) { + pusher_to_be_closed = pusher; + pusher_stream_to_be_closed = pusher_stream; + pusher = null; + pusher_stream = null; + } + } + + if (pusher_to_be_closed != null) { + // Pusher must not be closed synchronized against control_mutex, + // this may result in synchronized conflict between pusher + // and current thread. + pusher_to_be_closed.stop(); + + try { + pusher_stream_to_be_closed.close(); + } catch (IOException e) { + //e.printStackTrace(); + } + } + + synchronized (control_mutex) { + + if (mainmixer != null) + mainmixer.close(); + open = false; + implicitOpen = false; + mainmixer = null; + voices = null; + channels = null; + + if (external_channels != null) + for (int i = 0; i < external_channels.length; i++) + external_channels[i].setChannel(null); + + if (sourceDataLine != null) { + sourceDataLine.close(); + sourceDataLine = null; + } + + inslist.clear(); + availlist.clear(); + loadedlist.clear(); + tunings.clear(); + + while (recvslist.size() != 0) + recvslist.get(recvslist.size() - 1).close(); + + } + } + + public boolean isOpen() { + synchronized (control_mutex) { + return open; + } + } + + public long getMicrosecondPosition() { + + if (!isOpen()) + return 0; + + synchronized (control_mutex) { + return mainmixer.getMicrosecondPosition(); + } + } + + public int getMaxReceivers() { + return -1; + } + + public int getMaxTransmitters() { + return 0; + } + + public Receiver getReceiver() throws MidiUnavailableException { + + synchronized (control_mutex) { + SoftReceiver receiver = new SoftReceiver(this); + receiver.open = open; + recvslist.add(receiver); + return receiver; + } + } + + public List getReceivers() { + + synchronized (control_mutex) { + ArrayList recvs = new ArrayList(); + recvs.addAll(recvslist); + return recvs; + } + } + + public Transmitter getTransmitter() throws MidiUnavailableException { + + throw new MidiUnavailableException("No transmitter available"); + } + + public List getTransmitters() { + + return new ArrayList(); + } + + public Receiver getReceiverReferenceCounting() + throws MidiUnavailableException { + + if (!isOpen()) { + open(); + synchronized (control_mutex) { + implicitOpen = true; + } + } + + return getReceiver(); + } + + public Transmitter getTransmitterReferenceCounting() + throws MidiUnavailableException { + + throw new MidiUnavailableException("No transmitter available"); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java b/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java new file mode 100644 index 00000000000..a5a1eafe1a4 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java @@ -0,0 +1,256 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.Patch; + +/** + * A tuning program container, for use with MIDI Tuning. + * See: http://www.midi.org + * + * @author Karl Helgason + */ +public class SoftTuning { + + private String name = null; + private double[] tuning = new double[128]; + private Patch patch = null; + + public SoftTuning() { + name = "12-TET"; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + } + + public SoftTuning(byte[] data) { + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + load(data); + } + + public SoftTuning(Patch patch) { + this.patch = patch; + name = "12-TET"; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + } + + public SoftTuning(Patch patch, byte[] data) { + this.patch = patch; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100; + load(data); + } + + private boolean checksumOK(byte[] data) { + int x = data[1] & 0xFF; + for (int i = 2; i < data.length - 2; i++) + x = x ^ (data[i] & 0xFF); + return (data[data.length - 2] & 0xFF) == (x & 127); + } + + /* + private boolean checksumOK2(byte[] data) { + int x = data[1] & 0xFF; // 7E + x = x ^ (data[2] & 0xFF); // + x = x ^ (data[4] & 0xFF); // nn + x = x ^ (data[5] & 0xFF); // tt + for (int i = 22; i < data.length - 2; i++) + x = x ^ (data[i] & 0xFF); + return (data[data.length - 2] & 0xFF) == (x & 127); + } + */ + public void load(byte[] data) { + // Universal Non-Real-Time / Real-Time SysEx + if ((data[1] & 0xFF) == 0x7E || (data[1] & 0xFF) == 0x7F) { + int subid1 = data[3] & 0xFF; + switch (subid1) { + case 0x08: // MIDI Tuning Standard + int subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // BULK TUNING DUMP (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + //if (!checksumOK2(data)) + // break; + try { + name = new String(data, 6, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int r = 22; + for (int i = 0; i < 128; i++) { + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[i] = 100.0 * + (((xx * 16384) + (yy * 128) + zz) / 16384.0); + } + break; + } + case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + int ll = data[6] & 0xFF; + int r = 7; + for (int i = 0; i < ll; i++) { + int kk = data[r++] & 0xFF; + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[kk] = 100.0*(((xx*16384) + (yy*128) + zz)/16384.0); + } + break; + } + case 0x04: // KEY-BASED TUNING DUMP (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int r = 23; + for (int i = 0; i < 128; i++) { + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[i] = 100.0*(((xx*16384) + (yy*128) + zz)/16384.0); + } + break; + } + case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format + // (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + int[] octave_tuning = new int[12]; + for (int i = 0; i < 12; i++) + octave_tuning[i] = (data[i + 23] & 0xFF) - 64; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format + // (NON-REAL-TIME) + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (!checksumOK(data)) + break; + try { + name = new String(data, 7, 16, "ascii"); + } catch (UnsupportedEncodingException e) { + name = null; + } + double[] octave_tuning = new double[12]; + for (int i = 0; i < 12; i++) { + int v = (data[i * 2 + 23] & 0xFF) * 128 + + (data[i * 2 + 24] & 0xFF); + octave_tuning[i] = (v / 8192.0 - 1) * 100.0; + } + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x07: // SINGLE NOTE TUNING CHANGE (NON + // REAL-TIME/REAL-TIME) (BANK) + // http://www.midi.org/about-midi/tuning_extens.shtml + int ll = data[7] & 0xFF; + int r = 8; + for (int i = 0; i < ll; i++) { + int kk = data[r++] & 0xFF; + int xx = data[r++] & 0xFF; + int yy = data[r++] & 0xFF; + int zz = data[r++] & 0xFF; + if (!(xx == 127 && yy == 127 && zz == 127)) + tuning[kk] = 100.0 + * (((xx*16384) + (yy*128) + zz) / 16384.0); + } + break; + case 0x08: // scale/octave tuning 1-byte form (Non + // Real-Time/REAL-TIME) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + int[] octave_tuning = new int[12]; + for (int i = 0; i < 12; i++) + octave_tuning[i] = (data[i + 8] & 0xFF) - 64; + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + case 0x09: // scale/octave tuning 2-byte form (Non + // Real-Time/REAL-TIME) + { + // http://www.midi.org/about-midi/tuning-scale.shtml + double[] octave_tuning = new double[12]; + for (int i = 0; i < 12; i++) { + int v = (data[i * 2 + 8] & 0xFF) * 128 + + (data[i * 2 + 9] & 0xFF); + octave_tuning[i] = (v / 8192.0 - 1) * 100.0; + } + for (int i = 0; i < tuning.length; i++) + tuning[i] = i * 100 + octave_tuning[i % 12]; + break; + } + default: + break; + } + } + } + } + + public double[] getTuning() { + return tuning; + } + + public double getTuning(int noteNumber) { + return tuning[noteNumber]; + } + + public Patch getPatch() { + return patch; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java b/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java new file mode 100644 index 00000000000..49662b78706 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/SoftVoice.java @@ -0,0 +1,841 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.midi.VoiceStatus; + +/** + * Software synthesizer voice class. + * + * @author Karl Helgason + */ +public class SoftVoice extends VoiceStatus { + + public int exclusiveClass = 0; + public boolean releaseTriggered = false; + private int noteOn_noteNumber = 0; + private int noteOn_velocity = 0; + private int noteOff_velocity = 0; + protected ModelChannelMixer channelmixer = null; + protected double tunedKey = 0; + protected SoftTuning tuning = null; + protected SoftChannel stealer_channel = null; + protected ModelConnectionBlock[] stealer_extendedConnectionBlocks = null; + protected SoftPerformer stealer_performer = null; + protected ModelChannelMixer stealer_channelmixer = null; + protected int stealer_voiceID = -1; + protected int stealer_noteNumber = 0; + protected int stealer_velocity = 0; + protected boolean stealer_releaseTriggered = false; + protected int voiceID = -1; + protected boolean sustain = false; + protected boolean sostenuto = false; + protected boolean portamento = false; + private SoftFilter filter_left; + private SoftFilter filter_right; + private SoftProcess eg = new SoftEnvelopeGenerator(); + private SoftProcess lfo = new SoftLowFrequencyOscillator(); + protected Map objects = + new HashMap(); + protected SoftSynthesizer synthesizer; + protected SoftInstrument instrument; + protected SoftPerformer performer; + protected SoftChannel softchannel = null; + protected boolean on = false; + private boolean audiostarted = false; + private boolean started = false; + private boolean stopping = false; + private float osc_attenuation = 0.0f; + private ModelOscillatorStream osc_stream; + private int osc_stream_nrofchannels; + private float[][] osc_buff = new float[2][]; + private boolean osc_stream_off_transmitted = false; + private boolean out_mixer_end = false; + private float out_mixer_left = 0; + private float out_mixer_right = 0; + private float out_mixer_effect1 = 0; + private float out_mixer_effect2 = 0; + private float last_out_mixer_left = 0; + private float last_out_mixer_right = 0; + private float last_out_mixer_effect1 = 0; + private float last_out_mixer_effect2 = 0; + protected ModelConnectionBlock[] extendedConnectionBlocks = null; + private ModelConnectionBlock[] connections; + // Last value added to destination + private double[] connections_last = new double[50]; + // Pointer to source value + private double[][][] connections_src = new double[50][3][]; + // Key-based override (if any) + private int[][] connections_src_kc = new int[50][3]; + // Pointer to destination value + private double[][] connections_dst = new double[50][]; + private boolean soundoff = false; + private float lastMuteValue = 0; + private float lastSoloMuteValue = 0; + protected double[] co_noteon_keynumber = new double[1]; + protected double[] co_noteon_velocity = new double[1]; + protected double[] co_noteon_on = new double[1]; + private SoftControl co_noteon = new SoftControl() { + double[] keynumber = co_noteon_keynumber; + double[] velocity = co_noteon_velocity; + double[] on = co_noteon_on; + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("keynumber")) + return keynumber; + if (name.equals("velocity")) + return velocity; + if (name.equals("on")) + return on; + return null; + } + }; + private double[] co_mixer_active = new double[1]; + private double[] co_mixer_gain = new double[1]; + private double[] co_mixer_pan = new double[1]; + private double[] co_mixer_balance = new double[1]; + private double[] co_mixer_reverb = new double[1]; + private double[] co_mixer_chorus = new double[1]; + private SoftControl co_mixer = new SoftControl() { + double[] active = co_mixer_active; + double[] gain = co_mixer_gain; + double[] pan = co_mixer_pan; + double[] balance = co_mixer_balance; + double[] reverb = co_mixer_reverb; + double[] chorus = co_mixer_chorus; + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("active")) + return active; + if (name.equals("gain")) + return gain; + if (name.equals("pan")) + return pan; + if (name.equals("balance")) + return balance; + if (name.equals("reverb")) + return reverb; + if (name.equals("chorus")) + return chorus; + return null; + } + }; + private double[] co_osc_pitch = new double[1]; + private SoftControl co_osc = new SoftControl() { + double[] pitch = co_osc_pitch; + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("pitch")) + return pitch; + return null; + } + }; + private double[] co_filter_freq = new double[1]; + private double[] co_filter_type = new double[1]; + private double[] co_filter_q = new double[1]; + private SoftControl co_filter = new SoftControl() { + double[] freq = co_filter_freq; + double[] ftype = co_filter_type; + double[] q = co_filter_q; + public double[] get(int instance, String name) { + if (name == null) + return null; + if (name.equals("freq")) + return freq; + if (name.equals("type")) + return ftype; + if (name.equals("q")) + return q; + return null; + } + }; + protected SoftResamplerStreamer resampler; + private int nrofchannels; + + public SoftVoice(SoftSynthesizer synth) { + synthesizer = synth; + filter_left = new SoftFilter(synth.getFormat().getSampleRate()); + filter_right = new SoftFilter(synth.getFormat().getSampleRate()); + nrofchannels = synth.getFormat().getChannels(); + } + + private int getValueKC(ModelIdentifier id) { + if (id.getObject().equals("midi_cc")) { + int ic = Integer.parseInt(id.getVariable()); + if (ic != 0 && ic != 32) { + if (ic < 120) + return ic; + } + } else if (id.getObject().equals("midi_rpn")) { + if (id.getVariable().equals("1")) + return 120; // Fine tuning + if (id.getVariable().equals("2")) + return 121; // Coarse tuning + } + return -1; + } + + private double[] getValue(ModelIdentifier id) { + SoftControl o = objects.get(id.getObject()); + if (o == null) + return null; + return o.get(id.getInstance(), id.getVariable()); + } + + private double transformValue(double value, ModelSource src) { + if (src.getTransform() != null) + return src.getTransform().transform(value); + else + return value; + } + + private double transformValue(double value, ModelDestination dst) { + if (dst.getTransform() != null) + return dst.getTransform().transform(value); + else + return value; + } + + private double processKeyBasedController(double value, int keycontrol) { + if (keycontrol == -1) + return value; + if (softchannel.keybasedcontroller_active != null) + if (softchannel.keybasedcontroller_active[note] != null) + if (softchannel.keybasedcontroller_active[note][keycontrol]) { + double key_controlvalue = + softchannel.keybasedcontroller_value[note][keycontrol]; + if (keycontrol == 10 || keycontrol == 91 || keycontrol == 93) + return key_controlvalue; + value += key_controlvalue * 2.0 - 1.0; + if (value > 1) + value = 1; + else if (value < 0) + value = 0; + } + return value; + } + + private void processConnection(int ix) { + ModelConnectionBlock conn = connections[ix]; + double[][] src = connections_src[ix]; + double[] dst = connections_dst[ix]; + if (dst == null || Double.isInfinite(dst[0])) + return; + + double value = conn.getScale(); + if (softchannel.keybasedcontroller_active == null) { + ModelSource[] srcs = conn.getSources(); + for (int i = 0; i < srcs.length; i++) { + value *= transformValue(src[i][0], srcs[i]); + if (value == 0) + break; + } + } else { + ModelSource[] srcs = conn.getSources(); + int[] src_kc = connections_src_kc[ix]; + for (int i = 0; i < srcs.length; i++) { + value *= transformValue(processKeyBasedController(src[i][0], + src_kc[i]), srcs[i]); + if (value == 0) + break; + } + } + + value = transformValue(value, conn.getDestination()); + dst[0] = dst[0] - connections_last[ix] + value; + connections_last[ix] = value; + // co_mixer_gain[0] = 0; + } + + protected void updateTuning(SoftTuning newtuning) { + tunedKey = tuning.getTuning(note) / 100.0; + if (!portamento) { + co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); + int[] c = performer.midi_connections[4]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + } + + protected void setNote(int noteNumber) { + note = noteNumber; + tunedKey = tuning.getTuning(noteNumber) / 100.0; + } + + protected void noteOn(int noteNumber, int velocity) { + + sustain = false; + sostenuto = false; + portamento = false; + + soundoff = false; + on = true; + active = true; + started = true; + // volume = velocity; + + noteOn_noteNumber = noteNumber; + noteOn_velocity = velocity; + + lastMuteValue = 0; + lastSoloMuteValue = 0; + + setNote(noteNumber); + + if (performer.forcedKeynumber) + co_noteon_keynumber[0] = 0; + else + co_noteon_keynumber[0] = tunedKey * (1f / 128f); + if (performer.forcedVelocity) + co_noteon_velocity[0] = 0; + else + co_noteon_velocity[0] = velocity * (1f / 128f); + co_mixer_active[0] = 0; + co_mixer_gain[0] = 0; + co_mixer_pan[0] = 0; + co_mixer_balance[0] = 0; + co_mixer_reverb[0] = 0; + co_mixer_chorus[0] = 0; + co_osc_pitch[0] = 0; + co_filter_freq[0] = 0; + co_filter_q[0] = 0; + co_filter_type[0] = 0; + co_noteon_on[0] = 1; + + eg.reset(); + lfo.reset(); + filter_left.reset(); + filter_right.reset(); + + objects.put("master", synthesizer.getMainMixer().co_master); + objects.put("eg", eg); + objects.put("lfo", lfo); + objects.put("noteon", co_noteon); + objects.put("osc", co_osc); + objects.put("mixer", co_mixer); + objects.put("filter", co_filter); + + connections = performer.connections; + + if (connections_last == null + || connections_last.length < connections.length) { + connections_last = new double[connections.length]; + } + if (connections_src == null + || connections_src.length < connections.length) { + connections_src = new double[connections.length][][]; + connections_src_kc = new int[connections.length][]; + } + if (connections_dst == null + || connections_dst.length < connections.length) { + connections_dst = new double[connections.length][]; + } + for (int i = 0; i < connections.length; i++) { + ModelConnectionBlock conn = connections[i]; + connections_last[i] = 0; + if (conn.getSources() != null) { + ModelSource[] srcs = conn.getSources(); + if (connections_src[i] == null + || connections_src[i].length < srcs.length) { + connections_src[i] = new double[srcs.length][]; + connections_src_kc[i] = new int[srcs.length]; + } + double[][] src = connections_src[i]; + int[] src_kc = connections_src_kc[i]; + connections_src[i] = src; + for (int j = 0; j < srcs.length; j++) { + src_kc[j] = getValueKC(srcs[j].getIdentifier()); + src[j] = getValue(srcs[j].getIdentifier()); + } + } + + if (conn.getDestination() != null) + connections_dst[i] = getValue(conn.getDestination() + .getIdentifier()); + else + connections_dst[i] = null; + } + + for (int i = 0; i < connections.length; i++) + processConnection(i); + + if (extendedConnectionBlocks != null) { + for (ModelConnectionBlock connection: extendedConnectionBlocks) { + double value = 0; + + if (softchannel.keybasedcontroller_active == null) { + for (ModelSource src: connection.getSources()) { + double x = getValue(src.getIdentifier())[0]; + ModelTransform t = src.getTransform(); + if (t == null) + value += x; + else + value += t.transform(x); + } + } else { + for (ModelSource src: connection.getSources()) { + double x = getValue(src.getIdentifier())[0]; + x = processKeyBasedController(x, + getValueKC(src.getIdentifier())); + ModelTransform t = src.getTransform(); + if (t == null) + value += x; + else + value += t.transform(x); + } + } + + ModelDestination dest = connection.getDestination(); + ModelTransform t = dest.getTransform(); + if (t != null) + value = t.transform(value); + getValue(dest.getIdentifier())[0] += value; + } + } + + eg.init(synthesizer); + lfo.init(synthesizer); + + } + + protected void setPolyPressure(int pressure) { + int[] c = performer.midi_connections[2]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void setChannelPressure(int pressure) { + int[] c = performer.midi_connections[1]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void controlChange(int controller, int value) { + int[] c = performer.midi_ctrl_connections[controller]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void nrpnChange(int controller, int value) { + int[] c = performer.midi_nrpn_connections.get(controller); + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void rpnChange(int controller, int value) { + int[] c = performer.midi_rpn_connections.get(controller); + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void setPitchBend(int bend) { + int[] c = performer.midi_connections[0]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void setMute(boolean mute) { + co_mixer_gain[0] -= lastMuteValue; + lastMuteValue = mute ? -960 : 0; + co_mixer_gain[0] += lastMuteValue; + } + + protected void setSoloMute(boolean mute) { + co_mixer_gain[0] -= lastSoloMuteValue; + lastSoloMuteValue = mute ? -960 : 0; + co_mixer_gain[0] += lastSoloMuteValue; + } + + protected void shutdown() { + if (co_noteon_on[0] < -0.5) + return; + on = false; + + co_noteon_on[0] = -1; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void soundOff() { + on = false; + soundoff = true; + } + + protected void noteOff(int velocity) { + if (!on) + return; + on = false; + + noteOff_velocity = velocity; + + if (softchannel.sustain) { + sustain = true; + return; + } + if (sostenuto) + return; + + co_noteon_on[0] = 0; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void redamp() { + if (co_noteon_on[0] > 0.5) + return; + if (co_noteon_on[0] < -0.5) + return; // don't redamp notes in shutdown stage + + sustain = true; + co_noteon_on[0] = 1; + + int[] c = performer.midi_connections[3]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + protected void processControlLogic() { + if (stopping) { + active = false; + stopping = false; + audiostarted = false; + if (osc_stream != null) + try { + osc_stream.close(); + } catch (IOException e) { + //e.printStackTrace(); + } + + if (stealer_channel != null) { + stealer_channel.initVoice(this, stealer_performer, + stealer_voiceID, stealer_noteNumber, stealer_velocity, + stealer_extendedConnectionBlocks, stealer_channelmixer, + stealer_releaseTriggered); + stealer_releaseTriggered = false; + stealer_channel = null; + stealer_performer = null; + stealer_voiceID = -1; + stealer_noteNumber = 0; + stealer_velocity = 0; + stealer_extendedConnectionBlocks = null; + stealer_channelmixer = null; + } + } + if (started) { + audiostarted = true; + + ModelOscillator osc = performer.oscillators[0]; + + osc_stream_off_transmitted = false; + if (osc instanceof ModelWavetable) { + try { + resampler.open((ModelWavetable)osc, + synthesizer.getFormat().getSampleRate()); + osc_stream = resampler; + } catch (IOException e) { + //e.printStackTrace(); + } + } else { + osc_stream = osc.open(synthesizer.getFormat().getSampleRate()); + } + osc_attenuation = osc.getAttenuation(); + osc_stream_nrofchannels = osc.getChannels(); + if (osc_buff == null || osc_buff.length < osc_stream_nrofchannels) + osc_buff = new float[osc_stream_nrofchannels][]; + + if (osc_stream != null) + osc_stream.noteOn(softchannel, this, noteOn_noteNumber, + noteOn_velocity); + + + } + if (audiostarted) { + if (portamento) { + double note_delta = tunedKey - (co_noteon_keynumber[0] * 128); + double note_delta_a = Math.abs(note_delta); + if (note_delta_a < 0.0000000001) { + co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0); + portamento = false; + } else { + if (note_delta_a > softchannel.portamento_time) + note_delta = Math.signum(note_delta) + * softchannel.portamento_time; + co_noteon_keynumber[0] += note_delta * (1.0 / 128.0); + } + + int[] c = performer.midi_connections[4]; + if (c == null) + return; + for (int i = 0; i < c.length; i++) + processConnection(c[i]); + } + + eg.processControlLogic(); + lfo.processControlLogic(); + + for (int i = 0; i < performer.ctrl_connections.length; i++) + processConnection(performer.ctrl_connections[i]); + + osc_stream.setPitch((float)co_osc_pitch[0]); + + int filter_type = (int)co_filter_type[0]; + double filter_freq; + + if (co_filter_freq[0] == 13500.0) + filter_freq = 19912.126958213175; + else + filter_freq = 440.0 * Math.exp( + ((co_filter_freq[0]) - 6900.0) * + (Math.log(2.0) / 1200.0)); + /* + filter_freq = 440.0 * Math.pow(2.0, + ((co_filter_freq[0]) - 6900.0) / 1200.0);*/ + /* + * double velocity = co_noteon_velocity[0]; if(velocity < 0.5) + * filter_freq *= ((velocity * 2)*0.75 + 0.25); + */ + + double q = co_filter_q[0] / 10.0; + filter_left.setFilterType(filter_type); + filter_left.setFrequency(filter_freq); + filter_left.setResonance(q); + filter_right.setFilterType(filter_type); + filter_right.setFrequency(filter_freq); + filter_right.setResonance(q); + /* + float gain = (float) Math.pow(10, + (-osc_attenuation + co_mixer_gain[0]) / 200.0); + */ + float gain = (float)Math.exp( + (-osc_attenuation + co_mixer_gain[0])*(Math.log(10) / 200.0)); + + if (co_mixer_gain[0] <= -960) + gain = 0; + + if (soundoff) { + stopping = true; + gain = 0; + /* + * if(co_mixer_gain[0] > -960) + * co_mixer_gain[0] -= 960; + */ + } + + volume = (int)(Math.sqrt(gain) * 128); + + // gain *= 0.2; + + double pan = co_mixer_pan[0] * (1.0 / 1000.0); + // System.out.println("pan = " + pan); + if (pan < 0) + pan = 0; + else if (pan > 1) + pan = 1; + + if (pan == 0.5) { + out_mixer_left = gain * 0.7071067811865476f; + out_mixer_right = out_mixer_left; + } else { + out_mixer_left = gain * (float)Math.cos(pan * Math.PI * 0.5); + out_mixer_right = gain * (float)Math.sin(pan * Math.PI * 0.5); + } + + double balance = co_mixer_balance[0] * (1.0 / 1000.0); + if (balance != 0.5) { + if (balance > 0.5) + out_mixer_left *= (1 - balance) * 2; + else + out_mixer_right *= balance * 2; + } + + if (synthesizer.reverb_on) { + out_mixer_effect1 = (float)(co_mixer_reverb[0] * (1.0 / 1000.0)); + out_mixer_effect1 *= gain; + } else + out_mixer_effect1 = 0; + if (synthesizer.chorus_on) { + out_mixer_effect2 = (float)(co_mixer_chorus[0] * (1.0 / 1000.0)); + out_mixer_effect2 *= gain; + } else + out_mixer_effect2 = 0; + out_mixer_end = co_mixer_active[0] < 0.5; + + if (!on) + if (!osc_stream_off_transmitted) { + osc_stream_off_transmitted = true; + if (osc_stream != null) + osc_stream.noteOff(noteOff_velocity); + } + + } + if (started) { + last_out_mixer_left = out_mixer_left; + last_out_mixer_right = out_mixer_right; + last_out_mixer_effect1 = out_mixer_effect1; + last_out_mixer_effect2 = out_mixer_effect2; + started = false; + } + + } + + protected void mixAudioStream(SoftAudioBuffer in, SoftAudioBuffer out, + float amp_from, float amp_to) { + int bufferlen = in.getSize(); + if (amp_from < 0.000000001 && amp_to < 0.000000001) + return; + if (amp_from == amp_to) { + float[] fout = out.array(); + float[] fin = in.array(); + for (int i = 0; i < bufferlen; i++) + fout[i] += fin[i] * amp_to; + } else { + float amp = amp_from; + float amp_delta = (amp_to - amp_from) / bufferlen; + float[] fout = out.array(); + float[] fin = in.array(); + for (int i = 0; i < bufferlen; i++) { + amp += amp_delta; + fout[i] += fin[i] * amp; + } + } + + } + + protected void processAudioLogic(SoftAudioBuffer[] buffer) { + if (!audiostarted) + return; + + int bufferlen = buffer[0].getSize(); + + try { + osc_buff[0] = buffer[SoftMainMixer.CHANNEL_LEFT_DRY].array(); + if (nrofchannels != 1) + osc_buff[1] = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY].array(); + int ret = osc_stream.read(osc_buff, 0, bufferlen); + if (ret == -1) { + stopping = true; + return; + } + if (ret != bufferlen) { + Arrays.fill(osc_buff[0], ret, bufferlen, 0f); + if (nrofchannels != 1) + Arrays.fill(osc_buff[1], ret, bufferlen, 0f); + } + + } catch (IOException e) { + //e.printStackTrace(); + } + + SoftAudioBuffer left = buffer[SoftMainMixer.CHANNEL_LEFT]; + SoftAudioBuffer right = buffer[SoftMainMixer.CHANNEL_RIGHT]; + SoftAudioBuffer eff1 = buffer[SoftMainMixer.CHANNEL_EFFECT1]; + SoftAudioBuffer eff2 = buffer[SoftMainMixer.CHANNEL_EFFECT2]; + SoftAudioBuffer leftdry = buffer[SoftMainMixer.CHANNEL_LEFT_DRY]; + SoftAudioBuffer rightdry = buffer[SoftMainMixer.CHANNEL_RIGHT_DRY]; + + if (osc_stream_nrofchannels == 1) + rightdry = null; + + if (!Double.isInfinite(co_filter_freq[0])) { + filter_left.processAudio(leftdry); + if (rightdry != null) + filter_right.processAudio(rightdry); + } + + if (nrofchannels == 1) { + out_mixer_left = (out_mixer_left + out_mixer_right) / 2; + mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); + if (rightdry != null) + mixAudioStream(rightdry, left, last_out_mixer_left, + out_mixer_left); + } else { + mixAudioStream(leftdry, left, last_out_mixer_left, out_mixer_left); + if (rightdry != null) + mixAudioStream(rightdry, right, last_out_mixer_right, + out_mixer_right); + else + mixAudioStream(leftdry, right, last_out_mixer_right, + out_mixer_right); + } + + if (rightdry == null) { + mixAudioStream(leftdry, eff1, last_out_mixer_effect1, + out_mixer_effect1); + mixAudioStream(leftdry, eff2, last_out_mixer_effect2, + out_mixer_effect2); + } else { + mixAudioStream(leftdry, eff1, last_out_mixer_effect1 * 0.5f, + out_mixer_effect1 * 0.5f); + mixAudioStream(leftdry, eff2, last_out_mixer_effect2 * 0.5f, + out_mixer_effect2 * 0.5f); + mixAudioStream(rightdry, eff1, last_out_mixer_effect1 * 0.5f, + out_mixer_effect1 * 0.5f); + mixAudioStream(rightdry, eff2, last_out_mixer_effect2 * 0.5f, + out_mixer_effect2 * 0.5f); + } + + last_out_mixer_left = out_mixer_left; + last_out_mixer_right = out_mixer_right; + last_out_mixer_effect1 = out_mixer_effect1; + last_out_mixer_effect2 = out_mixer_effect2; + + if (out_mixer_end) { + stopping = true; + } + + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java b/jdk/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java new file mode 100644 index 00000000000..8f9effee351 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java @@ -0,0 +1,339 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * WAVE file reader for files using format WAVE_FORMAT_EXTENSIBLE (0xFFFE). + * + * @author Karl Helgason + */ +public class WaveExtensibleFileReader extends AudioFileReader { + + static private class GUID { + long i1; + + int s1; + + int s2; + + int x1; + + int x2; + + int x3; + + int x4; + + int x5; + + int x6; + + int x7; + + int x8; + + private GUID() { + } + + public GUID(long i1, int s1, int s2, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, int x8) { + this.i1 = i1; + this.s1 = s1; + this.s2 = s2; + this.x1 = x1; + this.x2 = x2; + this.x3 = x3; + this.x4 = x4; + this.x5 = x5; + this.x6 = x6; + this.x7 = x7; + this.x8 = x8; + } + + public static GUID read(RIFFReader riff) throws IOException { + GUID d = new GUID(); + d.i1 = riff.readUnsignedInt(); + d.s1 = riff.readUnsignedShort(); + d.s2 = riff.readUnsignedShort(); + d.x1 = riff.readUnsignedByte(); + d.x2 = riff.readUnsignedByte(); + d.x3 = riff.readUnsignedByte(); + d.x4 = riff.readUnsignedByte(); + d.x5 = riff.readUnsignedByte(); + d.x6 = riff.readUnsignedByte(); + d.x7 = riff.readUnsignedByte(); + d.x8 = riff.readUnsignedByte(); + return d; + } + + public int hashCode() { + return (int) i1; + } + + public boolean equals(Object obj) { + if (!(obj instanceof GUID)) + return false; + GUID t = (GUID) obj; + if (i1 != t.i1) + return false; + if (s1 != t.s1) + return false; + if (s2 != t.s2) + return false; + if (x1 != t.x1) + return false; + if (x2 != t.x2) + return false; + if (x3 != t.x3) + return false; + if (x4 != t.x4) + return false; + if (x5 != t.x5) + return false; + if (x6 != t.x6) + return false; + if (x7 != t.x7) + return false; + if (x8 != t.x8) + return false; + return true; + } + + } + + private static String[] channelnames = { "FL", "FR", "FC", "LF", + "BL", + "BR", // 5.1 + "FLC", "FLR", "BC", "SL", "SR", "TC", "TFL", "TFC", "TFR", "TBL", + "TBC", "TBR" }; + + private static String[] allchannelnames = { "w1", "w2", "w3", "w4", "w5", + "w6", "w7", "w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", + "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", "w24", + "w25", "w26", "w27", "w28", "w29", "w30", "w31", "w32", "w33", + "w34", "w35", "w36", "w37", "w38", "w39", "w40", "w41", "w42", + "w43", "w44", "w45", "w46", "w47", "w48", "w49", "w50", "w51", + "w52", "w53", "w54", "w55", "w56", "w57", "w58", "w59", "w60", + "w61", "w62", "w63", "w64" }; + + private static GUID SUBTYPE_PCM = new GUID(0x00000001, 0x0000, 0x0010, + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); + + private static GUID SUBTYPE_IEEE_FLOAT = new GUID(0x00000003, 0x0000, + 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); + + private String decodeChannelMask(long channelmask) { + StringBuffer sb = new StringBuffer(); + long m = 1; + for (int i = 0; i < allchannelnames.length; i++) { + if ((channelmask & m) != 0L) { + if (i < channelnames.length) { + sb.append(channelnames[i] + " "); + } else { + sb.append(allchannelnames[i] + " "); + } + } + m *= 2L; + } + if (sb.length() == 0) + return null; + return sb.substring(0, sb.length() - 1); + + } + + public AudioFileFormat getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + stream.mark(200); + AudioFileFormat format; + try { + format = internal_getAudioFileFormat(stream); + } finally { + stream.reset(); + } + return format; + } + + private AudioFileFormat internal_getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + + boolean fmt_found = false; + boolean data_found = false; + + int channels = 1; + long samplerate = 1; + // long framerate = 1; + int framesize = 1; + int bits = 1; + int validBitsPerSample = 1; + long channelMask = 0; + GUID subFormat = null; + + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + + if (chunk.getFormat().equals("fmt ")) { + fmt_found = true; + + int format = chunk.readUnsignedShort(); + if (format != 0xFFFE) + throw new UnsupportedAudioFileException(); // WAVE_FORMAT_EXTENSIBLE + // only + channels = chunk.readUnsignedShort(); + samplerate = chunk.readUnsignedInt(); + /* framerate = */chunk.readUnsignedInt(); + framesize = chunk.readUnsignedShort(); + bits = chunk.readUnsignedShort(); + int cbSize = chunk.readUnsignedShort(); + if (cbSize != 22) + throw new UnsupportedAudioFileException(); + validBitsPerSample = chunk.readUnsignedShort(); + if (validBitsPerSample > bits) + throw new UnsupportedAudioFileException(); + channelMask = chunk.readUnsignedInt(); + subFormat = GUID.read(chunk); + + } + if (chunk.getFormat().equals("data")) { + data_found = true; + break; + } + } + + if (!fmt_found) + throw new UnsupportedAudioFileException(); + if (!data_found) + throw new UnsupportedAudioFileException(); + + Map p = new HashMap(); + String s_channelmask = decodeChannelMask(channelMask); + if (s_channelmask != null) + p.put("channelOrder", s_channelmask); + if (channelMask != 0) + p.put("channelMask", channelMask); + // validBitsPerSample is only informational for PCM data, + // data is still encode according to SampleSizeInBits. + p.put("validBitsPerSample", validBitsPerSample); + + AudioFormat audioformat = null; + if (subFormat.equals(SUBTYPE_PCM)) { + if (bits == 8) { + audioformat = new AudioFormat(Encoding.PCM_UNSIGNED, + samplerate, bits, channels, framesize, samplerate, + false, p); + } else { + audioformat = new AudioFormat(Encoding.PCM_SIGNED, samplerate, + bits, channels, framesize, samplerate, false, p); + } + } else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) { + audioformat = new AudioFormat(AudioFloatConverter.PCM_FLOAT, + samplerate, bits, channels, framesize, samplerate, false, p); + } else + throw new UnsupportedAudioFileException(); + + AudioFileFormat fileformat = new AudioFileFormat( + AudioFileFormat.Type.WAVE, audioformat, + AudioSystem.NOT_SPECIFIED); + return fileformat; + } + + public AudioInputStream getAudioInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + AudioFileFormat format = getAudioFileFormat(stream); + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + if (chunk.getFormat().equals("data")) { + return new AudioInputStream(chunk, format.getFormat(), chunk + .getSize()); + } + } + throw new UnsupportedAudioFileException(); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException { + InputStream stream = url.openStream(); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException { + InputStream stream = new FileInputStream(file); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(url.openStream())); + } + + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(new FileInputStream( + file))); + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java new file mode 100644 index 00000000000..b096e4a5172 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java @@ -0,0 +1,166 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +/** + * Floating-point encoded (format 3) WAVE file loader. + * + * @author Karl Helgason + */ +public class WaveFloatFileReader extends AudioFileReader { + + public AudioFileFormat getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + stream.mark(200); + AudioFileFormat format; + try { + format = internal_getAudioFileFormat(stream); + } finally { + stream.reset(); + } + return format; + } + + private AudioFileFormat internal_getAudioFileFormat(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + + boolean fmt_found = false; + boolean data_found = false; + + int channels = 1; + long samplerate = 1; + int framesize = 1; + int bits = 1; + + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + + if (chunk.getFormat().equals("fmt ")) { + fmt_found = true; + + int format = chunk.readUnsignedShort(); + if (format != 3) // WAVE_FORMAT_IEEE_FLOAT only + throw new UnsupportedAudioFileException(); + channels = chunk.readUnsignedShort(); + samplerate = chunk.readUnsignedInt(); + /* framerate = */chunk.readUnsignedInt(); + framesize = chunk.readUnsignedShort(); + bits = chunk.readUnsignedShort(); + } + if (chunk.getFormat().equals("data")) { + data_found = true; + break; + } + } + + if (!fmt_found) + throw new UnsupportedAudioFileException(); + if (!data_found) + throw new UnsupportedAudioFileException(); + + AudioFormat audioformat = new AudioFormat( + AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels, + framesize, samplerate, false); + AudioFileFormat fileformat = new AudioFileFormat( + AudioFileFormat.Type.WAVE, audioformat, + AudioSystem.NOT_SPECIFIED); + return fileformat; + } + + public AudioInputStream getAudioInputStream(InputStream stream) + throws UnsupportedAudioFileException, IOException { + + AudioFileFormat format = getAudioFileFormat(stream); + RIFFReader riffiterator = new RIFFReader(stream); + if (!riffiterator.getFormat().equals("RIFF")) + throw new UnsupportedAudioFileException(); + if (!riffiterator.getType().equals("WAVE")) + throw new UnsupportedAudioFileException(); + while (riffiterator.hasNextChunk()) { + RIFFReader chunk = riffiterator.nextChunk(); + if (chunk.getFormat().equals("data")) { + return new AudioInputStream(chunk, format.getFormat(), + chunk.getSize()); + } + } + throw new UnsupportedAudioFileException(); + } + + public AudioFileFormat getAudioFileFormat(URL url) + throws UnsupportedAudioFileException, IOException { + InputStream stream = url.openStream(); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioFileFormat getAudioFileFormat(File file) + throws UnsupportedAudioFileException, IOException { + InputStream stream = new FileInputStream(file); + AudioFileFormat format; + try { + format = getAudioFileFormat(new BufferedInputStream(stream)); + } finally { + stream.close(); + } + return format; + } + + public AudioInputStream getAudioInputStream(URL url) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(url.openStream())); + } + + public AudioInputStream getAudioInputStream(File file) + throws UnsupportedAudioFileException, IOException { + return getAudioInputStream(new BufferedInputStream(new FileInputStream( + file))); + } +} diff --git a/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java b/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java new file mode 100644 index 00000000000..ff11bd46459 --- /dev/null +++ b/jdk/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java @@ -0,0 +1,147 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.media.sound; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFileFormat.Type; +import javax.sound.sampled.spi.AudioFileWriter; + +/** + * Floating-point encoded (format 3) WAVE file writer. + * + * @author Karl Helgason + */ +public class WaveFloatFileWriter extends AudioFileWriter { + + public Type[] getAudioFileTypes() { + return new Type[] { Type.WAVE }; + } + + public Type[] getAudioFileTypes(AudioInputStream stream) { + + if (!stream.getFormat().getEncoding().equals( + AudioFloatConverter.PCM_FLOAT)) + return new Type[0]; + return new Type[] { Type.WAVE }; + } + + private void checkFormat(AudioFileFormat.Type type, AudioInputStream stream) { + if (!Type.WAVE.equals(type)) + throw new IllegalArgumentException("File type " + type + + " not supported."); + if (!stream.getFormat().getEncoding().equals( + AudioFloatConverter.PCM_FLOAT)) + throw new IllegalArgumentException("File format " + + stream.getFormat() + " not supported."); + } + + public void write(AudioInputStream stream, RIFFWriter writer) + throws IOException { + + RIFFWriter fmt_chunk = writer.writeChunk("fmt "); + + AudioFormat format = stream.getFormat(); + fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT + fmt_chunk.writeUnsignedShort(format.getChannels()); + fmt_chunk.writeUnsignedInt((int) format.getSampleRate()); + fmt_chunk.writeUnsignedInt(((int) format.getFrameRate()) + * format.getFrameSize()); + fmt_chunk.writeUnsignedShort(format.getFrameSize()); + fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits()); + fmt_chunk.close(); + RIFFWriter data_chunk = writer.writeChunk("data"); + byte[] buff = new byte[1024]; + int len; + while ((len = stream.read(buff, 0, buff.length)) != -1) + data_chunk.write(buff, 0, len); + data_chunk.close(); + } + + private static class NoCloseOutputStream extends OutputStream { + OutputStream out; + + public NoCloseOutputStream(OutputStream out) { + this.out = out; + } + + public void write(int b) throws IOException { + out.write(b); + } + + public void flush() throws IOException { + out.flush(); + } + + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + } + + public void write(byte[] b) throws IOException { + out.write(b); + } + } + + private AudioInputStream toLittleEndian(AudioInputStream ais) { + AudioFormat format = ais.getFormat(); + AudioFormat targetFormat = new AudioFormat(format.getEncoding(), format + .getSampleRate(), format.getSampleSizeInBits(), format + .getChannels(), format.getFrameSize(), format.getFrameRate(), + false); + return AudioSystem.getAudioInputStream(targetFormat, ais); + } + + public int write(AudioInputStream stream, Type fileType, OutputStream out) + throws IOException { + + checkFormat(fileType, stream); + if (stream.getFormat().isBigEndian()) + stream = toLittleEndian(stream); + RIFFWriter writer = new RIFFWriter(new NoCloseOutputStream(out), "WAVE"); + write(stream, writer); + int fpointer = (int) writer.getFilePointer(); + writer.close(); + return fpointer; + } + + public int write(AudioInputStream stream, Type fileType, File out) + throws IOException { + checkFormat(fileType, stream); + if (stream.getFormat().isBigEndian()) + stream = toLittleEndian(stream); + RIFFWriter writer = new RIFFWriter(out, "WAVE"); + write(stream, writer); + int fpointer = (int) writer.getFilePointer(); + writer.close(); + return fpointer; + } + +} diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider index e0bbb102530..bffb952eb65 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider @@ -1,5 +1,5 @@ # Providers for midi devices -com.sun.media.sound.MixerSynthProvider com.sun.media.sound.RealTimeSequencerProvider com.sun.media.sound.MidiOutDeviceProvider com.sun.media.sound.MidiInDeviceProvider +com.sun.media.sound.SoftProvider diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader index 2daf82731a6..1d643a0e42e 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiFileReader @@ -1,3 +1,2 @@ # Providers for midi sequences com.sun.media.sound.StandardMidiFileReader -com.sun.media.sound.RmfFileReader diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader index 85a8af274f3..03c3df8201e 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.SoundbankReader @@ -1,2 +1,5 @@ # Providers for Soundbanks -com.sun.media.sound.HsbParser +com.sun.media.sound.SF2SoundbankReader +com.sun.media.sound.DLSSoundbankReader +com.sun.media.sound.AudioFileSoundbankReader +com.sun.media.sound.JARSoundbankReader diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader index db1cd3044f6..624dac1c026 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.AudioFileReader @@ -2,3 +2,5 @@ com.sun.media.sound.AuFileReader com.sun.media.sound.AiffFileReader com.sun.media.sound.WaveFileReader +com.sun.media.sound.WaveFloatFileReader +com.sun.media.sound.SoftMidiAudioFileReader diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider index 7f452444c64..2ea4f8b8040 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.FormatConversionProvider @@ -2,3 +2,4 @@ com.sun.media.sound.UlawCodec com.sun.media.sound.AlawCodec com.sun.media.sound.PCMtoPCMCodec +com.sun.media.sound.AudioFloatFormatConverter diff --git a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider index fc551ed398d..5414bee18fb 100644 --- a/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider +++ b/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.sampled.spi.MixerProvider @@ -1,5 +1,3 @@ # last mixer is default mixer com.sun.media.sound.PortMixerProvider -com.sun.media.sound.SimpleInputDeviceProvider -com.sun.media.sound.HeadspaceMixerProvider com.sun.media.sound.DirectAudioDeviceProvider diff --git a/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java b/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java new file mode 100644 index 00000000000..b612c0e8d59 --- /dev/null +++ b/jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.nio.file; + +import java.nio.file.CopyOption; + +/** + * Defines extended copy options supported on some platforms + * by Sun's provider implementation. + * + * @since 1.7 + */ + +public enum ExtendedCopyOption implements CopyOption { + /** + * The copy may be interrupted by the {@link Thread#interrupt interrupt} + * method. + */ + INTERRUPTIBLE, +} diff --git a/jdk/src/windows/native/sun/windows/awt_Multimon.h b/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java similarity index 53% rename from jdk/src/windows/native/sun/windows/awt_Multimon.h rename to jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java index f2b371e3499..25208d81257 100644 --- a/jdk/src/windows/native/sun/windows/awt_Multimon.h +++ b/jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,33 +22,29 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ -#ifndef _INC_MULTIMON_ -#define _INC_MULTIMON_ -#endif -// -// build defines that replace the regular APIs with our versions -// -#undef GetMonitorInfo -#undef GetSystemMetrics -#undef MonitorFromWindow -#undef MonitorFromRect -#undef MonitorFromPoint -#undef EnumDisplayMonitors -#undef EnumDisplayDevices -#include "awt_MMStub.h" +package com.sun.nio.file; -#define GetSystemMetricsMM _getSystemMetrics -#define MonitorFromWindow _monitorFromWindow -#define MonitorFromRect _monitorFromRect -#define MonitorFromPoint _monitorFromPoint -#define GetMonitorInfo _getMonitorInfo -#define EnumDisplayMonitors _enumDisplayMonitors -#define EnumDisplayDevices _enumDisplayDevices +import java.nio.file.OpenOption; +/** + * Defines extended open options supported on some platforms + * by Sun's provider implementation. + * + * @since 1.7 + */ -#define CountMonitors _countMonitors -#define CollectMonitors _collectMonitors -#define MonitorBounds _monitorBounds -#define MakeDCFromMonitor _makeDCFromMonitor -#define CreateWindowOnMonitor _createWindowOM +public enum ExtendedOpenOption implements OpenOption { + /** + * Prevent operations on the file that request read access. + */ + NOSHARE_READ, + /** + * Prevent operations on the file that request write access. + */ + NOSHARE_WRITE, + /** + * Prevent operations on the file that request delete access. + */ + NOSHARE_DELETE; +} diff --git a/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java b/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java new file mode 100644 index 00000000000..0f6ddc3276a --- /dev/null +++ b/jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java @@ -0,0 +1,43 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.nio.file; + +import java.nio.file.WatchEvent.Modifier; + +/** + * Defines extended watch event modifiers supported on some platforms + * by Sun's provider implementation. + * + * @since 1.7 + */ + +public enum ExtendedWatchEventModifier implements Modifier { + + /** + * Register a file tree instead of a single directory. + */ + FILE_TREE, +} diff --git a/jdk/src/share/classes/com/sun/nio/file/SensitivityWatchEventModifier.java b/jdk/src/share/classes/com/sun/nio/file/SensitivityWatchEventModifier.java new file mode 100644 index 00000000000..57ab111b00b --- /dev/null +++ b/jdk/src/share/classes/com/sun/nio/file/SensitivityWatchEventModifier.java @@ -0,0 +1,62 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.nio.file; + +import java.nio.file.WatchEvent.Modifier; + +/** + * Defines the sensitivity levels when registering objects with a + * watch service implementation that polls the file system. + * + * @since 1.7 + */ + +public enum SensitivityWatchEventModifier implements Modifier { + /** + * High sensitivity. + */ + HIGH(2), + /** + * Medium sensitivity. + */ + MEDIUM(10), + /** + * Low sensitivity. + */ + LOW(30); + + /** + * Returns the sensitivity in seconds. + */ + public int sensitivityValueInSeconds() { + return sensitivity; + } + + private final int sensitivity; + private SensitivityWatchEventModifier(int sensitivity) { + this.sensitivity = sensitivity; + } +} diff --git a/jdk/src/share/classes/java/awt/Choice.java b/jdk/src/share/classes/java/awt/Choice.java index ea46b8d772e..64c46b53da4 100644 --- a/jdk/src/share/classes/java/awt/Choice.java +++ b/jdk/src/share/classes/java/awt/Choice.java @@ -228,7 +228,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { pItems.insertElementAt(item, index); ChoicePeer peer = (ChoicePeer)this.peer; if (peer != null) { - peer.addItem(item, index); + peer.add(item, index); } // no selection or selection shifted up if (selectedIndex < 0 || selectedIndex >= index) { diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index 8896ec248b4..afe091dccef 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -65,8 +65,10 @@ import java.applet.Applet; import sun.security.action.GetPropertyAction; import sun.awt.AppContext; +import sun.awt.AWTAccessor; import sun.awt.ConstrainableGraphics; import sun.awt.SubRegionShowable; +import sun.awt.SunToolkit; import sun.awt.WindowClosingListener; import sun.awt.CausedFocusEvent; import sun.awt.EmbeddedFrame; @@ -758,22 +760,26 @@ public abstract class Component implements ImageObserver, MenuContainer, * The shape set with the applyCompoundShape() method. It uncludes the result * of the HW/LW mixing related shape computation. It may also include * the user-specified shape of the component. + * The 'null' value means the component has normal shape (or has no shape at all) + * and applyCompoundShape() will skip the following shape identical to normal. */ private transient Region compoundShape = null; + /* + * Represents the shape of this lightweight component to be cut out from + * heavyweight components should they intersect. Possible values: + * 1. null - consider the shape rectangular + * 2. EMPTY_REGION - nothing gets cut out (children still get cut out) + * 3. non-empty - this shape gets cut out. + */ + private transient Region mixingCutoutRegion = null; + /* * Indicates whether addNotify() is complete * (i.e. the peer is created). */ private transient boolean isAddNotifyComplete = false; - private static final PropertyChangeListener opaquePropertyChangeListener = - new PropertyChangeListener() { - public void propertyChange(java.beans.PropertyChangeEvent evt) { - ((Component)evt.getSource()).mixOnOpaqueChanging(); - } - }; - /** * Should only be used in subclass getBounds to check that part of bounds * is actualy changing @@ -793,6 +799,39 @@ public abstract class Component implements ImageObserver, MenuContainer, } } + static { + AWTAccessor.setComponentAccessor(new AWTAccessor.ComponentAccessor() { + public void setMixingCutoutShape(Component comp, Shape shape) { + Region region = shape == null ? null : + Region.getInstance(shape, null); + + synchronized (comp.getTreeLock()) { + boolean needShowing = false; + boolean needHiding = false; + + if (!comp.isNonOpaqueForMixing()) { + needHiding = true; + } + + comp.mixingCutoutRegion = region; + + if (!comp.isNonOpaqueForMixing()) { + needShowing = true; + } + + if (comp.isMixingNeeded()) { + if (needHiding) { + comp.mixOnHiding(comp.isLightweight()); + } + if (needShowing) { + comp.mixOnShowing(); + } + } + } + } + }); + } + /** * Constructs a new component. Class Component can be * extended directly to create a lightweight component that does not @@ -1306,7 +1345,7 @@ public abstract class Component implements ImageObserver, MenuContainer, enabled = true; ComponentPeer peer = this.peer; if (peer != null) { - peer.enable(); + peer.setEnabled(true); if (visible) { updateCursorImmediately(); } @@ -1355,7 +1394,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } ComponentPeer peer = this.peer; if (peer != null) { - peer.disable(); + peer.setEnabled(false); if (visible) { updateCursorImmediately(); } @@ -1447,7 +1486,7 @@ public abstract class Component implements ImageObserver, MenuContainer, mixOnShowing(); ComponentPeer peer = this.peer; if (peer != null) { - peer.show(); + peer.setVisible(true); createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, this, parent, HierarchyEvent.SHOWING_CHANGED, @@ -1517,7 +1556,7 @@ public abstract class Component implements ImageObserver, MenuContainer, } ComponentPeer peer = this.peer; if (peer != null) { - peer.hide(); + peer.setVisible(false); createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, this, parent, HierarchyEvent.SHOWING_CHANGED, @@ -2414,7 +2453,7 @@ public abstract class Component implements ImageObserver, MenuContainer, if (dim == null || !(isPreferredSizeSet() || isValid())) { synchronized (getTreeLock()) { prefSize = (peer != null) ? - peer.preferredSize() : + peer.getPreferredSize() : getMinimumSize(); dim = prefSize; } @@ -2484,7 +2523,7 @@ public abstract class Component implements ImageObserver, MenuContainer, if (dim == null || !(isMinimumSizeSet() || isValid())) { synchronized (getTreeLock()) { minSize = (peer != null) ? - peer.minimumSize() : + peer.getMinimumSize() : size(); dim = minSize; } @@ -3171,7 +3210,7 @@ public abstract class Component implements ImageObserver, MenuContainer, private Insets getInsets_NoClientCode() { ComponentPeer peer = this.peer; if (peer instanceof ContainerPeer) { - return (Insets)((ContainerPeer)peer).insets().clone(); + return (Insets)((ContainerPeer)peer).getInsets().clone(); } return new Insets(0, 0, 0, 0); } @@ -6643,7 +6682,6 @@ public abstract class Component implements ImageObserver, MenuContainer, } if (!isAddNotifyComplete) { - addPropertyChangeListener("opaque", opaquePropertyChangeListener); mixOnShowing(); } @@ -6722,7 +6760,7 @@ public abstract class Component implements ImageObserver, MenuContainer, // Hide peer first to stop system events such as cursor moves. if (visible) { - p.hide(); + p.setVisible(false); } peer = null; // Stop peer updates. @@ -6735,9 +6773,11 @@ public abstract class Component implements ImageObserver, MenuContainer, p.dispose(); mixOnHiding(isLightweight); - removePropertyChangeListener("opaque", opaquePropertyChangeListener); isAddNotifyComplete = false; + // Nullifying compoundShape means that the component has normal shape + // (or has no shape at all). + this.compoundShape = null; } if (hierarchyListener != null || @@ -9401,10 +9441,9 @@ public abstract class Component implements ImageObserver, MenuContainer, * Null-layout of the container or absence of the container mean * the bounds of the component are final and can be trusted. */ - private boolean areBoundsValid() { + final boolean areBoundsValid() { Container cont = getContainer(); - return cont == null || cont.isValid() - || cont.getLayout() == null; + return cont == null || cont.isValid() || cont.getLayout() == null; } /** @@ -9413,6 +9452,14 @@ public abstract class Component implements ImageObserver, MenuContainer, */ void applyCompoundShape(Region shape) { checkTreeLock(); + + if (!areBoundsValid()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); + } + return; + } + if (!isLightweight()) { ComponentPeer peer = getPeer(); if (peer != null) { @@ -9422,22 +9469,31 @@ public abstract class Component implements ImageObserver, MenuContainer, // with some incorrect Region object with loX being // greater than the hiX for instance. if (shape.isEmpty()) { - shape = Region.getInstanceXYWH(0, 0, 0, 0); + shape = Region.EMPTY_REGION; } + // Note: the shape is not really copied/cloned. We create // the Region object ourselves, so there's no any possibility // to modify the object outside of the mixing code. - this.compoundShape = shape; - - if (areBoundsValid()) { + // Nullifying compoundShape means that the component has normal shape + // (or has no shape at all). + if (shape.equals(getNormalShape())) { + if (this.compoundShape == null) { + return; + } + this.compoundShape = null; + peer.applyShape(null); + } else { + if (shape.equals(getAppliedShape())) { + return; + } + this.compoundShape = shape; Point compAbsolute = getLocationOnWindow(); - if (mixingLog.isLoggable(Level.FINER)) { mixingLog.fine("this = " + this + - "; compAbsolute=" + compAbsolute + "; shape=" + shape); + "; compAbsolute=" + compAbsolute + "; shape=" + shape); } - peer.applyShape(shape.getTranslatedRegion(-compAbsolute.x, -compAbsolute.y)); } } @@ -9460,7 +9516,7 @@ public abstract class Component implements ImageObserver, MenuContainer, Point curLocation = getLocation(); for (Container parent = getContainer(); - parent != null; + parent != null && !(parent instanceof Window); parent = parent.getContainer()) { curLocation.x += parent.getX(); @@ -9486,7 +9542,28 @@ public abstract class Component implements ImageObserver, MenuContainer, ); } - private int getSiblingIndexAbove() { + /** + * Returns the "opaque shape" of the component. + * + * The opaque shape of a lightweight components is the actual shape that + * needs to be cut off of the heavyweight components in order to mix this + * lightweight component correctly with them. + * + * The method is overriden in the java.awt.Container to handle non-opaque + * containers containing opaque children. + * + * See 6637655 for details. + */ + Region getOpaqueShape() { + checkTreeLock(); + if (mixingCutoutRegion != null) { + return mixingCutoutRegion; + } else { + return getNormalShape(); + } + } + + final int getSiblingIndexAbove() { checkTreeLock(); Container parent = getContainer(); if (parent == null) { @@ -9498,7 +9575,7 @@ public abstract class Component implements ImageObserver, MenuContainer, return nextAbove < 0 ? -1 : nextAbove; } - private int getSiblingIndexBelow() { + final int getSiblingIndexBelow() { checkTreeLock(); Container parent = getContainer(); if (parent == null) { @@ -9510,6 +9587,11 @@ public abstract class Component implements ImageObserver, MenuContainer, return nextBelow >= parent.getComponentCount() ? -1 : nextBelow; } + final boolean isNonOpaqueForMixing() { + return mixingCutoutRegion != null && + mixingCutoutRegion.isEmpty(); + } + private Region calculateCurrentShape() { checkTreeLock(); Region s = getNormalShape(); @@ -9532,8 +9614,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * implementation of the Container class. */ Component c = cont.getComponent(index); - if (c.isLightweight() && c.isShowing() && c.isOpaque()) { - s = s.getDifference(c.getNormalShape()); + if (c.isLightweight() && c.isShowing()) { + s = s.getDifference(c.getOpaqueShape()); } } @@ -9558,6 +9640,9 @@ public abstract class Component implements ImageObserver, MenuContainer, void applyCurrentShape() { checkTreeLock(); if (!areBoundsValid()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); + } return; // Because applyCompoundShape() ignores such components anyway } if (mixingLog.isLoggable(Level.FINE)) { @@ -9576,16 +9661,54 @@ public abstract class Component implements ImageObserver, MenuContainer, applyCompoundShape(getAppliedShape().getDifference(s)); } + private final void applyCurrentShapeBelowMe() { + checkTreeLock(); + Container parent = getContainer(); + if (parent != null && parent.isShowing()) { + // First, reapply shapes of my siblings + parent.recursiveApplyCurrentShape(getSiblingIndexBelow()); + + // Second, if my container is non-opaque, reapply shapes of siblings of my container + Container parent2 = parent.getContainer(); + while (!parent.isOpaque() && parent2 != null) { + parent2.recursiveApplyCurrentShape(parent.getSiblingIndexBelow()); + + parent = parent2; + parent2 = parent.getContainer(); + } + } + } + + final void subtractAndApplyShapeBelowMe() { + checkTreeLock(); + Container parent = getContainer(); + if (parent != null && isShowing()) { + Region opaqueShape = getOpaqueShape(); + + // First, cut my siblings + parent.recursiveSubtractAndApplyShape(opaqueShape, getSiblingIndexBelow()); + + // Second, if my container is non-opaque, cut siblings of my container + Container parent2 = parent.getContainer(); + while (!parent.isOpaque() && parent2 != null) { + parent2.recursiveSubtractAndApplyShape(opaqueShape, parent.getSiblingIndexBelow()); + + parent = parent2; + parent2 = parent.getContainer(); + } + } + } + void mixOnShowing() { synchronized (getTreeLock()) { if (mixingLog.isLoggable(Level.FINE)) { mixingLog.fine("this = " + this); } + if (!isMixingNeeded()) { + return; + } if (isLightweight()) { - Container parent = getContainer(); - if (parent != null && isShowing() && isOpaque()) { - parent.recursiveSubtractAndApplyShape(getNormalShape(), getSiblingIndexBelow()); - } + subtractAndApplyShapeBelowMe(); } else { applyCurrentShape(); } @@ -9599,12 +9722,12 @@ public abstract class Component implements ImageObserver, MenuContainer, if (mixingLog.isLoggable(Level.FINE)) { mixingLog.fine("this = " + this + "; isLightweight = " + isLightweight); } + if (!isMixingNeeded()) { + return; + } if (isLightweight) { - Container parent = getContainer(); - if (parent != null) { - parent.recursiveApplyCurrentShape(getSiblingIndexBelow()); - } - } //XXX: else applyNormalShape() ??? + applyCurrentShapeBelowMe(); + } } } @@ -9613,11 +9736,11 @@ public abstract class Component implements ImageObserver, MenuContainer, if (mixingLog.isLoggable(Level.FINE)) { mixingLog.fine("this = " + this); } + if (!isMixingNeeded()) { + return; + } if (isLightweight()) { - Container parent = getContainer(); - if (parent != null) { - parent.recursiveApplyCurrentShape(parent.getComponentZOrder(this)); - } + applyCurrentShapeBelowMe(); } else { applyCurrentShape(); } @@ -9633,11 +9756,13 @@ public abstract class Component implements ImageObserver, MenuContainer, mixingLog.fine("this = " + this + "; oldZorder=" + oldZorder + "; newZorder=" + newZorder + "; parent=" + parent); } - + if (!isMixingNeeded()) { + return; + } if (isLightweight()) { if (becameHigher) { - if (parent != null && isShowing() && isOpaque()) { - parent.recursiveSubtractAndApplyShape(getNormalShape(), getSiblingIndexBelow(), oldZorder); + if (parent != null && isShowing()) { + parent.recursiveSubtractAndApplyShape(getOpaqueShape(), getSiblingIndexBelow(), oldZorder); } } else { if (parent != null) { @@ -9653,8 +9778,8 @@ public abstract class Component implements ImageObserver, MenuContainer, for (int index = oldZorder; index < newZorder; index++) { Component c = parent.getComponent(index); - if (c.isLightweight() && c.isShowing() && c.isOpaque()) { - shape = shape.getDifference(c.getNormalShape()); + if (c.isLightweight() && c.isShowing()) { + shape = shape.getDifference(c.getOpaqueShape()); } } applyCompoundShape(shape); @@ -9664,21 +9789,42 @@ public abstract class Component implements ImageObserver, MenuContainer, } } - void mixOnOpaqueChanging() { - if (mixingLog.isLoggable(Level.FINE)) { - mixingLog.fine("this = " + this); - } - if (isOpaque()) { - mixOnShowing(); - } else { - mixOnHiding(isLightweight()); - } - } - void mixOnValidating() { // This method gets overriden in the Container. Obviously, a plain // non-container components don't need to handle validation. } + final boolean isMixingNeeded() { + if (SunToolkit.getSunAwtDisableMixing()) { + if (mixingLog.isLoggable(Level.FINEST)) { + mixingLog.finest("this = " + this + "; Mixing disabled via sun.awt.disableMixing"); + } + return false; + } + if (!areBoundsValid()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("this = " + this + "; areBoundsValid = " + areBoundsValid()); + } + return false; + } + Window window = getContainingWindow(); + if (window != null) { + if (!window.hasHeavyweightDescendants() || !window.hasLightweightDescendants()) { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.fine("containing window = " + window + + "; has h/w descendants = " + window.hasHeavyweightDescendants() + + "; has l/w descendants = " + window.hasLightweightDescendants()); + } + return false; + } + } else { + if (mixingLog.isLoggable(Level.FINE)) { + mixingLog.finest("this = " + this + "; containing window is null"); + } + return false; + } + return true; + } + // ****************** END OF MIXING CODE ******************************** } diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index c302e4b0edc..04425d5a45a 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -343,7 +343,7 @@ public class Container extends Component { ComponentPeer peer = this.peer; if (peer instanceof ContainerPeer) { ContainerPeer cpeer = (ContainerPeer)peer; - return (Insets)cpeer.insets().clone(); + return (Insets)cpeer.getInsets().clone(); } return new Insets(0, 0, 0, 0); } @@ -569,7 +569,7 @@ public class Container extends Component { * @return true if there is at least one heavyweight children in a container, false otherwise * @since 1.5 */ - private boolean hasHeavyweightDescendants() { + final boolean hasHeavyweightDescendants() { checkTreeLock(); return numOfHWComponents > 0; } @@ -580,7 +580,7 @@ public class Container extends Component { * @return true if there is at least one lightweight children in a container, false otherwise * @since 1.7 */ - private boolean hasLightweightDescendants() { + final boolean hasLightweightDescendants() { checkTreeLock(); return numOfLWComponents > 0; } @@ -3861,6 +3861,28 @@ public class Container extends Component { return -1; } + /* + * This method is overriden to handle opaque children in non-opaque + * containers. + */ + @Override + final Region getOpaqueShape() { + checkTreeLock(); + if (isLightweight() && isNonOpaqueForMixing() + && hasLightweightDescendants()) + { + Region s = Region.EMPTY_REGION; + for (int index = 0; index < getComponentCount(); index++) { + Component c = getComponent(index); + if (c.isLightweight() && c.isShowing()) { + s = s.getUnion(c.getOpaqueShape()); + } + } + return s.getIntersection(getNormalShape()); + } + return super.getOpaqueShape(); + } + final void recursiveSubtractAndApplyShape(Region shape) { recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex()); } @@ -3878,6 +3900,15 @@ public class Container extends Component { if (fromZorder == -1) { return; } + if (shape.isEmpty()) { + return; + } + // An invalid container with not-null layout should be ignored + // by the mixing code, the container will be validated later + // and the mixing code will be executed later. + if (getLayout() != null && !isValid()) { + return; + } for (int index = fromZorder; index <= toZorder; index++) { Component comp = getComponent(index); if (!comp.isLightweight()) { @@ -3906,10 +3937,19 @@ public class Container extends Component { if (fromZorder == -1) { return; } + // An invalid container with not-null layout should be ignored + // by the mixing code, the container will be validated later + // and the mixing code will be executed later. + if (getLayout() != null && !isValid()) { + return; + } for (int index = fromZorder; index <= toZorder; index++) { Component comp = getComponent(index); if (!comp.isLightweight()) { comp.applyCurrentShape(); + if (comp instanceof Container && ((Container)comp).getLayout() == null) { + ((Container)comp).recursiveApplyCurrentShape(); + } } else if (comp instanceof Container && ((Container)comp).hasHeavyweightDescendants()) { ((Container)comp).recursiveApplyCurrentShape(); @@ -3931,7 +3971,7 @@ public class Container extends Component { if (comp.isVisible()) { ComponentPeer peer = comp.getPeer(); if (peer != null) { - peer.show(); + peer.setVisible(true); } } } @@ -3952,7 +3992,7 @@ public class Container extends Component { if (comp.isVisible()) { ComponentPeer peer = comp.getPeer(); if (peer != null) { - peer.hide(); + peer.setVisible(false); } } } @@ -4000,6 +4040,10 @@ public class Container extends Component { mixingLog.fine("this = " + this); } + if (!isMixingNeeded()) { + return; + } + boolean isLightweight = isLightweight(); if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) { @@ -4034,6 +4078,9 @@ public class Container extends Component { if (mixingLog.isLoggable(Level.FINE)) { mixingLog.fine("this = " + this); } + + boolean isMixingNeeded = isMixingNeeded(); + if (isLightweight() && hasHeavyweightDescendants()) { final Point origin = new Point(getX(), getY()); for (Container cont = getContainer(); @@ -4044,7 +4091,18 @@ public class Container extends Component { } recursiveRelocateHeavyweightChildren(origin); + + if (!isMixingNeeded) { + return; + } + + recursiveApplyCurrentShape(); } + + if (!isMixingNeeded) { + return; + } + super.mixOnReshaping(); } } @@ -4057,6 +4115,10 @@ public class Container extends Component { "; oldZ=" + oldZorder + "; newZ=" + newZorder); } + if (!isMixingNeeded()) { + return; + } + boolean becameHigher = newZorder < oldZorder; if (becameHigher && isLightweight() && hasHeavyweightDescendants()) { @@ -4073,10 +4135,18 @@ public class Container extends Component { mixingLog.fine("this = " + this); } + if (!isMixingNeeded()) { + return; + } + if (hasHeavyweightDescendants()) { recursiveApplyCurrentShape(); } + if (isLightweight() && isNonOpaqueForMixing()) { + subtractAndApplyShapeBelowMe(); + } + super.mixOnValidating(); } } diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index 2104a64b742..310e52350e1 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -941,7 +941,7 @@ public class Dialog extends Window { // does not invoke the super.show(). So wried... :( mixOnShowing(); - peer.show(); // now guaranteed never to block + peer.setVisible(true); // now guaranteed never to block if (isModalBlocked()) { modalBlocker.toFront(); } diff --git a/jdk/src/share/classes/java/awt/EventDispatchThread.java b/jdk/src/share/classes/java/awt/EventDispatchThread.java index c9b77b0b27e..f35ff913a7d 100644 --- a/jdk/src/share/classes/java/awt/EventDispatchThread.java +++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java @@ -300,119 +300,19 @@ class EventDispatchThread extends Thread { } // Can get and throw only unchecked exceptions catch (RuntimeException e) { - processException(e, modalFiltersCount > 0); + processException(e); } catch (Error e) { - processException(e, modalFiltersCount > 0); + processException(e); } return true; } - private void processException(Throwable e, boolean isModal) { + private void processException(Throwable e) { if (eventLog.isLoggable(Level.FINE)) { - eventLog.log(Level.FINE, "Processing exception: " + e + - ", isModal = " + isModal); + eventLog.log(Level.FINE, "Processing exception: " + e); } - if (!handleException(e)) { - // See bug ID 4499199. - // If we are in a modal dialog, we cannot throw - // an exception for the ThreadGroup to handle (as added - // in RFE 4063022). If we did, the message pump of - // the modal dialog would be interrupted. - // We instead choose to handle the exception ourselves. - // It may be useful to add either a runtime flag or API - // later if someone would like to instead dispose the - // dialog and allow the thread group to handle it. - if (isModal) { - System.err.println( - "Exception occurred during event dispatching:"); - e.printStackTrace(); - } else if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } else if (e instanceof Error) { - throw (Error)e; - } - } - } - - private static final String handlerPropName = "sun.awt.exception.handler"; - private static String handlerClassName = null; - private static String NO_HANDLER = new String(); - - /** - * Handles an exception thrown in the event-dispatch thread. - * - *

    If the system property "sun.awt.exception.handler" is defined, then - * when this method is invoked it will attempt to do the following: - * - *

      - *
    1. Load the class named by the value of that property, using the - * current thread's context class loader, - *
    2. Instantiate that class using its zero-argument constructor, - *
    3. Find the resulting handler object's public void handle - * method, which should take a single argument of type - * Throwable, and - *
    4. Invoke the handler's handle method, passing it the - * thrown argument that was passed to this method. - *
    - * - * If any of the first three steps fail then this method will return - * false and all following invocations of this method will return - * false immediately. An exception thrown by the handler object's - * handle will be caught, and will cause this method to return - * false. If the handler's handle method is successfully - * invoked, then this method will return true. This method will - * never throw any sort of exception. - * - *

    Note: This method is a temporary hack to work around the - * absence of a real API that provides the ability to replace the - * event-dispatch thread. The magic "sun.awt.exception.handler" property - * will be removed in a future release. - * - * @param thrown The Throwable that was thrown in the event-dispatch - * thread - * - * @return false if any of the above steps failed, otherwise - * true - */ - private boolean handleException(Throwable thrown) { - - try { - - if (handlerClassName == NO_HANDLER) { - return false; /* Already tried, and failed */ - } - - /* Look up the class name */ - if (handlerClassName == null) { - handlerClassName = ((String) AccessController.doPrivileged( - new GetPropertyAction(handlerPropName))); - if (handlerClassName == null) { - handlerClassName = NO_HANDLER; /* Do not try this again */ - return false; - } - } - - /* Load the class, instantiate it, and find its handle method */ - Method m; - Object h; - try { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Class c = Class.forName(handlerClassName, true, cl); - m = c.getMethod("handle", new Class[] { Throwable.class }); - h = c.newInstance(); - } catch (Throwable x) { - handlerClassName = NO_HANDLER; /* Do not try this again */ - return false; - } - - /* Finally, invoke the handler */ - m.invoke(h, new Object[] { thrown }); - - } catch (Throwable x) { - return false; - } - - return true; + getUncaughtExceptionHandler().uncaughtException(this, e); + // don't rethrow the exception to avoid EDT recreation } boolean isDispatching(EventQueue eq) { diff --git a/jdk/src/share/classes/java/awt/List.java b/jdk/src/share/classes/java/awt/List.java index 2ce9af6c0a6..5fd4e46313f 100644 --- a/jdk/src/share/classes/java/awt/List.java +++ b/jdk/src/share/classes/java/awt/List.java @@ -378,7 +378,7 @@ public class List extends Component implements ItemSelectable, Accessible { ListPeer peer = (ListPeer)this.peer; if (peer != null) { - peer.addItem(item, index); + peer.add(item, index); } } @@ -413,7 +413,7 @@ public class List extends Component implements ItemSelectable, Accessible { public synchronized void clear() { ListPeer peer = (ListPeer)this.peer; if (peer != null) { - peer.clear(); + peer.removeAll(); } items = new Vector(); selected = new int[0]; @@ -718,7 +718,7 @@ public class List extends Component implements ItemSelectable, Accessible { multipleMode = b; ListPeer peer = (ListPeer)this.peer; if (peer != null) { - peer.setMultipleSelections(b); + peer.setMultipleMode(b); } } } @@ -768,7 +768,7 @@ public class List extends Component implements ItemSelectable, Accessible { synchronized (getTreeLock()) { ListPeer peer = (ListPeer)this.peer; return (peer != null) ? - peer.preferredSize(rows) : + peer.getPreferredSize(rows) : super.preferredSize(); } } @@ -818,7 +818,7 @@ public class List extends Component implements ItemSelectable, Accessible { synchronized (getTreeLock()) { ListPeer peer = (ListPeer)this.peer; return (peer != null) ? - peer.minimumSize(rows) : + peer.getMinimumSize(rows) : super.minimumSize(); } } diff --git a/jdk/src/share/classes/java/awt/MenuItem.java b/jdk/src/share/classes/java/awt/MenuItem.java index 99ddac75d15..71dd760a9bd 100644 --- a/jdk/src/share/classes/java/awt/MenuItem.java +++ b/jdk/src/share/classes/java/awt/MenuItem.java @@ -268,7 +268,7 @@ public class MenuItem extends MenuComponent implements Accessible { enabled = true; MenuItemPeer peer = (MenuItemPeer)this.peer; if (peer != null) { - peer.enable(); + peer.setEnabled(true); } } @@ -294,7 +294,7 @@ public class MenuItem extends MenuComponent implements Accessible { enabled = false; MenuItemPeer peer = (MenuItemPeer)this.peer; if (peer != null) { - peer.disable(); + peer.setEnabled(false); } } diff --git a/jdk/src/share/classes/java/awt/Robot.java b/jdk/src/share/classes/java/awt/Robot.java index 2ce6a2686f1..94c71283cee 100644 --- a/jdk/src/share/classes/java/awt/Robot.java +++ b/jdk/src/share/classes/java/awt/Robot.java @@ -70,10 +70,7 @@ public class Robot { private RobotPeer peer; private boolean isAutoWaitForIdle = false; private int autoDelay = 0; - private static final int LEGAL_BUTTON_MASK = - InputEvent.BUTTON1_MASK| - InputEvent.BUTTON2_MASK| - InputEvent.BUTTON3_MASK; + private static int LEGAL_BUTTON_MASK; // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage() private Point gdLoc; @@ -98,6 +95,19 @@ public class Robot { } init(GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice()); + int tmpMask = 0; + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + for (int i = 0; i < peer.getNumberOfButtons(); i++){ + tmpMask |= InputEvent.getMaskForButton(i+1); + } + } + tmpMask |= InputEvent.BUTTON1_MASK| + InputEvent.BUTTON2_MASK| + InputEvent.BUTTON3_MASK| + InputEvent.BUTTON1_DOWN_MASK| + InputEvent.BUTTON2_DOWN_MASK| + InputEvent.BUTTON3_DOWN_MASK; + LEGAL_BUTTON_MASK = tmpMask; } /** @@ -187,18 +197,55 @@ public class Robot { /** * Presses one or more mouse buttons. The mouse buttons should - * be released using the mouseRelease method. + * be released using the {@link #mouseRelease(int)} method. * - * @param buttons the Button mask; a combination of one or more - * of these flags: + * @param buttons the Button mask; a combination of one or more + * mouse button masks. + *

    + * It is allowed to use only a combination of valid values as a {@code buttons} parameter. + * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} + * and values returned by the + * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method. + * + * The valid combination also depends on a + * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows: *

      - *
    • InputEvent.BUTTON1_MASK - *
    • InputEvent.BUTTON2_MASK - *
    • InputEvent.BUTTON3_MASK + *
    • If support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to use only the following standard button masks: + * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK}, + * {@code InputEvent.BUTTON3_DOWN_MASK}. + *
    • If support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to use the standard button masks + * and masks for existing extended mouse buttons, if the mouse has more then three buttons. + * In that way, it is allowed to use the button masks corresponding to the buttons + * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. + *
      + * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} + * method to obtain the mask for any mouse button by its number. *
    - * @throws IllegalArgumentException if the button mask is not a - * valid combination + *

    + * The following standard button masks are also accepted: + *

      + *
    • {@code InputEvent.BUTTON1_MASK} + *
    • {@code InputEvent.BUTTON2_MASK} + *
    • {@code InputEvent.BUTTON3_MASK} + *
    + * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} instead. + * Either extended {@code _DOWN_MASK} or old {@code _MASK} values + * should be used, but both those models should not be mixed. + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java * @see #mouseRelease(int) + * @see InputEvent#getMaskForButton(int) + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see java.awt.event.MouseEvent */ public synchronized void mousePress(int buttons) { checkButtonsArgument(buttons); @@ -209,16 +256,53 @@ public class Robot { /** * Releases one or more mouse buttons. * - * @param buttons the Button mask; a combination of one or more - * of these flags: + * @param buttons the Button mask; a combination of one or more + * mouse button masks. + *

    + * It is allowed to use only a combination of valid values as a {@code buttons} parameter. + * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} + * and values returned by the + * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method. + * + * The valid combination also depends on a + * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows: *

      - *
    • InputEvent.BUTTON1_MASK - *
    • InputEvent.BUTTON2_MASK - *
    • InputEvent.BUTTON3_MASK + *
    • If the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to use only the following standard button masks: + * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK}, + * {@code InputEvent.BUTTON3_DOWN_MASK}. + *
    • If the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to use the standard button masks + * and masks for existing extended mouse buttons, if the mouse has more then three buttons. + * In that way, it is allowed to use the button masks corresponding to the buttons + * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. + *
      + * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} + * method to obtain the mask for any mouse button by its number. *
    + *

    + * The following standard button masks are also accepted: + *

      + *
    • {@code InputEvent.BUTTON1_MASK} + *
    • {@code InputEvent.BUTTON2_MASK} + *
    • {@code InputEvent.BUTTON3_MASK} + *
    + * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} instead. + * Either extended {@code _DOWN_MASK} or old {@code _MASK} values + * should be used, but both those models should not be mixed. + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java * @see #mousePress(int) - * @throws IllegalArgumentException if the button mask is not a valid - * combination + * @see InputEvent#getMaskForButton(int) + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see java.awt.event.MouseEvent */ public synchronized void mouseRelease(int buttons) { checkButtonsArgument(buttons); diff --git a/jdk/src/share/classes/java/awt/TextArea.java b/jdk/src/share/classes/java/awt/TextArea.java index 6d2f8ca0ced..8cf1c2ced00 100644 --- a/jdk/src/share/classes/java/awt/TextArea.java +++ b/jdk/src/share/classes/java/awt/TextArea.java @@ -321,7 +321,7 @@ public class TextArea extends TextComponent { public synchronized void insertText(String str, int pos) { TextAreaPeer peer = (TextAreaPeer)this.peer; if (peer != null) { - peer.insertText(str, pos); + peer.insert(str, pos); } else { text = text.substring(0, pos) + str + text.substring(pos); } @@ -385,7 +385,7 @@ public class TextArea extends TextComponent { public synchronized void replaceText(String str, int start, int end) { TextAreaPeer peer = (TextAreaPeer)this.peer; if (peer != null) { - peer.replaceText(str, start, end); + peer.replaceRange(str, start, end); } else { text = text.substring(0, start) + str + text.substring(end); } @@ -500,7 +500,7 @@ public class TextArea extends TextComponent { synchronized (getTreeLock()) { TextAreaPeer peer = (TextAreaPeer)this.peer; return (peer != null) ? - peer.preferredSize(rows, columns) : + peer.getPreferredSize(rows, columns) : super.preferredSize(); } } @@ -552,7 +552,7 @@ public class TextArea extends TextComponent { synchronized (getTreeLock()) { TextAreaPeer peer = (TextAreaPeer)this.peer; return (peer != null) ? - peer.minimumSize(rows, columns) : + peer.getMinimumSize(rows, columns) : super.minimumSize(); } } diff --git a/jdk/src/share/classes/java/awt/TextField.java b/jdk/src/share/classes/java/awt/TextField.java index b2659aa99f0..e5e809e1744 100644 --- a/jdk/src/share/classes/java/awt/TextField.java +++ b/jdk/src/share/classes/java/awt/TextField.java @@ -281,7 +281,7 @@ public class TextField extends TextComponent { echoChar = c; TextFieldPeer peer = (TextFieldPeer)this.peer; if (peer != null) { - peer.setEchoCharacter(c); + peer.setEchoChar(c); } } } @@ -376,7 +376,7 @@ public class TextField extends TextComponent { synchronized (getTreeLock()) { TextFieldPeer peer = (TextFieldPeer)this.peer; return (peer != null) ? - peer.preferredSize(columns) : + peer.getPreferredSize(columns) : super.preferredSize(); } } @@ -424,7 +424,7 @@ public class TextField extends TextComponent { synchronized (getTreeLock()) { TextFieldPeer peer = (TextFieldPeer)this.peer; return (peer != null) ? - peer.minimumSize(columns) : + peer.getMinimumSize(columns) : super.minimumSize(); } } diff --git a/jdk/src/share/classes/java/awt/Toolkit.java b/jdk/src/share/classes/java/awt/Toolkit.java index 5ac97013d1a..aaa6afdd5a0 100644 --- a/jdk/src/share/classes/java/awt/Toolkit.java +++ b/jdk/src/share/classes/java/awt/Toolkit.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2550,4 +2550,37 @@ public abstract class Toolkit { } } } + + /** + * Reports whether events from extra mouse buttons are allowed to be processed and posted into + * {@code EventQueue}. + *
    + * To change the returned value it is necessary to set the {@code sun.awt.enableExtraMouseButtons} + * property before the {@code Toolkit} class initialization. This setting could be done on the application + * startup by the following command: + *
    +    * java -Dsun.awt.enableExtraMouseButtons=false Application
    +    * 
    + * Alternatively, the property could be set in the application by using the following code: + *
    +    * System.setProperty("sun.awt.enableExtraMouseButtons", "true");
    +    * 
    + * before the {@code Toolkit} class initialization. + * If not set by the time of the {@code Toolkit} class initialization, this property will be + * initialized with {@code true}. + * Changing this value after the {@code Toolkit} class initialization will have no effect. + *

    + * The current value could be queried by using the + * {@code System.getProperty("sun.awt.enableExtraMouseButtons")} method. + * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @return {@code true} if events from extra mouse buttons are allowed to be processed and posted; + * {@code false} otherwise + * @see System#getProperty(String propertyName) + * @see System#setProperty(String propertyName, String value) + * @see java.awt.EventQueue + * @since 1.7 + */ + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled(); + } } diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 94a8ff2ed5b..2651729f20d 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -53,6 +53,7 @@ import sun.awt.AppContext; import sun.awt.CausedFocusEvent; import sun.awt.SunToolkit; import sun.awt.util.IdentityArrayList; +import sun.java2d.Disposer; import sun.java2d.pipe.Region; import sun.security.action.GetPropertyAction; import sun.security.util.SecurityConstants; @@ -409,8 +410,6 @@ public class Window extends Container implements Accessible { } modalExclusionType = Dialog.ModalExclusionType.NO_EXCLUDE; - - sun.java2d.Disposer.addRecord(anchor, new WindowDisposerRecord(appContext, this)); } /** @@ -540,6 +539,10 @@ public class Window extends Container implements Accessible { if (owner != null) { owner.addOwnedWindow(weakThis); } + + // Fix for 6758673: this call is moved here from init(gc), because + // WindowDisposerRecord requires a proper value of parent field. + Disposer.addRecord(anchor, new WindowDisposerRecord(appContext, this)); } /** diff --git a/jdk/src/share/classes/java/awt/doc-files/DesktopProperties.html b/jdk/src/share/classes/java/awt/doc-files/DesktopProperties.html index f699ba2fa7a..5f3afb37442 100644 --- a/jdk/src/share/classes/java/awt/doc-files/DesktopProperties.html +++ b/jdk/src/share/classes/java/awt/doc-files/DesktopProperties.html @@ -1,5 +1,5 @@ + diff --git a/jdk/src/share/classes/java/net/CookieManager.java b/jdk/src/share/classes/java/net/CookieManager.java index e262dd8c2c0..6b7b1165329 100644 --- a/jdk/src/share/classes/java/net/CookieManager.java +++ b/jdk/src/share/classes/java/net/CookieManager.java @@ -107,8 +107,9 @@ import java.io.IOException; *

* * - *

The implementation conforms to RFC 2965, section 3.3. + *

The implementation conforms to RFC 2965, section 3.3. * + * @see CookiePolicy * @author Edward Wang * @since 1.6 */ diff --git a/jdk/src/share/classes/java/net/DatagramSocket.java b/jdk/src/share/classes/java/net/DatagramSocket.java index 4558632c214..40c95ef5aee 100644 --- a/jdk/src/share/classes/java/net/DatagramSocket.java +++ b/jdk/src/share/classes/java/net/DatagramSocket.java @@ -41,10 +41,11 @@ import java.security.PrivilegedExceptionAction; * one machine to another may be routed differently, and may arrive in * any order. * - *

UDP broadcasts sends are always enabled on a DatagramSocket. - * In order to receive broadcast packets a DatagramSocket - * should be bound to the wildcard address. In some - * implementations, broadcast packets may also be received when + *

Where possible, a newly constructed {@code DatagramSocket} has the + * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as + * to allow the transmission of broadcast datagrams. In order to receive + * broadcast packets a DatagramSocket should be bound to the wildcard address. + * In some implementations, broadcast packets may also be received when * a DatagramSocket is bound to a more specific address. *

* Example: @@ -1017,9 +1018,18 @@ class DatagramSocket implements java.io.Closeable { /** * Enable/disable SO_BROADCAST. - * @param on whether or not to have broadcast turned on. - * @exception SocketException if there is an error - * in the underlying protocol, such as an UDP error. + * + *

Some operating systems may require that the Java virtual machine be + * started with implementation specific privileges to enable this option or + * send broadcast datagrams. + * + * @param on + * whether or not to have broadcast turned on. + * + * @throws SocketException + * if there is an error in the underlying protocol, such as an UDP + * error. + * * @since 1.4 * @see #getBroadcast() */ diff --git a/jdk/src/share/classes/java/net/HttpCookie.java b/jdk/src/share/classes/java/net/HttpCookie.java index 1fcdd6c51da..bd16d4f2723 100644 --- a/jdk/src/share/classes/java/net/HttpCookie.java +++ b/jdk/src/share/classes/java/net/HttpCookie.java @@ -33,6 +33,7 @@ import java.util.TimeZone; import java.util.Date; import java.lang.NullPointerException; // for javadoc +import java.util.Locale; /** * An HttpCookie object represents an http cookie, which carries state @@ -1058,8 +1059,7 @@ public final class HttpCookie implements Cloneable { if (assignor != null) { assignor.assign(cookie, attrName, attrValue); } else { - // must be an error - throw new IllegalArgumentException("Illegal cookie attribute"); + // Ignore the attribute as per RFC 2965 } } @@ -1097,7 +1097,7 @@ public final class HttpCookie implements Cloneable { static { cDateFormats = new SimpleDateFormat[COOKIE_DATE_FORMATS.length]; for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) { - cDateFormats[i] = new SimpleDateFormat(COOKIE_DATE_FORMATS[i]); + cDateFormats[i] = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US); cDateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT")); } } diff --git a/jdk/src/share/classes/java/net/StandardProtocolFamily.java b/jdk/src/share/classes/java/net/StandardProtocolFamily.java index 7c11b32f59f..d4b03ed887f 100644 --- a/jdk/src/share/classes/java/net/StandardProtocolFamily.java +++ b/jdk/src/share/classes/java/net/StandardProtocolFamily.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package java.net; /** - * Defines the standard family of communication protocols. + * Defines the standard families of communication protocols. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/net/StandardSocketOption.java b/jdk/src/share/classes/java/net/StandardSocketOption.java index 405038cc1c2..dba8ff22d90 100644 --- a/jdk/src/share/classes/java/net/StandardSocketOption.java +++ b/jdk/src/share/classes/java/net/StandardSocketOption.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,7 @@ public final class StandardSocketOption { * * @see RFC 929: * Broadcasting Internet Datagrams + * @see DatagramSocket#setBroadcast */ public static final SocketOption SO_BROADCAST = new StdSocketOption("SO_BROADCAST", Boolean.class); @@ -78,6 +79,7 @@ public final class StandardSocketOption { * * @see RFC 1122 * Requirements for Internet Hosts -- Communication Layers + * @see Socket#setKeepAlive */ public static final SocketOption SO_KEEPALIVE = new StdSocketOption("SO_KEEPALIVE", Boolean.class); @@ -107,6 +109,8 @@ public final class StandardSocketOption { * socket is bound or connected. Whether an implementation allows the * socket send buffer to be changed after the socket is bound is system * dependent. + * + * @see Socket#setSendBufferSize */ public static final SocketOption SO_SNDBUF = new StdSocketOption("SO_SNDBUF", Integer.class); @@ -145,6 +149,8 @@ public final class StandardSocketOption { * * @see RFC 1323: TCP * Extensions for High Performance + * @see Socket#setReceiveBufferSize + * @see ServerSocket#setReceiveBufferSize */ public static final SocketOption SO_RCVBUF = new StdSocketOption("SO_RCVBUF", Integer.class); @@ -175,6 +181,7 @@ public final class StandardSocketOption { * * @see RFC 793: Transmission * Control Protocol + * @see ServerSocket#setReuseAddress */ public static final SocketOption SO_REUSEADDR = new StdSocketOption("SO_REUSEADDR", Boolean.class); @@ -205,6 +212,8 @@ public final class StandardSocketOption { * is system dependent. Setting the linger interval to a value that is * greater than its maximum value causes the linger interval to be set to * its maximum value. + * + * @see Socket#setSoLinger */ public static final SocketOption SO_LINGER = new StdSocketOption("SO_LINGER", Integer.class); @@ -215,15 +224,15 @@ public final class StandardSocketOption { /** * The Type of Service (ToS) octet in the Internet Protocol (IP) header. * - *

The value of this socket option is an {@code Integer}, the least - * significant 8 bits of which represents the value of the ToS octet in IP - * packets sent by sockets to an {@link StandardProtocolFamily#INET IPv4} - * socket. The interpretation of the ToS octet is network specific and - * is not defined by this class. Further information on the ToS octet can be - * found in RFC 1349 - * and RFC 2474. The - * value of the socket option is a hint. An implementation may - * ignore the value, or ignore specific values. + *

The value of this socket option is an {@code Integer} representing + * the value of the ToS octet in IP packets sent by sockets to an {@link + * StandardProtocolFamily#INET IPv4} socket. The interpretation of the ToS + * octet is network specific and is not defined by this class. Further + * information on the ToS octet can be found in RFC 1349 and RFC 2474. The value + * of the socket option is a hint. An implementation may ignore the + * value, or ignore specific values. * *

The initial/default value of the TOS field in the ToS octet is * implementation specific but will typically be {@code 0}. For @@ -235,6 +244,8 @@ public final class StandardSocketOption { *

The behavior of this socket option on a stream-oriented socket, or an * {@link StandardProtocolFamily#INET6 IPv6} socket, is not defined in this * release. + * + * @see DatagramSocket#setTrafficClass */ public static final SocketOption IP_TOS = new StdSocketOption("IP_TOS", Integer.class); @@ -257,6 +268,7 @@ public final class StandardSocketOption { * is system dependent. * * @see java.nio.channels.MulticastChannel + * @see MulticastSocket#setInterface */ public static final SocketOption IP_MULTICAST_IF = new StdSocketOption("IP_MULTICAST_IF", NetworkInterface.class); @@ -283,6 +295,7 @@ public final class StandardSocketOption { * prior to binding the socket is system dependent. * * @see java.nio.channels.MulticastChannel + * @see MulticastSocket#setTimeToLive */ public static final SocketOption IP_MULTICAST_TTL = new StdSocketOption("IP_MULTICAST_TTL", Integer.class); @@ -307,6 +320,7 @@ public final class StandardSocketOption { * binding the socket is system dependent. * * @see java.nio.channels.MulticastChannel + * @see MulticastSocket#setLoopbackMode */ public static final SocketOption IP_MULTICAST_LOOP = new StdSocketOption("IP_MULTICAST_LOOP", Boolean.class); @@ -328,11 +342,12 @@ public final class StandardSocketOption { * coalescing impacts performance. The socket option may be enabled at any * time. In other words, the Nagle Algorithm can be disabled. Once the option * is enabled, it is system dependent whether it can be subsequently - * disabled. In that case, invoking the {@code setOption} method to disable - * the option has no effect. + * disabled. If it cannot, then invoking the {@code setOption} method to + * disable the option has no effect. * * @see RFC 1122: * Requirements for Internet Hosts -- Communication Layers + * @see Socket#setTcpNoDelay */ public static final SocketOption TCP_NODELAY = new StdSocketOption("TCP_NODELAY", Boolean.class); diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java index 9ffd0287c36..afb92b8c938 100644 --- a/jdk/src/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/share/classes/java/net/URLClassLoader.java @@ -31,10 +31,12 @@ import java.io.File; import java.io.FilePermission; import java.io.InputStream; import java.io.IOException; +import java.io.Closeable; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandlerFactory; import java.util.Enumeration; +import java.util.List; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.jar.Manifest; @@ -70,7 +72,7 @@ import sun.security.util.SecurityConstants; * @author David Connelly * @since 1.2 */ -public class URLClassLoader extends SecureClassLoader { +public class URLClassLoader extends SecureClassLoader implements Closeable { /* The search path for classes and resources */ URLClassPath ucp; @@ -85,13 +87,13 @@ public class URLClassLoader extends SecureClassLoader { * to refer to a JAR file which will be downloaded and opened as needed. * *

If there is a security manager, this method first - * calls the security manager's checkCreateClassLoader method + * calls the security manager's {@code checkCreateClassLoader} method * to ensure creation of a class loader is allowed. * * @param urls the URLs from which to load classes and resources * @param parent the parent class loader for delegation * @exception SecurityException if a security manager exists and its - * checkCreateClassLoader method doesn't allow + * {@code checkCreateClassLoader} method doesn't allow * creation of a class loader. * @see SecurityManager#checkCreateClassLoader */ @@ -169,12 +171,65 @@ public class URLClassLoader extends SecureClassLoader { acc = AccessController.getContext(); } + + /** + * Closes this URLClassLoader, so that it can no longer be used to load + * new classes or resources that are defined by this loader. + * Classes and resources defined by any of this loader's parents in the + * delegation hierarchy are still accessible. Also, any classes or resources + * that are already loaded, are still accessible. + *

+ * In the case of jar: and file: URLs, it also closes any class files, + * or JAR files that were opened by it. If another thread is loading a + * class when the {@code close} method is invoked, then the result of + * that load is undefined. + *

+ * The method makes a best effort attempt to close all opened files, + * by catching {@link IOException}s internally. Unchecked exceptions + * and errors are not caught. Calling close on an already closed + * loader has no effect. + *

+ * @throws IOException if closing any file opened by this class loader + * resulted in an IOException. Any such exceptions are caught, and a + * single IOException is thrown after the last file has been closed. + * If only one exception was thrown, it will be set as the cause + * of this IOException. + * + * @throws SecurityException if a security manager is set, and it denies + * {@link RuntimePermission}("closeClassLoader") + * + * @since 1.7 + */ + public void close() throws IOException { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPermission(new RuntimePermission("closeClassLoader")); + } + List errors = ucp.closeLoaders(); + if (errors.isEmpty()) { + return; + } + if (errors.size() == 1) { + throw new IOException ( + "Error closing URLClassLoader resource", + errors.get(0) + ); + } + // Several exceptions. So, just combine the error messages + String errormsg = "Error closing resources: "; + for (IOException error: errors) { + errormsg = errormsg + "[" + error.toString() + "] "; + } + throw new IOException (errormsg); + } + /** * Appends the specified URL to the list of URLs to search for * classes and resources. *

* If the URL specified is null or is already in the - * list of URLs, then invoking this method has no effect. + * list of URLs, or if this loader is closed, then invoking this + * method has no effect. * * @param url the URL to be added to the search path of URLs */ @@ -199,7 +254,8 @@ public class URLClassLoader extends SecureClassLoader { * * @param name the name of the class * @return the resulting class - * @exception ClassNotFoundException if the class could not be found + * @exception ClassNotFoundException if the class could not be found, + * or if the loader is closed. */ protected Class findClass(final String name) throws ClassNotFoundException @@ -370,7 +426,7 @@ public class URLClassLoader extends SecureClassLoader { * * @param name the name of the resource * @return a URL for the resource, or null - * if the resource could not be found. + * if the resource could not be found, or if the loader is closed. */ public URL findResource(final String name) { /* @@ -393,6 +449,7 @@ public class URLClassLoader extends SecureClassLoader { * @param name the resource name * @exception IOException if an I/O exception occurs * @return an Enumeration of URLs + * If the loader is closed, the Enumeration will be empty. */ public Enumeration findResources(final String name) throws IOException diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java new file mode 100644 index 00000000000..7bc43357479 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java @@ -0,0 +1,205 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.ByteBuffer; +import java.util.concurrent.Future; + +/** + * An asynchronous channel that can read and write bytes. + * + *

Some channels may not allow more than one read or write to be outstanding + * at any given time. If a thread invokes a read method before a previous read + * operation has completed then a {@link ReadPendingException} will be thrown. + * Similarly, if a write method is invoked before a previous write has completed + * then {@link WritePendingException} is thrown. Whether or not other kinds of + * I/O operations may proceed concurrently with a read operation depends upon + * the type of the channel. + * + *

Note that {@link java.nio.ByteBuffer ByteBuffers} are not safe for use by + * multiple concurrent threads. When a read or write operation is initiated then + * care must be taken to ensure that the buffer is not accessed until the + * operation completes. + * + * @see Channels#newInputStream(AsynchronousByteChannel) + * @see Channels#newOutputStream(AsynchronousByteChannel) + * + * @since 1.7 + */ + +public interface AsynchronousByteChannel + extends AsynchronousChannel +{ + /** + * Reads a sequence of bytes from this channel into the given buffer. + * + *

This method initiates an operation to read a sequence of bytes from + * this channel into the given buffer. The method returns a {@link Future} + * representing the pending result of the operation. The result of the + * operation, obtained by invoking the {@code Future} 's {@link + * Future#get() get} method, is the number of bytes read or {@code -1} if + * all bytes have been read and the channel has reached end-of-stream. + * + *

This method initiates a read operation to read up to r bytes + * from the channel, where r is the number of bytes remaining in the + * buffer, that is, {@code dst.remaining()} at the time that the read is + * attempted. Where r is 0, the read operation completes immediately + * with a result of {@code 0} without initiating an I/O operation. + * + *

Suppose that a byte sequence of length n is read, where + * 0 < n <= r. + * This byte sequence will be transferred into the buffer so that the first + * byte in the sequence is at index p and the last byte is at index + * p + n - 1, + * where p is the buffer's position at the moment the read is + * performed. Upon completion the buffer's position will be equal to + * p + n; its limit will not have changed. + * + *

Buffers are not safe for use by multiple concurrent threads so care + * should be taken to not to access the buffer until the operaton has completed. + * + *

This method may be invoked at any time. Some channel types may not + * allow more than one read to be outstanding at any given time. If a thread + * initiates a read operation before a previous read operation has + * completed then a {@link ReadPendingException} will be thrown. + * + *

The handler parameter is used to specify a {@link + * CompletionHandler}. When the read operation completes the handler's + * {@link CompletionHandler#completed completed} method is executed. + * + * + * @param dst + * The buffer into which bytes are to be transferred + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The completion handler object; can be {@code null} + * + * @return A Future representing the result of the operation + * + * @throws IllegalArgumentException + * If the buffer is read-only + * @throws ReadPendingException + * If the channel does not allow more than one read to be outstanding + * and a previous read has not completed + */ + Future read(ByteBuffer dst, + A attachment, + CompletionHandler handler); + + /** + * Reads a sequence of bytes from this channel into the given buffer. + * + *

An invocation of this method of the form c.read(dst) + * behaves in exactly the same manner as the invocation + *

+     * c.read(dst, null, null);
+ * + * @param dst + * The buffer into which bytes are to be transferred + * + * @return A Future representing the result of the operation + * + * @throws IllegalArgumentException + * If the buffer is read-only + * @throws ReadPendingException + * If the channel does not allow more than one read to be outstanding + * and a previous read has not completed + */ + Future read(ByteBuffer dst); + + /** + * Writes a sequence of bytes to this channel from the given buffer. + * + *

This method initiates an operation to write a sequence of bytes to + * this channel from the given buffer. This method returns a {@link + * Future} representing the pending result of the operation. The result + * of the operation, obtained by invoking the Future's {@link + * Future#get() get} method, is the number of bytes written, possibly zero. + * + *

This method initiates a write operation to write up to r bytes + * to the channel, where r is the number of bytes remaining in the + * buffer, that is, {@code src.remaining()} at the moment the write is + * attempted. Where r is 0, the write operation completes immediately + * with a result of {@code 0} without initiating an I/O operation. + * + *

Suppose that a byte sequence of length n is written, where + * 0 < n <= r. + * This byte sequence will be transferred from the buffer starting at index + * p, where p is the buffer's position at the moment the + * write is performed; the index of the last byte written will be + * p + n - 1. + * Upon completion the buffer's position will be equal to + * p + n; its limit will not have changed. + * + *

Buffers are not safe for use by multiple concurrent threads so care + * should be taken to not to access the buffer until the operaton has completed. + * + *

This method may be invoked at any time. Some channel types may not + * allow more than one write to be outstanding at any given time. If a thread + * initiates a write operation before a previous write operation has + * completed then a {@link WritePendingException} will be thrown. + * + *

The handler parameter is used to specify a {@link + * CompletionHandler}. When the write operation completes the handler's + * {@link CompletionHandler#completed completed} method is executed. + * + * @param src + * The buffer from which bytes are to be retrieved + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The completion handler object; can be {@code null} + * + * @return A Future representing the result of the operation + * + * @throws WritePendingException + * If the channel does not allow more than one write to be outstanding + * and a previous write has not completed + */ + Future write(ByteBuffer src, + A attachment, + CompletionHandler handler); + + /** + * Writes a sequence of bytes to this channel from the given buffer. + * + *

An invocation of this method of the form c.write(src) + * behaves in exactly the same manner as the invocation + *

+     * c.write(src, null, null);
+ * + * @param src + * The buffer from which bytes are to be retrieved + * + * @return A Future representing the result of the operation + * + * @throws WritePendingException + * If the channel does not allow more than one write to be outstanding + * and a previous write has not completed + */ + Future write(ByteBuffer src); +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java new file mode 100644 index 00000000000..f3e4ffe4ea5 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java @@ -0,0 +1,116 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.io.IOException; +import java.util.concurrent.Future; // javadoc + +/** + * A channel that supports asynchronous I/O operations. Asynchronous I/O + * operations will usually take one of two forms: + * + *
    + *
  1. {@link Future}<V> operation(...)
  2. + *
  3. Future<V> operation(... A attachment, {@link CompletionHandler}<V,? super A> handler)
  4. + *
+ * + * where operation is the name of the I/O operation (read or write for + * example), V is the result type of the I/O operation, and A is + * the type of an object attached to the I/O operation to provide context when + * consuming the result. The attachment is important for cases where a + * state-less {@code CompletionHandler} is used to consume the result + * of many I/O operations. + * + *

In the first form, the methods defined by the {@link Future Future} + * interface may be used to check if the operation has completed, wait for its + * completion, and to retrieve the result. In the second form, a {@link + * CompletionHandler} is invoked to consume the result of the I/O operation when + * it completes, fails, or is cancelled. + * + *

A channel that implements this interface is asynchronously + * closeable: If an I/O operation is outstanding on the channel and the + * channel's {@link #close close} method is invoked, then the I/O operation + * fails with the exception {@link AsynchronousCloseException}. + * + *

Asynchronous channels are safe for use by multiple concurrent threads. + * Some channel implementations may support concurrent reading and writing, but + * may not allow more than one read and one write operation to be outstanding at + * any given time. + * + *

Cancellation

+ * + *

The {@code Future} interface defines the {@link Future#cancel cancel} + * method to cancel execution of a task. + * + *

Where the {@code cancel} method is invoked with the {@code + * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation + * may be interrupted by closing the channel. This will cause any other I/O + * operations outstanding on the channel to complete with the exception {@link + * AsynchronousCloseException}. + * + *

If a {@code CompletionHandler} is specified when initiating an I/O + * operation, and the {@code cancel} method is invoked to cancel the I/O + * operation before it completes, then the {@code CompletionHandler}'s {@link + * CompletionHandler#cancelled cancelled} method is invoked. + * + *

If an implementation of this interface supports a means to cancel I/O + * operations, and where cancellation may leave the channel, or the entity to + * which it is connected, in an inconsistent state, then the channel is put into + * an implementation specific error state that prevents further + * attempts to initiate I/O operations on the channel. For example, if a read + * operation is cancelled but the implementation cannot guarantee that bytes + * have not been read from the channel then it puts the channel into error state + * state; further attempts to initiate a {@code read} operation causes an + * unspecified runtime exception to be thrown. + * + *

Where the {@code cancel} method is invoked to cancel read or write + * operations then it recommended that all buffers used in the I/O operations be + * discarded or care taken to ensure that the buffers are not accessed while the + * channel remains open. + * + * @since 1.7 + */ + +public interface AsynchronousChannel + extends Channel +{ + /** + * Closes this channel. + * + *

Any outstanding asynchronous operations upon this channel will + * complete with the exception {@link AsynchronousCloseException}. After a + * channel is closed then further attempts to initiate asynchronous I/O + * operations complete immediately with cause {@link ClosedChannelException}. + * + *

This method otherwise behaves exactly as specified by the {@link + * Channel} interface. + * + * @throws IOException + * If an I/O error occurs + */ + @Override + void close() throws IOException; +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java b/jdk/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java new file mode 100644 index 00000000000..1199e16b51f --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java @@ -0,0 +1,344 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +/** + * A grouping of asynchronous channels for the purpose of resource sharing. + * + *

An asynchronous channel group encapsulates the mechanics required to + * handle the completion of I/O operations initiated by {@link AsynchronousChannel + * asynchronous channels} that are bound to the group. A group has an associated + * thread pool to which tasks are submitted to handle I/O events and dispatch to + * {@link CompletionHandler completion-handlers} that consume the result of + * asynchronous operations performed on channels in the group. In addition to + * handling I/O events, the pooled threads may also execute other tasks required + * to support the execution of asynchronous I/O operations. + * + *

An asynchronous channel group is created by invoking the {@link + * #withFixedThreadPool withFixedThreadPool} or {@link #withCachedThreadPool + * withCachedThreadPool} methods defined here. Channels are bound to a group by + * specifying the group when constructing the channel. The associated thread + * pool is owned by the group; termination of the group results in the + * shutdown of the associated thread pool. + * + *

In addition to groups created explicitly, the Java virtual machine + * maintains a system-wide default group that is constructed + * automatically. Asynchronous channels that do not specify a group at + * construction time are bound to the default group. The default group has an + * associated thread pool that creates new threads as needed. The default group + * may be configured by means of system properties defined in the table below. + * Where the {@link java.util.concurrent.ThreadFactory ThreadFactory} for the + * default group is not configured then the pooled threads of the default group + * are {@link Thread#isDaemon daemon} threads. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
System propertyDescription
{@code java.nio.channels.DefaultThreadPool.threadFactory} The value of this property is taken to be the fully-qualified name + * of a concrete {@link java.util.concurrent.ThreadFactory ThreadFactory} + * class. The class is loaded using the system class loader and instantiated. + * The factory's {@link java.util.concurrent.ThreadFactory#newThread + * newThread} method is invoked to create each thread for the default + * group's thread pool. If the process to load and instantiate the value + * of the property fails then an unspecified error is thrown during the + * construction of the default group.
{@code java.nio.channels.DefaultThreadPool.initialSize} The value of the {@code initialSize} parameter for the default + * group (see {@link #withCachedThreadPool withCachedThreadPool}). + * The value of the property is taken to be the {@code String} + * representation of an {@code Integer} that is the initial size parameter. + * If the value cannot be parsed as an {@code Integer} it causes an + * unspecified error to be thrown during the construction of the default + * group.
+ * + *

Threading

+ * + *

The completion handler for an I/O operation initiated on a channel bound + * to a group is guaranteed to be invoked by one of the pooled threads in the + * group. This ensures that the completion handler is run by a thread with the + * expected identity. + * + *

Where an I/O operation completes immediately, and the initiating thread + * is one of the pooled threads in the group then the completion handler may + * be invoked directly by the initiating thread. To avoid stack overflow, an + * implementation may impose a limit as to the number of activations on the + * thread stack. Some I/O operations may prohibit invoking the completion + * handler directly by the initiating thread (see {@link + * AsynchronousServerSocketChannel#accept(Object,CompletionHandler) accept}). + * + *

Shutdown and Termination

+ * + *

The {@link #shutdown() shutdown} method is used to initiate an orderly + * shutdown of a group. An orderly shutdown marks the group as shutdown; + * further attempts to construct a channel that binds to the group will throw + * {@link ShutdownChannelGroupException}. Whether or not a group is shutdown can + * be tested using the {@link #isShutdown() isShutdown} method. Once shutdown, + * the group terminates when all asynchronous channels that are bound to + * the group are closed, all actively executing completion handlers have run to + * completion, and resources used by the group are released. No attempt is made + * to stop or interrupt threads that are executing completion handlers. The + * {@link #isTerminated() isTerminated} method is used to test if the group has + * terminated, and the {@link #awaitTermination awaitTermination} method can be + * used to block until the group has terminated. + * + *

The {@link #shutdownNow() shutdownNow} method can be used to initiate a + * forceful shutdown of the group. In addition to the actions performed + * by an orderly shutdown, the {@code shutdownNow} method closes all open channels + * in the group as if by invoking the {@link AsynchronousChannel#close close} + * method. + * + * @since 1.7 + * + * @see AsynchronousSocketChannel#open(AsynchronousChannelGroup) + * @see AsynchronousServerSocketChannel#open(AsynchronousChannelGroup) + */ + +public abstract class AsynchronousChannelGroup { + private final AsynchronousChannelProvider provider; + + /** + * Initialize a new instance of this class. + * + * @param provider + * The asynchronous channel provider for this group + */ + protected AsynchronousChannelGroup(AsynchronousChannelProvider provider) { + this.provider = provider; + } + + /** + * Returns the provider that created this channel group. + * + * @return The provider that created this channel group + */ + public final AsynchronousChannelProvider provider() { + return provider; + } + + /** + * Creates an asynchronous channel group with a fixed thread pool. + * + *

The resulting asynchronous channel group reuses a fixed number of + * threads. At any point, at most {@code nThreads} threads will be active + * processing tasks that are submitted to handle I/O events and dispatch + * completion results for operations initiated on asynchronous channels in + * the group. + * + *

The group is created by invoking the {@link + * AsynchronousChannelProvider#openAsynchronousChannelGroup(int,ThreadFactory) + * openAsynchronousChannelGroup(int,ThreadFactory)} method of the system-wide + * default {@link AsynchronousChannelProvider} object. + * + * @param nThreads + * The number of threads in the pool + * @param threadFactory + * The factory to use when creating new threads + * + * @return A new asynchronous channel group + * + * @throws IllegalArgumentException + * If {@code nThreads <= 0} + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousChannelGroup withFixedThreadPool(int nThreads, + ThreadFactory threadFactory) + throws IOException + { + return AsynchronousChannelProvider.provider() + .openAsynchronousChannelGroup(nThreads, threadFactory); + } + + /** + * Creates an asynchronous channel group with a given thread pool that + * creates new threads as needed. + * + *

The {@code executor} parameter is an {@code ExecutorService} that + * creates new threads as needed to execute tasks that are submitted to + * handle I/O events and dispatch completion results for operations initiated + * on asynchronous channels in the group. It may reuse previously constructed + * threads when they are available. + * + *

The {@code initialSize} parameter may be used by the implementation + * as a hint as to the initial number of tasks it may submit. For + * example, it may be used to indictae the initial number of threads that + * wait on I/O events. + * + *

The executor is intended to be used exclusively by the resulting + * asynchronous channel group. Termination of the group results in the + * orderly {@link ExecutorService#shutdown shutdown} of the executor + * service. Shutting down the executor service by other means results in + * unspecified behavior. + * + *

The group is created by invoking the {@link + * AsynchronousChannelProvider#openAsynchronousChannelGroup(ExecutorService,int) + * openAsynchronousChannelGroup(ExecutorService,int)} method of the system-wide + * default {@link AsynchronousChannelProvider} object. + * + * @param executor + * The thread pool for the resulting group + * @param initialSize + * A value {@code >=0} or a negative value for implementation + * specific default + * + * @return A new asynchronous channel group + * + * @throws IOException + * If an I/O error occurs + * + * @see java.util.concurrent.Executors#newCachedThreadPool + */ + public static AsynchronousChannelGroup withCachedThreadPool(ExecutorService executor, + int initialSize) + throws IOException + { + return AsynchronousChannelProvider.provider() + .openAsynchronousChannelGroup(executor, initialSize); + } + + /** + * Creates an asynchronous channel group with a given thread pool. + * + *

The {@code executor} parameter is an {@code ExecutorService} that + * executes tasks submitted to dispatch completion results for operations + * initiated on asynchronous channels in the group. + * + *

Care should be taken when configuring the executor service. It + * should support direct handoff or unbounded queuing of + * submitted tasks, and the thread that invokes the {@link + * ExecutorService#execute execute} method should never invoke the task + * directly. An implementation may mandate additional constraints. + * + *

The executor is intended to be used exclusively by the resulting + * asynchronous channel group. Termination of the group results in the + * orderly {@link ExecutorService#shutdown shutdown} of the executor + * service. Shutting down the executor service by other means results in + * unspecified behavior. + * + *

The group is created by invoking the {@link + * AsynchronousChannelProvider#openAsynchronousChannelGroup(ExecutorService,int) + * openAsynchronousChannelGroup(ExecutorService,int)} method of the system-wide + * default {@link AsynchronousChannelProvider} object with an {@code + * initialSize} of {@code 0}. + * + * @param executor + * The thread pool for the resulting group + * + * @return A new asynchronous channel group + * + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousChannelGroup withThreadPool(ExecutorService executor) + throws IOException + { + return AsynchronousChannelProvider.provider() + .openAsynchronousChannelGroup(executor, 0); + } + + /** + * Tells whether or not this asynchronous channel group is shutdown. + * + * @return {@code true} if this asynchronous channel group is shutdown or + * has been marked for shutdown. + */ + public abstract boolean isShutdown(); + + /** + * Tells whether or not this group has terminated. + * + *

Where this method returns {@code true}, then the associated thread + * pool has also {@link ExecutorService#isTerminated terminated}. + * + * @return {@code true} if this group has terminated + */ + public abstract boolean isTerminated(); + + /** + * Initiates an orderly shutdown of the group. + * + *

This method marks the group as shutdown. Further attempts to construct + * channel that binds to this group will throw {@link ShutdownChannelGroupException}. + * The group terminates when all asynchronous channels in the group are + * closed, all actively executing completion handlers have run to completion, + * and all resources have been released. This method has no effect if the + * group is already shutdown. + */ + public abstract void shutdown(); + + /** + * Shuts down the group and closes all open channels in the group. + * + *

In addition to the actions performed by the {@link #shutdown() shutdown} + * method, this method invokes the {@link AsynchronousChannel#close close} + * method on all open channels in the group. This method does not attempt to + * stop or interrupt threads that are executing completion handlers. The + * group terminates when all actively executing completion handlers have run + * to completion and all resources have been released. This method may be + * invoked at any time. If some other thread has already invoked it, then + * another invocation will block until the first invocation is complete, + * after which it will return without effect. + * + * @throws IOException + * If an I/O error occurs + */ + public abstract void shutdownNow() throws IOException; + + /** + * Awaits termination of the group. + + *

This method blocks until the group has terminated, or the timeout + * occurs, or the current thread is interrupted, whichever happens first. + * + * @param timeout + * The maximum time to wait, or zero or less to not wait + * @param unit + * The time unit of the timeout argument + * + * @return {@code true} if the group has terminated; {@code false} if the + * timeout elapsed before termination + * + * @throws InterruptedException + * If interrupted while waiting + */ + public abstract boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException; +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java new file mode 100644 index 00000000000..6a9d9f09715 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java @@ -0,0 +1,718 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.channels.spi.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.Future; +import java.io.IOException; +import java.net.SocketOption; +import java.net.SocketAddress; +import java.net.ProtocolFamily; +import java.nio.ByteBuffer; + +/** + * An asynchronous channel for datagram-oriented sockets. + * + *

An asynchronous datagram channel is created by invoking one of the {@link + * #open open} methods defined by this class. It is not possible to create a channel + * for an arbitrary, pre-existing datagram socket. A newly-created asynchronous + * datagram channel is open but not connected. It need not be connected in order + * for the {@link #send send} and {@link #receive receive} methods to be used. + * A datagram channel may be connected, by invoking its {@link #connect connect} + * method, in order to avoid the overhead of the security checks that are otherwise + * performed as part of every send and receive operation when a security manager + * is set. The channel must be connected in order to use the {@link #read read} + * and {@link #write write} methods, since those methods do not accept or return + * socket addresses. Once connected, an asynchronous datagram channel remains + * connected until it is disconnected or closed. + * + *

Socket options are configured using the {@link #setOption(SocketOption,Object) + * setOption} method. An asynchronous datagram channel to an Internet Protocol + * (IP) socket supports the following options: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option NameDescription
{@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} The size of the socket send buffer
{@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
{@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} Re-use address
{@link java.net.StandardSocketOption#SO_BROADCAST SO_BROADCAST} Allow transmission of broadcast datagrams
{@link java.net.StandardSocketOption#IP_TOS IP_TOS} The Type of Service (ToS) octet in the Internet Protocol (IP) header
{@link java.net.StandardSocketOption#IP_MULTICAST_IF IP_MULTICAST_IF} The network interface for Internet Protocol (IP) multicast datagrams
{@link java.net.StandardSocketOption#IP_MULTICAST_TTL + * IP_MULTICAST_TTL} The time-to-live for Internet Protocol (IP) multicast + * datagrams
{@link java.net.StandardSocketOption#IP_MULTICAST_LOOP + * IP_MULTICAST_LOOP} Loopback for Internet Protocol (IP) multicast datagrams
+ *
+ * Additional (implementation specific) options may also be supported. + * + *

Asynchronous datagram channels allow more than one read/receive and + * write/send to be oustanding at any given time. + * + *

Usage Example: + *

+ *  final AsynchronousDatagramChannel dc = AsynchronousDatagramChannel.open()
+ *      .bind(new InetSocketAddress(4000));
+ *
+ *  // print the source address of all packets that we receive
+ *  dc.receive(buffer, buffer, new CompletionHandler<SocketAddress,ByteBuffer>() {
+ *      public void completed(SocketAddress sa, ByteBuffer buffer) {
+ *          try {
+ *               System.out.println(sa);
+ *
+ *               buffer.clear();
+ *               dc.receive(buffer, buffer, this);
+ *           } catch (...) { ... }
+ *      }
+ *      public void failed(Throwable exc, ByteBuffer buffer) {
+ *          ...
+ *      }
+ *      public void cancelled(ByteBuffer buffer) {
+ *          ...
+ *      }
+ *  });
+ * 
+ * + * @since 1.7 + */ + +public abstract class AsynchronousDatagramChannel + implements AsynchronousByteChannel, MulticastChannel +{ + private final AsynchronousChannelProvider provider; + + /** + * Initializes a new instance of this class. + */ + protected AsynchronousDatagramChannel(AsynchronousChannelProvider provider) { + this.provider = provider; + } + + /** + * Returns the provider that created this channel. + */ + public final AsynchronousChannelProvider provider() { + return provider; + } + + /** + * Opens an asynchronous datagram channel. + * + *

The new channel is created by invoking the {@link + * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousDatagramChannel + * openAsynchronousDatagramChannel} method on the {@link + * java.nio.channels.spi.AsynchronousChannelProvider} object that created + * the given group (or the default provider where {@code group} is {@code + * null}). + * + *

The {@code family} parameter is used to specify the {@link ProtocolFamily}. + * If the datagram channel is to be used for Internet Protocol {@link + * MulticastChannel multicasting} then this parameter should correspond to + * the address type of the multicast groups that this channel will join. + * + * @param family + * The protocol family, or {@code null} to use the default protocol + * family + * @param group + * The group to which the newly constructed channel should be bound, + * or {@code null} for the default group + * + * @return A new asynchronous datagram channel + * + * @throws UnsupportedOperationException + * If the specified protocol family is not supported. For example, + * suppose the parameter is specified as {@link + * java.net.StandardProtocolFamily#INET6 INET6} but IPv6 is not + * enabled on the platform. + * @throws ShutdownChannelGroupException + * The specified group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousDatagramChannel open(ProtocolFamily family, + AsynchronousChannelGroup group) + throws IOException + { + AsynchronousChannelProvider provider = (group == null) ? + AsynchronousChannelProvider.provider() : group.provider(); + return provider.openAsynchronousDatagramChannel(family, group); + } + + /** + * Opens an asynchronous datagram channel. + * + *

This method returns an asynchronous datagram channel that is + * bound to the default group. This method is equivalent to evaluating + * the expression: + *

+     * open((ProtocolFamily)null, (AsynchronousChannelGroup)null);
+     * 
+ * + * @return A new asynchronous datagram channel + * + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousDatagramChannel open() + throws IOException + { + return open(null, null); + } + + // -- Socket-specific operations -- + + /** + * @throws AlreadyBoundException {@inheritDoc} + * @throws UnsupportedAddressTypeException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + * @throws SecurityException + * If a security manager has been installed and its {@link + * SecurityManager#checkListen checkListen} method denies the + * operation + */ + @Override + public abstract AsynchronousDatagramChannel bind(SocketAddress local) + throws IOException; + + /** + * @throws IllegalArgumentException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract AsynchronousDatagramChannel setOption(SocketOption name, T value) + throws IOException; + + /** + * Returns the remote address to which this channel is connected. + * + *

Where the channel is connected to an Internet Protocol socket address + * then the return value from this method is of type {@link + * java.net.InetSocketAddress}. + * + * @return The remote address; {@code null} if the channel's socket is not + * connected + * + * @throws ClosedChannelException + * If the channel is closed + * @throws IOException + * If an I/O error occurs + */ + public abstract SocketAddress getRemoteAddress() throws IOException; + + /** + * Connects this channel's socket. + * + *

The channel's socket is configured so that it only receives + * datagrams from, and sends datagrams to, the given remote peer + * address. Once connected, datagrams may not be received from or sent to + * any other address. A datagram socket remains connected until it is + * explicitly disconnected or until it is closed. + * + *

This method performs exactly the same security checks as the {@link + * java.net.DatagramSocket#connect connect} method of the {@link + * java.net.DatagramSocket} class. That is, if a security manager has been + * installed then this method verifies that its {@link + * java.lang.SecurityManager#checkAccept checkAccept} and {@link + * java.lang.SecurityManager#checkConnect checkConnect} methods permit + * datagrams to be received from and sent to, respectively, the given + * remote address. + * + *

This method may be invoked at any time. Whether it has any effect + * on outstanding read or write operations is implementation specific and + * therefore not specified. + * + * @param remote + * The remote address to which this channel is to be connected + * + * @return This datagram channel + * + * @throws ClosedChannelException + * If this channel is closed + * + * @throws SecurityException + * If a security manager has been installed + * and it does not permit access to the given remote address + * + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousDatagramChannel connect(SocketAddress remote) + throws IOException; + + /** + * Disconnects this channel's socket. + * + *

The channel's socket is configured so that it can receive datagrams + * from, and sends datagrams to, any remote address so long as the security + * manager, if installed, permits it. + * + *

This method may be invoked at any time. Whether it has any effect + * on outstanding read or write operations is implementation specific and + * therefore not specified. + * + * @return This datagram channel + * + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousDatagramChannel disconnect() throws IOException; + + /** + * Receives a datagram via this channel. + * + *

This method initiates the receiving of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The {@code Future}'s {@link Future#get() get} method returns + * the source address of the datagram upon successful completion. + * + *

The datagram is transferred into the given byte buffer starting at + * its current position, as if by a regular {@link AsynchronousByteChannel#read + * read} operation. If there are fewer bytes remaining in the buffer + * than are required to hold the datagram then the remainder of the datagram + * is silently discarded. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then the operation completes with the exception {@link + * InterruptedByTimeoutException}. When a timeout elapses then the state of + * the {@link ByteBuffer} is not defined. The buffers should be discarded or + * at least care must be taken to ensure that the buffer is not accessed + * while the channel remains open. + * + *

When a security manager has been installed and the channel is not + * connected, then it verifies that the source's address and port number are + * permitted by the security manager's {@link SecurityManager#checkAccept + * checkAccept} method. The permission check is performed with privileges that + * are restricted by the calling context of this method. If the permission + * check fails then the operation completes with a {@link SecurityException}. + * The overhead of this security check can be avoided by first connecting the + * socket via the {@link #connect connect} method. + * + * @param dst + * The buffer into which the datagram is to be transferred + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the timeout is negative or the buffer is read-only + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future receive(ByteBuffer dst, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * Receives a datagram via this channel. + * + *

This method initiates the receiving of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The {@code Future}'s {@link Future#get() get} method returns + * the source address of the datagram upon successful completion. + * + *

This method is equivalent to invoking {@link + * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a + * timeout of {@code 0L}. + * + * @param dst + * The buffer into which the datagram is to be transferred + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the buffer is read-only + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public final Future receive(ByteBuffer dst, + A attachment, + CompletionHandler handler) + { + return receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * Receives a datagram via this channel. + * + *

This method initiates the receiving of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The {@code Future}'s {@link Future#get() get} method returns + * the source address of the datagram upon successful completion. + * + *

This method is equivalent to invoking {@link + * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a + * timeout of {@code 0L}, and an attachment and completion handler + * of {@code null}. + * + * @param dst + * The buffer into which the datagram is to be transferred + * + * @return a {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the buffer is read-only + */ + public final Future receive(ByteBuffer dst) { + return receive(dst, 0L, TimeUnit.MILLISECONDS, null, null); + } + + /** + * Sends a datagram via this channel. + * + *

This method initiates sending of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The operation sends the remaining bytes in the given buffer as a single + * datagram to the given target address. The result of the operation, obtained + * by invoking the {@code Future}'s {@link Future#get() get} + * method, is the number of bytes sent. + * + *

The datagram is transferred from the byte buffer as if by a regular + * {@link AsynchronousByteChannel#write write} operation. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then the operation completes with the exception {@link + * InterruptedByTimeoutException}. When a timeout elapses then the state of + * the {@link ByteBuffer} is not defined. The buffers should be discarded or + * at least care must be taken to ensure that the buffer is not accessed + * while the channel remains open. + * + *

If there is a security manager installed and the the channel is not + * connected then this method verifies that the target address and port number + * are permitted by the security manager's {@link SecurityManager#checkConnect + * checkConnect} method. The overhead of this security check can be avoided + * by first connecting the socket via the {@link #connect connect} method. + * + * @param src + * The buffer containing the datagram to be sent + * @param target + * The address to which the datagram is to be sent + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws UnresolvedAddressException + * If the given remote address is not fully resolved + * @throws UnsupportedAddressTypeException + * If the type of the given remote address is not supported + * @throws IllegalArgumentException + * If the timeout is negative, or if the channel's socket is + * connected to an address that is not equal to {@code target} + * @throws SecurityException + * If a security manager has been installed and it does not permit + * datagrams to be sent to the given address + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future send(ByteBuffer src, + SocketAddress target, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * Sends a datagram via this channel. + * + *

This method initiates sending of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The operation sends the remaining bytes in the given buffer as a single + * datagram to the given target address. The result of the operation, obtained + * by invoking the {@code Future}'s {@link Future#get() get} + * method, is the number of bytes sent. + * + *

This method is equivalent to invoking {@link + * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)} + * with a timeout of {@code 0L}. + * + * @param src + * The buffer containing the datagram to be sent + * @param target + * The address to which the datagram is to be sent + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws UnresolvedAddressException + * If the given remote address is not fully resolved + * @throws UnsupportedAddressTypeException + * If the type of the given remote address is not supported + * @throws IllegalArgumentException + * If the channel's socket is connected and is connected to an + * address that is not equal to {@code target} + * @throws SecurityException + * If a security manager has been installed and it does not permit + * datagrams to be sent to the given address + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public final Future send(ByteBuffer src, + SocketAddress target, + A attachment, + CompletionHandler handler) + { + return send(src, target, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * Sends a datagram via this channel. + * + *

This method initiates sending of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The operation sends the remaining bytes in the given buffer as a single + * datagram to the given target address. The result of the operation, obtained + * by invoking the {@code Future}'s {@link Future#get() get} + * method, is the number of bytes sent. + * + *

This method is equivalent to invoking {@link + * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)} + * with a timeout of {@code 0L} and an attachment and completion handler + * of {@code null}. + * + * @param src + * The buffer containing the datagram to be sent + * @param target + * The address to which the datagram is to be sent + * + * @return a {@code Future} object representing the pending result + * + * @throws UnresolvedAddressException + * If the given remote address is not fully resolved + * @throws UnsupportedAddressTypeException + * If the type of the given remote address is not supported + * @throws IllegalArgumentException + * If the channel's socket is connected and is connected to an + * address that is not equal to {@code target} + * @throws SecurityException + * If a security manager has been installed and it does not permit + * datagrams to be sent to the given address + */ + public final Future send(ByteBuffer src, SocketAddress target) { + return send(src, target, 0L, TimeUnit.MILLISECONDS, null, null); + } + + /** + * Receives a datagram via this channel. + * + *

This method initiates the receiving of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The {@code Future}'s {@link Future#get() get} method returns + * the number of bytes transferred upon successful completion. + * + *

This method may only be invoked if this channel is connected, and it + * only accepts datagrams from the peer that the channel is connected too. + * The datagram is transferred into the given byte buffer starting at + * its current position and exactly as specified in the {@link + * AsynchronousByteChannel} interface. If there are fewer bytes + * remaining in the buffer than are required to hold the datagram then the + * remainder of the datagram is silently discarded. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then the operation completes with the exception {@link + * InterruptedByTimeoutException}. When a timeout elapses then the state of + * the {@link ByteBuffer} is not defined. The buffers should be discarded or + * at least care must be taken to ensure that the buffer is not accessed + * while the channel remains open. + * + * @param dst + * The buffer into which the datagram is to be transferred + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the timeout is negative or buffer is read-only + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future read(ByteBuffer dst, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future read(ByteBuffer dst, + A attachment, + CompletionHandler handler) + { + return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future read(ByteBuffer dst) { + return read(dst, 0L, TimeUnit.MILLISECONDS, null, null); + } + + /** + * Writes a datagram to this channel. + * + *

This method initiates sending of a datagram, returning a + * {@code Future} representing the pending result of the operation. + * The operation sends the remaining bytes in the given buffer as a single + * datagram. The result of the operation, obtained by invoking the + * {@code Future}'s {@link Future#get() get} method, is the + * number of bytes sent. + * + *

The datagram is transferred from the byte buffer as if by a regular + * {@link AsynchronousByteChannel#write write} operation. + * + *

This method may only be invoked if this channel is connected, + * in which case it sends datagrams directly to the socket's peer. Otherwise + * it behaves exactly as specified in the {@link + * AsynchronousByteChannel} interface. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then the operation completes with the exception {@link + * InterruptedByTimeoutException}. When a timeout elapses then the state of + * the {@link ByteBuffer} is not defined. The buffers should be discarded or + * at least care must be taken to ensure that the buffer is not accessed + * while the channel remains open. + * + * @param src + * The buffer containing the datagram to be sent + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the timeout is negative + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future write(ByteBuffer src, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + /** + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future write(ByteBuffer src, + A attachment, + CompletionHandler handler) + { + return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * @throws NotYetConnectedException + * If this channel is not connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future write(ByteBuffer src) { + return write(src, 0L, TimeUnit.MILLISECONDS, null, null); + } +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java new file mode 100644 index 00000000000..a9bff5f16d4 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java @@ -0,0 +1,774 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.file.*; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.spi.*; +import java.nio.ByteBuffer; +import java.io.IOException; +import java.util.concurrent.Future; +import java.util.concurrent.ExecutorService; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; + +/** + * An asynchronous channel for reading, writing, and manipulating a file. + * + *

An asynchronous file channel is created when a file is opened by invoking + * one of the {@link #open open} methods defined by this class. The file contains + * a variable-length sequence of bytes that can be read and written and whose + * current size can be {@link #size() queried}. The size of the file increases + * when bytes are written beyond its current size; the size of the file decreases + * when it is {@link #truncate truncated}. + * + *

An asynchronous file channel does not have a current position + * within the file. Instead, the file position is specified to each read and + * write operation. + * + *

In addition to read and write operations, this class defines the + * following operations:

+ * + *
    + * + *
  • Updates made to a file may be {@link #force forced + * out} to the underlying storage device, ensuring that data are not + * lost in the event of a system crash.

  • + * + *
  • A region of a file may be {@link FileLock locked} + * against access by other programs.

  • + * + *
+ * + *

The {@link #read read}, {@link #write write}, and {@link #lock lock} + * methods defined by this class are asynchronous and return a {@link Future} + * to represent the pending result of the operation. This may be used to check + * if the operation has completed, to wait for its completion, and to retrieve + * the result. These method may optionally specify a {@link CompletionHandler} + * that is invoked to consume the result of the I/O operation when it completes. + * + *

An {@code AsynchronousFileChannel} is associated with a thread pool to + * which tasks are submitted to handle I/O events and dispatch to completion + * handlers that consume the results of I/O operations on the channel. The + * completion handler for an I/O operation initiated on a channel is guaranteed + * to be invoked by one threads in the thread pool (This ensures that the + * completion handler is run by a thread with the expected identity). + * Where an I/O operation completes immediately, and the initiating thread is + * itself a thread in the thread pool, then the completion handler may be invoked + * directly by the initiating thread. When an {@code AsynchronousFileChannel} is + * created without specifying a thread pool then the channel is associated with + * a system-dependent and default thread pool that may be shared with other + * channels. The default thread pool is configured by the system properties + * defined by the {@link AsynchronousChannelGroup} class. + * + *

Channels of this type are safe for use by multiple concurrent threads. The + * {@link Channel#close close} method may be invoked at any time, as specified + * by the {@link Channel} interface. This causes all outstanding asynchronous + * operations on the channel to complete with the exception {@link + * AsynchronousCloseException}. Multiple read and write operations may be + * outstanding at the same time. When multiple read and write operations are + * outstanding then the ordering of the I/O operations, and the order that the + * completion handlers are invoked, is not specified; they are not, in particular, + * guaranteed to execute in the order that the operations were initiated. The + * {@link java.nio.ByteBuffer ByteBuffers} used when reading or writing are not + * safe for use by multiple concurrent I/O operations. Furthermore, after an I/O + * operation is initiated then care should be taken to ensure that the buffer is + * not accessed until after the operation has completed. + * + *

As with {@link FileChannel}, the view of a file provided by an instance of + * this class is guaranteed to be consistent with other views of the same file + * provided by other instances in the same program. The view provided by an + * instance of this class may or may not, however, be consistent with the views + * seen by other concurrently-running programs due to caching performed by the + * underlying operating system and delays induced by network-filesystem protocols. + * This is true regardless of the language in which these other programs are + * written, and whether they are running on the same machine or on some other + * machine. The exact nature of any such inconsistencies are system-dependent + * and are therefore unspecified. + * + * @since 1.7 + */ + +public abstract class AsynchronousFileChannel + implements AsynchronousChannel +{ + /** + * Initializes a new instance of this class. + */ + protected AsynchronousFileChannel() { + } + + /** + * Closes this channel. + * + *

If this channel is associated with its own thread pool then closing + * the channel causes the thread pool to shutdown after all actively + * executing completion handlers have completed. No attempt is made to stop + * or interrupt actively completion handlers. + * + *

This method otherwise behaves exactly as specified by the {@link + * AsynchronousChannel} interface. + * + * @throws IOException {@inheritDoc} + */ + @Override + public abstract void close() throws IOException; + + /** + * Opens or creates a file for reading and/or writing, returning an + * asynchronous file channel to access the file. + * + *

The {@code options} parameter determines how the file is opened. + * The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE + * WRITE} options determines if the file should be opened for reading and/or + * writing. If neither option is contained in the array then an existing file + * is opened for reading. + * + *

In addition to {@code READ} and {@code WRITE}, the following options + * may be present: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option Description
{@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} When opening an existing file, the file is first truncated to a + * size of 0 bytes. This option is ignored when the file is opened only + * for reading.
{@link StandardOpenOption#CREATE_NEW CREATE_NEW} If this option is present then a new file is created, failing if + * the file already exists. When creating a file the check for the + * existence of the file and the creation of the file if it does not exist + * is atomic with respect to other file system operations. This option is + * ignored when the file is opened only for reading.
{@link StandardOpenOption#CREATE CREATE} If this option is present then an existing file is opened if it + * exists, otherwise a new file is created. When creating a file the check + * for the existence of the file and the creation of the file if it does + * not exist is atomic with respect to other file system operations. This + * option is ignored if the {@code CREATE_NEW} option is also present or + * the file is opened only for reading.
{@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} When this option is present then the implementation makes a + * best effort attempt to delete the file when closed by the + * the {@link #close close} method. If the {@code close} method is not + * invoked then a best effort attempt is made to delete the file + * when the Java virtual machine terminates.
{@link StandardOpenOption#SPARSE SPARSE} When creating a new file this option is a hint that the + * new file will be sparse. This option is ignored when not creating + * a new file.
{@link StandardOpenOption#SYNC SYNC} Requires that every update to the file's content or metadata be + * written synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
{@link StandardOpenOption#DSYNC DSYNC} Requires that every update to the file's content be written + * synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
+ * + *

An implementation may also support additional options. + * + *

The {@code executor} parameter is the {@link ExecutorService} to + * which tasks are submitted to handle I/O events and dispatch completion + * results for operations initiated on resulting channel. + * The nature of these tasks is highly implementation specific and so care + * should be taken when configuring the {@code Executor}. Minimally it + * should support an unbounded work queue and should not run tasks on the + * caller thread of the {@link ExecutorService#execute execute} method. + * {@link #close Closing} the channel results in the orderly {@link + * ExecutorService#shutdown shutdown} of the executor service. Shutting down + * the executor service by other means results in unspecified behavior. + * + *

The {@code attrs} parameter is an optional array of file {@link + * FileAttribute file-attributes} to set atomically when creating the file. + * + *

The new channel is created by invoking the {@link + * FileSystemProvider#newFileChannel newFileChannel} method on the + * provider that created the {@code Path}. + * + * @param file + * The path of the file to open or create + * @param options + * Options specifying how the file is opened + * @param executor + * The thread pool or {@code null} to associate the channel with + * the default thread pool + * @param attrs + * An optional list of file attributes to set atomically when + * creating the file + * + * @return A new asynchronous file channel + * + * @throws IllegalArgumentException + * If the set contains an invalid combination of options + * @throws UnsupportedOperationException + * If the {@code file} is associated with a provider that does not + * support creating asynchronous file channels, or an unsupported + * open option is specified, or the array contains an attribute that + * cannot be set atomically when creating the file + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * If a security manager is installed and it denies an + * unspecified permission required by the implementation. + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} method is invoked to check + * read access if the file is opened for reading. The {@link + * SecurityManager#checkWrite(String)} method is invoked to check + * write access if the file is opened for writing + */ + public static AsynchronousFileChannel open(Path file, + Set options, + ExecutorService executor, + FileAttribute... attrs) + throws IOException + { + FileSystemProvider provider = file.getFileSystem().provider(); + return provider.newAsynchronousFileChannel(file, options, executor, attrs); + } + + private static final FileAttribute[] NO_ATTRIBUTES = new FileAttribute[0]; + + /** + * Opens or creates a file for reading and/or writing, returning an + * asynchronous file channel to access the file. + * + *

An invocation of this method behaves in exactly the same way as the + * invocation + *

+     *     ch.{@link #open(Path,Set,ExecutorService,FileAttribute[]) open}(file, opts, null, new FileAttribute<?>[0]);
+     * 
+ * where {@code opts} is a {@code Set} containing the options specified to + * this method. + * + *

The resulting channel is associated with default thread pool to which + * tasks are submitted to handle I/O events and dispatch to completion + * handlers that consume the result of asynchronous operations performed on + * the resulting channel. + * + * @param file + * The path of the file to open or create + * @param options + * Options specifying how the file is opened + * + * @return A new asynchronous file channel + * + * @throws IllegalArgumentException + * If the set contains an invalid combination of options + * @throws UnsupportedOperationException + * If the {@code file} is associated with a provider that does not + * support creating file channels, or an unsupported open option is + * specified + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * If a security manager is installed and it denies an + * unspecified permission required by the implementation. + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} method is invoked to check + * read access if the file is opened for reading. The {@link + * SecurityManager#checkWrite(String)} method is invoked to check + * write access if the file is opened for writing + */ + public static AsynchronousFileChannel open(Path file, OpenOption... options) + throws IOException + { + Set set = new HashSet(options.length); + Collections.addAll(set, options); + return open(file, set, null, NO_ATTRIBUTES); + } + + /** + * Returns the current size of this channel's file. + * + * @return The current size of this channel's file, measured in bytes + * + * @throws ClosedChannelException + * If this channel is closed + * @throws IOException + * If some other I/O error occurs + */ + public abstract long size() throws IOException; + + /** + * Truncates this channel's file to the given size. + * + *

If the given size is less than the file's current size then the file + * is truncated, discarding any bytes beyond the new end of the file. If + * the given size is greater than or equal to the file's current size then + * the file is not modified.

+ * + * @param size + * The new size, a non-negative byte count + * + * @return This file channel + * + * @throws NonWritableChannelException + * If this channel was not opened for writing + * + * @throws ClosedChannelException + * If this channel is closed + * + * @throws IllegalArgumentException + * If the new size is negative + * + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousFileChannel truncate(long size) throws IOException; + + /** + * Forces any updates to this channel's file to be written to the storage + * device that contains it. + * + *

If this channel's file resides on a local storage device then when + * this method returns it is guaranteed that all changes made to the file + * since this channel was created, or since this method was last invoked, + * will have been written to that device. This is useful for ensuring that + * critical information is not lost in the event of a system crash. + * + *

If the file does not reside on a local device then no such guarantee + * is made. + * + *

The {@code metaData} parameter can be used to limit the number of + * I/O operations that this method is required to perform. Passing + * {@code false} for this parameter indicates that only updates to the + * file's content need be written to storage; passing {@code true} + * indicates that updates to both the file's content and metadata must be + * written, which generally requires at least one more I/O operation. + * Whether this parameter actually has any effect is dependent upon the + * underlying operating system and is therefore unspecified. + * + *

Invoking this method may cause an I/O operation to occur even if the + * channel was only opened for reading. Some operating systems, for + * example, maintain a last-access time as part of a file's metadata, and + * this time is updated whenever the file is read. Whether or not this is + * actually done is system-dependent and is therefore unspecified. + * + *

This method is only guaranteed to force changes that were made to + * this channel's file via the methods defined in this class. + * + * @param metaData + * If {@code true} then this method is required to force changes + * to both the file's content and metadata to be written to + * storage; otherwise, it need only force content changes to be + * written + * + * @throws ClosedChannelException + * If this channel is closed + * + * @throws IOException + * If some other I/O error occurs + */ + public abstract void force(boolean metaData) throws IOException; + + /** + * Acquires a lock on the given region of this channel's file. + * + *

This method initiates an operation to acquire a lock on the given region + * of this channel's file. The method returns a {@code Future} representing + * the pending result of the operation. Its {@link Future#get() get} + * method returns the {@link FileLock} on successful completion. + * + *

The region specified by the {@code position} and {@code size} + * parameters need not be contained within, or even overlap, the actual + * underlying file. Lock regions are fixed in size; if a locked region + * initially contains the end of the file and the file grows beyond the + * region then the new portion of the file will not be covered by the lock. + * If a file is expected to grow in size and a lock on the entire file is + * required then a region starting at zero, and no smaller than the + * expected maximum size of the file, should be locked. The two-argument + * {@link #lock(Object,CompletionHandler)} method simply locks a region + * of size {@link Long#MAX_VALUE}. If a lock that overlaps the requested + * region is already held by this Java virtual machine, or this method has + * been invoked to lock an overlapping region and that operation has not + * completed, then this method throws {@link OverlappingFileLockException}. + * + *

Some operating systems do not support a mechanism to acquire a file + * lock in an asynchronous manner. Consequently an implementation may + * acquire the file lock in a background thread or from a task executed by + * a thread in the associated thread pool. If there are many lock operations + * outstanding then it may consume threads in the Java virtual machine for + * indefinite periods. + * + *

Some operating systems do not support shared locks, in which case a + * request for a shared lock is automatically converted into a request for + * an exclusive lock. Whether the newly-acquired lock is shared or + * exclusive may be tested by invoking the resulting lock object's {@link + * FileLock#isShared() isShared} method. + * + *

File locks are held on behalf of the entire Java virtual machine. + * They are not suitable for controlling access to a file by multiple + * threads within the same virtual machine. + * + * @param position + * The position at which the locked region is to start; must be + * non-negative + * @param size + * The size of the locked region; must be non-negative, and the sum + * {@code position} + {@code size} must be non-negative + * @param shared + * {@code true} to request a shared lock, in which case this + * channel must be open for reading (and possibly writing); + * {@code false} to request an exclusive lock, in which case this + * channel must be open for writing (and possibly reading) + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws OverlappingFileLockException + * If a lock that overlaps the requested region is already held by + * this Java virtual machine, or there is already a pending attempt + * to lock an overlapping region + * @throws IllegalArgumentException + * If the preconditions on the parameters do not hold + * @throws NonReadableChannelException + * If {@code shared} is true this channel but was not opened for reading + * @throws NonWritableChannelException + * If {@code shared} is false but this channel was not opened for writing + * @throws ShutdownChannelGroupException + * If a handler is specified, the channel is closed, and the channel + * was originally created with its own thread pool + */ + public abstract Future lock(long position, + long size, + boolean shared, + A attachment, + CompletionHandler handler); + + /** + * Acquires an exclusive lock on this channel's file. + * + *

This method initiates an operation to acquire an exclusive lock on this + * channel's file. The method returns a {@code Future} representing + * the pending result of the operation. Its {@link Future#get() get} + * method returns the {@link FileLock} on successful completion. + * + *

An invocation of this method of the form {@code ch.lock(att,handler)} + * behaves in exactly the same way as the invocation + *

+     *     ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, att, handler)
+     * 
+ * + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return a {@code Future} object representing the pending result + * + * @throws OverlappingFileLockException + * If a lock is already held by this Java virtual machine, or there + * is already a pending attempt to lock a region + * @throws NonWritableChannelException + * If this channel was not opened for writing + * @throws ShutdownChannelGroupException + * If a handler is specified, the channel is closed, and the channel + * was originally created with its own thread pool + */ + public final Future lock(A attachment, + CompletionHandler handler) + { + return lock(0L, Long.MAX_VALUE, false, attachment, handler); + } + + /** + * Acquires an exclusive lock on this channel's file. + * + *

This method initiates an operation to acquire an exclusive lock on this + * channel's file. The method returns a {@code Future} representing the + * pending result of the operation. Its {@link Future#get() get} method + * returns the {@link FileLock} on successful completion. + * + *

An invocation of this method behaves in exactly the same way as the + * invocation + *

+     *     ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, null, null)
+     * 
+ * + * @return A {@code Future} object representing the pending result + * + * @throws OverlappingFileLockException + * If a lock is already held by this Java virtual machine, or there + * is already a pending attempt to lock a region + * @throws NonWritableChannelException + * If this channel was not opened for writing + */ + public final Future lock() { + return lock(0L, Long.MAX_VALUE, false, null, null); + } + + /** + * Attempts to acquire a lock on the given region of this channel's file. + * + *

This method does not block. An invocation always returns immediately, + * either having acquired a lock on the requested region or having failed to + * do so. If it fails to acquire a lock because an overlapping lock is held + * by another program then it returns {@code null}. If it fails to acquire + * a lock for any other reason then an appropriate exception is thrown. + * + * @param position + * The position at which the locked region is to start; must be + * non-negative + * + * @param size + * The size of the locked region; must be non-negative, and the sum + * {@code position} + {@code size} must be non-negative + * + * @param shared + * {@code true} to request a shared lock, + * {@code false} to request an exclusive lock + * + * @return A lock object representing the newly-acquired lock, + * or {@code null} if the lock could not be acquired + * because another program holds an overlapping lock + * + * @throws IllegalArgumentException + * If the preconditions on the parameters do not hold + * @throws ClosedChannelException + * If this channel is closed + * @throws OverlappingFileLockException + * If a lock that overlaps the requested region is already held by + * this Java virtual machine, or if another thread is already + * blocked in this method and is attempting to lock an overlapping + * region of the same file + * @throws NonReadableChannelException + * If {@code shared} is true this channel but was not opened for reading + * @throws NonWritableChannelException + * If {@code shared} is false but this channel was not opened for writing + * + * @throws IOException + * If some other I/O error occurs + * + * @see #lock(Object,CompletionHandler) + * @see #lock(long,long,boolean,Object,CompletionHandler) + * @see #tryLock() + */ + public abstract FileLock tryLock(long position, long size, boolean shared) + throws IOException; + + /** + * Attempts to acquire an exclusive lock on this channel's file. + * + *

An invocation of this method of the form {@code ch.tryLock()} + * behaves in exactly the same way as the invocation + * + *

+     *     ch.{@link #tryLock(long,long,boolean) tryLock}(0L, Long.MAX_VALUE, false) 
+ * + * @return A lock object representing the newly-acquired lock, + * or {@code null} if the lock could not be acquired + * because another program holds an overlapping lock + * + * @throws ClosedChannelException + * If this channel is closed + * @throws OverlappingFileLockException + * If a lock that overlaps the requested region is already held by + * this Java virtual machine, or if another thread is already + * blocked in this method and is attempting to lock an overlapping + * region + * @throws NonWritableChannelException + * If {@code shared} is false but this channel was not opened for writing + * + * @throws IOException + * If some other I/O error occurs + * + * @see #lock(Object,CompletionHandler) + * @see #lock(long,long,boolean,Object,CompletionHandler) + * @see #tryLock(long,long,boolean) + */ + public final FileLock tryLock() throws IOException { + return tryLock(0L, Long.MAX_VALUE, false); + } + + /** + * Reads a sequence of bytes from this channel into the given buffer, + * starting at the given file position. + * + *

This method initiates the reading of a sequence of bytes from this + * channel into the given buffer, starting at the given file position. This + * method returns a {@code Future} representing the pending result of the + * operation. The Future's {@link Future#get() get} method returns the + * number of bytes read or {@code -1} if the given position is greater than + * or equal to the file's size at the time that the read is attempted. + * + *

This method works in the same manner as the {@link + * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)} + * method, except that bytes are read starting at the given file position. + * If the given file position is greater than the file's size at the time + * that the read is attempted then no bytes are read. + * + * @param dst + * The buffer into which bytes are to be transferred + * @param position + * The file position at which the transfer is to begin; + * must be non-negative + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the position is negative or the buffer is read-only + * @throws NonReadableChannelException + * If this channel was not opened for reading + * @throws ShutdownChannelGroupException + * If a handler is specified, the channel is closed, and the channel + * was originally created with its own thread pool + */ + public abstract Future read(ByteBuffer dst, + long position, + A attachment, + CompletionHandler handler); + + /** + * Reads a sequence of bytes from this channel into the given buffer, + * starting at the given file position. + * + *

This method initiates the reading of a sequence of bytes from this + * channel into the given buffer, starting at the given file position. This + * method returns a {@code Future} representing the pending result of the + * operation. The Future's {@link Future#get() get} method returns the + * number of bytes read or {@code -1} if the given position is greater + * than or equal to the file's size at the time that the read is attempted. + * + *

This method is equivalent to invoking {@link + * #read(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment} + * and handler parameters set to {@code null}. + * + * @param dst + * The buffer into which bytes are to be transferred + * @param position + * The file position at which the transfer is to begin; + * must be non-negative + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the position is negative or the buffer is read-only + * @throws NonReadableChannelException + * If this channel was not opened for reading + */ + public final Future read(ByteBuffer dst, long position) { + return read(dst, position, null, null); + } + + /** + * Writes a sequence of bytes to this channel from the given buffer, starting + * at the given file position. + * + *

This method initiates the writing of a sequence of bytes to this channel + * from the given buffer, starting at the given file position. The method + * returns a {@code Future} representing the pending result of the write + * operation. The Future's {@link Future#get() get} method returns the + * number of bytes written. + * + *

This method works in the same manner as the {@link + * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)} + * method, except that bytes are written starting at the given file position. + * If the given position is greater than the file's size, at the time that + * the write is attempted, then the file will be grown to accommodate the new + * bytes; the values of any bytes between the previous end-of-file and the + * newly-written bytes are unspecified. + * + * @param src + * The buffer from which bytes are to be transferred + * @param position + * The file position at which the transfer is to begin; + * must be non-negative + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the position is negative + * @throws NonWritableChannelException + * If this channel was not opened for writing + * @throws ShutdownChannelGroupException + * If a handler is specified, the channel is closed, and the channel + * was originally created with its own thread pool + */ + public abstract Future write(ByteBuffer src, + long position, + A attachment, + CompletionHandler handler); + + /** + * Writes a sequence of bytes to this channel from the given buffer, starting + * at the given file position. + * + *

This method initiates the writing of a sequence of bytes to this channel + * from the given buffer, starting at the given file position. The method + * returns a {@code Future} representing the pending result of the write + * operation. The Future's {@link Future#get() get} method returns the + * number of bytes written. + * + *

This method is equivalent to invoking {@link + * #write(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment} + * and handler parameters set to {@code null}. + * + * @param src + * The buffer from which bytes are to be transferred + * @param position + * The file position at which the transfer is to begin; + * must be non-negative + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the position is negative + * @throws NonWritableChannelException + * If this channel was not opened for writing + */ + public final Future write(ByteBuffer src, long position) { + return write(src, position, null, null); + } +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java new file mode 100644 index 00000000000..99c56fa59c0 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java @@ -0,0 +1,303 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.channels.spi.*; +import java.net.SocketOption; +import java.net.SocketAddress; +import java.util.concurrent.Future; +import java.io.IOException; + +/** + * An asynchronous channel for stream-oriented listening sockets. + * + *

An asynchronous server-socket channel is created by invoking the + * {@link #open open} method of this class. + * A newly-created asynchronous server-socket channel is open but not yet bound. + * It can be bound to a local address and configured to listen for connections + * by invoking the {@link #bind(SocketAddress,int) bind} method. Once bound, + * the {@link #accept(Object,CompletionHandler) accept} method + * is used to initiate the accepting of connections to the channel's socket. + * An attempt to invoke the accept method on an unbound channel will + * cause a {@link NotYetBoundException} to be thrown. + * + *

Channels of this type are safe for use by multiple concurrent threads + * though at most one accept operation can be outstanding at any time. + * If a thread initiates an accept operation before a previous accept operation + * has completed then an {@link AcceptPendingException} will be thrown. + * + *

Socket options are configured using the {@link #setOption(SocketOption,Object) + * setOption} method. Channels of this type support the following options: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option NameDescription
{@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
{@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} Re-use address
+ *
+ * Additional (implementation specific) options may also be supported. + * + *

Usage Example: + *

+ *  final AsynchronousServerSocketChannel listener =
+ *      AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));
+ *
+ *  listener.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {
+ *      public void completed(AsynchronousSocketChannel ch, Void att) {
+ *          // accept the next connection
+ *          listener.accept(null, this);
+ *
+ *          // handle this connection
+ *          handle(ch);
+ *      }
+ *      public void failed(Throwable exc, Void att) {
+ *          ...
+ *      }
+ *      public void cancelled(Void att) {
+ *          ...
+ *      }
+ *  });
+ * 
+ * + * @since 1.7 + */ + +public abstract class AsynchronousServerSocketChannel + implements AsynchronousChannel, NetworkChannel +{ + private final AsynchronousChannelProvider provider; + + /** + * Initializes a new instance of this class. + */ + protected AsynchronousServerSocketChannel(AsynchronousChannelProvider provider) { + this.provider = provider; + } + + /** + * Returns the provider that created this channel. + */ + public final AsynchronousChannelProvider provider() { + return provider; + } + + /** + * Opens an asynchronous server-socket channel. + * + *

The new channel is created by invoking the {@link + * java.nio.channels.spi.AsynchronousChannelProvider#openAsynchronousServerSocketChannel + * openAsynchronousServerSocketChannel} method on the {@link + * java.nio.channels.spi.AsynchronousChannelProvider} object that created + * the given group. If the group parameter is null then the + * resulting channel is created by the system-wide default provider, and + * bound to the default group. + * + * @param group + * The group to which the newly constructed channel should be bound, + * or null for the default group + * + * @return A new asynchronous server socket channel + * + * @throws ShutdownChannelGroupException + * If the channel group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousServerSocketChannel open(AsynchronousChannelGroup group) + throws IOException + { + AsynchronousChannelProvider provider = (group == null) ? + AsynchronousChannelProvider.provider() : group.provider(); + return provider.openAsynchronousServerSocketChannel(group); + } + + /** + * Opens an asynchronous server-socket channel. + * + *

This method returns an asynchronous server socket channel that is + * bound to the default group. This method is equivalent to evaluating + * the expression: + *

+     * open((AsynchronousChannelGroup)null);
+     * 
+ * + * @return A new asynchronous server socket channel + * + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousServerSocketChannel open() + throws IOException + { + return open(null); + } + + /** + * Binds the channel's socket to a local address and configures the socket to + * listen for connections. + * + *

An invocation of this method is equivalent to the following: + *

+     * bind(local, 0);
+     * 
+ * + * @param local + * The local address to bind the socket, or null to bind + * to an automatically assigned socket address + * + * @return This channel + * + * @throws AlreadyBoundException {@inheritDoc} + * @throws UnsupportedAddressTypeException {@inheritDoc} + * @throws SecurityException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + public final AsynchronousServerSocketChannel bind(SocketAddress local) + throws IOException + { + return bind(local, 0); + } + + /** + * Binds the channel's socket to a local address and configures the socket to + * listen for connections. + * + *

This method is used to establish an association between the socket and + * a local address. Once an association is established then the socket remains + * bound until the associated channel is closed. + * + *

The {@code backlog} parameter is the maximum number of pending + * connections on the socket. Its exact semantics are implementation specific. + * In particular, an implementation may impose a maximum length or may choose + * to ignore the parameter altogther. If the {@code backlog} parameter has + * the value {@code 0}, or a negative value, then an implementation specific + * default is used. + * + * @param local + * The local address to bind the socket, or {@code null} to bind + * to an automatically assigned socket address + * @param backlog + * The maximum number of pending connections + * + * @return This channel + * + * @throws AlreadyBoundException + * If the socket is already bound + * @throws UnsupportedAddressTypeException + * If the type of the given address is not supported + * @throws SecurityException + * If a security manager has been installed and its {@link + * SecurityManager#checkListen checkListen} method denies the operation + * @throws ClosedChannelException + * If the channel is closed + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousServerSocketChannel bind(SocketAddress local, int backlog) + throws IOException; + + /** + * @throws IllegalArgumentException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + public abstract AsynchronousServerSocketChannel setOption(SocketOption name, T value) + throws IOException; + + /** + * Accepts a connection. + * + *

This method initiates accepting a connection made to this channel's + * socket, returning a {@link Future} representing the pending result + * of the operation. The {@code Future}'s {@link Future#get() get} + * method will return the {@link AsynchronousSocketChannel} for the new + * connection on successful completion. + * + *

When a new connection is accepted then the resulting {@code + * AsynchronousSocketChannel} will be bound to the same {@link + * AsynchronousChannelGroup} as this channel. If the group is {@link + * AsynchronousChannelGroup#isShutdown shutdown} and a connection is accepted, + * then the connection is closed, and the operation completes with an {@code + * IOException} and cause {@link ShutdownChannelGroupException}. + * + *

To allow for concurrent handling of new connections, the completion + * handler is not invoked directly by the initiating thread when a new + * connection is accepted immediately (see Threading). + * + *

If a security manager has been installed then it verifies that the + * address and port number of the connection's remote endpoint are permitted + * by the security manager's {@link SecurityManager#checkAccept checkAccept} + * method. The permission check is performed with privileges that are restricted + * by the calling context of this method. If the permission check fails then + * the connection is closed and the operation completes with a {@link + * SecurityException}. + * + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return an Future object representing the pending result + * + * @throws AcceptPendingException + * If an accept operation is already in progress on this channel + * @throws NotYetBoundException + * If this channel's socket has not yet been bound + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future + accept(A attachment, CompletionHandler handler); + + /** + * Accepts a connection. + * + *

This method is equivalent to invoking {@link + * #accept(Object,CompletionHandler)} with the {@code attachment} + * and {@code handler} parameters set to {@code null}. + * + * @return an Future object representing the pending result + * + * @throws AcceptPendingException + * If an accept operation is already in progress on this channel + * @throws NotYetBoundException + * If this channel's socket has not yet been bound + */ + public final Future accept() { + return accept(null, null); + } +} diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java new file mode 100644 index 00000000000..b6a5da8105d --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java @@ -0,0 +1,670 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.channels.spi.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.Future; +import java.io.IOException; +import java.net.SocketOption; +import java.net.SocketAddress; +import java.nio.ByteBuffer; + +/** + * An asynchronous channel for stream-oriented connecting sockets. + * + *

Asynchronous socket channels are created in one of two ways. A newly-created + * {@code AsynchronousSocketChannel} is created by invoking one of the {@link + * #open open} methods defined by this class. A newly-created channel is open but + * not yet connected. A connected {@code AsynchronousSocketChannel} is created + * when a connection is made to the socket of an {@link AsynchronousServerSocketChannel}. + * It is not possible to create an asynchronous socket channel for an arbitrary, + * pre-existing {@link java.net.Socket socket}. + * + *

A newly-created channel is connected by invoking its {@link #connect connect} + * method; once connected, a channel remains connected until it is closed. Whether + * or not a socket channel is connected may be determined by invoking its {@link + * #getRemoteAddress getRemoteAddress} method. An attempt to invoke an I/O + * operation upon an unconnected channel will cause a {@link NotYetConnectedException} + * to be thrown. + * + *

Channels of this type are safe for use by multiple concurrent threads. + * They support concurrent reading and writing, though at most one read operation + * and one write operation can be outstanding at any time. + * If a thread initiates a read operation before a previous read operation has + * completed then a {@link ReadPendingException} will be thrown. Similarly, an + * attempt to initiate a write operation before a previous write has completed + * will throw a {@link WritePendingException}. + * + *

Socket options are configured using the {@link #setOption(SocketOption,Object) + * setOption} method. Asynchronous socket channels support the following options: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option NameDescription
{@link java.net.StandardSocketOption#SO_SNDBUF SO_SNDBUF} The size of the socket send buffer
{@link java.net.StandardSocketOption#SO_RCVBUF SO_RCVBUF} The size of the socket receive buffer
{@link java.net.StandardSocketOption#SO_KEEPALIVE SO_KEEPALIVE} Keep connection alive
{@link java.net.StandardSocketOption#SO_REUSEADDR SO_REUSEADDR} Re-use address
{@link java.net.StandardSocketOption#TCP_NODELAY TCP_NODELAY} Disable the Nagle algorithm
+ *
+ * Additional (implementation specific) options may also be supported. + * + *

Timeouts

+ * + *

The {@link #read(ByteBuffer,long,TimeUnit,Object,CompletionHandler) read} + * and {@link #write(ByteBuffer,long,TimeUnit,Object,CompletionHandler) write} + * methods defined by this class allow a timeout to be specified when initiating + * a read or write operation. If the timeout elapses before an operation completes + * then the operation completes with the exception {@link + * InterruptedByTimeoutException}. A timeout may leave the channel, or the + * underlying connection, in an inconsistent state. Where the implementation + * cannot guarantee that bytes have not been read from the channel then it puts + * the channel into an implementation specific error state. A subsequent + * attempt to initiate a {@code read} operation causes an unspecified runtime + * exception to be thrown. Similarly if a {@code write} operation times out and + * the implementation cannot guarantee bytes have not been written to the + * channel then further attempts to {@code write} to the channel cause an + * unspecified runtime exception to be thrown. When a timeout elapses then the + * state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O + * operation is not defined. Buffers should be discarded or at least care must + * be taken to ensure that the buffers are not accessed while the channel remains + * open. + * + * @since 1.7 + */ + +public abstract class AsynchronousSocketChannel + implements AsynchronousByteChannel, NetworkChannel +{ + private final AsynchronousChannelProvider provider; + + /** + * Initializes a new instance of this class. + */ + protected AsynchronousSocketChannel(AsynchronousChannelProvider provider) { + this.provider = provider; + } + + /** + * Returns the provider that created this channel. + */ + public final AsynchronousChannelProvider provider() { + return provider; + } + + /** + * Opens an asynchronous socket channel. + * + *

The new channel is created by invoking the {@link + * AsynchronousChannelProvider#openAsynchronousSocketChannel + * openAsynchronousSocketChannel} method on the {@link + * AsynchronousChannelProvider} that created the group. If the group parameter + * is {@code null} then the resulting channel is created by the system-wide + * default provider, and bound to the default group. + * + * @param group + * The group to which the newly constructed channel should be bound, + * or {@code null} for the default group + * + * @return A new asynchronous socket channel + * + * @throws ShutdownChannelGroupException + * If the channel group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousSocketChannel open(AsynchronousChannelGroup group) + throws IOException + { + AsynchronousChannelProvider provider = (group == null) ? + AsynchronousChannelProvider.provider() : group.provider(); + return provider.openAsynchronousSocketChannel(group); + } + + /** + * Opens an asynchronous socket channel. + * + *

This method returns an asynchronous socket channel that is bound to + * the default group.This method is equivalent to evaluating the + * expression: + *

+     * open((AsynchronousChannelGroup)null);
+     * 
+ * + * @return A new asynchronous socket channel + * + * @throws IOException + * If an I/O error occurs + */ + public static AsynchronousSocketChannel open() + throws IOException + { + return open(null); + } + + + // -- socket options and related -- + + /** + * @throws ConnectionPendingException + * If a connection operation is already in progress on this channel + * @throws AlreadyBoundException {@inheritDoc} + * @throws UnsupportedAddressTypeException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract AsynchronousSocketChannel bind(SocketAddress local) + throws IOException; + + /** + * @throws IllegalArgumentException {@inheritDoc} + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract AsynchronousSocketChannel setOption(SocketOption name, T value) + throws IOException; + + /** + * Shutdown the connection for reading without closing the channel. + * + *

Once shutdown for reading then further reads on the channel will + * return {@code -1}, the end-of-stream indication. If the input side of the + * connection is already shutdown then invoking this method has no effect. + * The effect on an outstanding read operation is system dependent and + * therefore not specified. The effect, if any, when there is data in the + * socket receive buffer that has not been read, or data arrives subsequently, + * is also system dependent. + * + * @return The channel + * + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ClosedChannelException + * If this channel is closed + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousSocketChannel shutdownInput() throws IOException; + + /** + * Shutdown the connection for writing without closing the channel. + * + *

Once shutdown for writing then further attempts to write to the + * channel will throw {@link ClosedChannelException}. If the output side of + * the connection is already shutdown then invoking this method has no + * effect. The effect on an outstanding write operation is system dependent + * and therefore not specified. + * + * @return The channel + * + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ClosedChannelException + * If this channel is closed + * @throws IOException + * If some other I/O error occurs + */ + public abstract AsynchronousSocketChannel shutdownOutput() throws IOException; + + // -- state -- + + /** + * Returns the remote address to which this channel's socket is connected. + * + *

Where the channel is bound and connected to an Internet Protocol + * socket address then the return value from this method is of type {@link + * java.net.InetSocketAddress}. + * + * @return The remote address; {@code null} if the channel's socket is not + * connected + * + * @throws ClosedChannelException + * If the channel is closed + * @throws IOException + * If an I/O error occurs + */ + public abstract SocketAddress getRemoteAddress() throws IOException; + + // -- asynchronous operations -- + + /** + * Connects this channel. + * + *

This method initiates an operation to connect this channel, returning + * a {@code Future} representing the pending result of the operation. If + * the connection is successfully established then the {@code Future}'s + * {@link Future#get() get} method will return {@code null}. If the + * connection cannot be established then the channel is closed. In that case, + * invoking the {@code get} method throws {@link + * java.util.concurrent.ExecutionException} with an {@code IOException} as + * the cause. + * + *

This method performs exactly the same security checks as the {@link + * java.net.Socket} class. That is, if a security manager has been + * installed then this method verifies that its {@link + * java.lang.SecurityManager#checkConnect checkConnect} method permits + * connecting to the address and port number of the given remote endpoint. + * + * @param remote + * The remote address to which this channel is to be connected + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws UnresolvedAddressException + * If the given remote address is not fully resolved + * @throws UnsupportedAddressTypeException + * If the type of the given remote address is not supported + * @throws AlreadyConnectedException + * If this channel is already connected + * @throws ConnectionPendingException + * If a connection operation is already in progress on this channel + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + * @throws SecurityException + * If a security manager has been installed + * and it does not permit access to the given remote endpoint + * + * @see #getRemoteAddress + */ + public abstract Future connect(SocketAddress remote, + A attachment, + CompletionHandler handler); + + /** + * Connects this channel. + * + *

This method is equivalent to invoking {@link + * #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment} + * and handler parameters set to {@code null}. + * + * @param remote + * The remote address to which this channel is to be connected + * + * @return A {@code Future} object representing the pending result + * + * @throws UnresolvedAddressException + * If the given remote address is not fully resolved + * @throws UnsupportedAddressTypeException + * If the type of the given remote address is not supported + * @throws AlreadyConnectedException + * If this channel is already connected + * @throws ConnectionPendingException + * If a connection operation is already in progress on this channel + * @throws SecurityException + * If a security manager has been installed + * and it does not permit access to the given remote endpoint + */ + public final Future connect(SocketAddress remote) { + return connect(remote, null, null); + } + + /** + * Reads a sequence of bytes from this channel into the given buffer. + * + *

This method initiates the reading of a sequence of bytes from this + * channel into the given buffer, returning a {@code Future} representing + * the pending result of the operation. The {@code Future}'s {@link + * Future#get() get} method returns the number of bytes read or {@code -1} + * if all bytes have been read and channel has reached end-of-stream. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then the operation completes with the exception {@link + * InterruptedByTimeoutException}. Where a timeout occurs, and the + * implementation cannot guarantee that bytes have not been read, or will not + * be read from the channel into the given buffer, then further attempts to + * read from the channel will cause an unspecific runtime exception to be + * thrown. + * + *

Otherwise this method works in the same manner as the {@link + * AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)} + * method. + * + * @param dst + * The buffer into which bytes are to be transferred + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the {@code timeout} parameter is negative or the buffer is + * read-only + * @throws ReadPendingException + * If a read operation is already in progress on this channel + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future read(ByteBuffer dst, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * @throws IllegalArgumentException {@inheritDoc} + * @throws ReadPendingException {@inheritDoc} + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future read(ByteBuffer dst, + A attachment, + CompletionHandler handler) + { + return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * @throws IllegalArgumentException {@inheritDoc} + * @throws ReadPendingException {@inheritDoc} + * @throws NotYetConnectedException + * If this channel is not yet connected + */ + @Override + public final Future read(ByteBuffer dst) { + return read(dst, 0L, TimeUnit.MILLISECONDS, null, null); + } + + /** + * Reads a sequence of bytes from this channel into a subsequence of the + * given buffers. This operation, sometimes called a scattering read, + * is often useful when implementing network protocols that group data into + * segments consisting of one or more fixed-length headers followed by a + * variable-length body. + * + *

This method initiates a read of up to r bytes from this channel, + * where r is the total number of bytes remaining in the specified + * subsequence of the given buffer array, that is, + * + *

+     * dsts[offset].remaining()
+     *     + dsts[offset+1].remaining()
+     *     + ... + dsts[offset+length-1].remaining()
+ * + * at the moment that the read is attempted. + * + *

Suppose that a byte sequence of length n is read, where + * 0 < n <= r. + * Up to the first dsts[offset].remaining() bytes of this sequence + * are transferred into buffer dsts[offset], up to the next + * dsts[offset+1].remaining() bytes are transferred into buffer + * dsts[offset+1], and so forth, until the entire byte sequence + * is transferred into the given buffers. As many bytes as possible are + * transferred into each buffer, hence the final position of each updated + * buffer, except the last updated buffer, is guaranteed to be equal to + * that buffer's limit. The underlying operating system may impose a limit + * on the number of buffers that may be used in an I/O operation. Where the + * number of buffers (with bytes remaining), exceeds this limit, then the + * I/O operation is performed with the maximum number of buffers allowed by + * the operating system. + * + *

The return value from this method is a {@code Future} representing + * the pending result of the operation. The {@code Future}'s {@link + * Future#get() get} method returns the number of bytes read or {@code -1L} + * if all bytes have been read and the channel has reached end-of-stream. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then it completes with the exception {@link + * InterruptedByTimeoutException}. Where a timeout occurs, and the + * implementation cannot guarantee that bytes have not been read, or will not + * be read from the channel into the given buffers, then further attempts to + * read from the channel will cause an unspecific runtime exception to be + * thrown. + * + * @param dsts + * The buffers into which bytes are to be transferred + * @param offset + * The offset within the buffer array of the first buffer into which + * bytes are to be transferred; must be non-negative and no larger than + * {@code dsts.length} + * @param length + * The maximum number of buffers to be accessed; must be non-negative + * and no larger than {@code dsts.length - offset} + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IndexOutOfBoundsException + * If the pre-conditions for the {@code offset} and {@code length} + * parameter aren't met + * @throws IllegalArgumentException + * If the {@code timeout} parameter is negative, or a buffer is + * read-only + * @throws ReadPendingException + * If a read operation is already in progress on this channel + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future read(ByteBuffer[] dsts, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * Writes a sequence of bytes to this channel from the given buffer. + * + *

This method initiates the writing of a sequence of bytes to this channel + * from the given buffer, returning a {@code Future} representing the + * pending result of the operation. The {@code Future}'s {@link Future#get() + * get} method will return the number of bytes written. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then it completes with the exception {@link + * InterruptedByTimeoutException}. Where a timeout occurs, and the + * implementation cannot guarantee that bytes have not been written, or will + * not be written to the channel from the given buffer, then further attempts + * to write to the channel will cause an unspecific runtime exception to be + * thrown. + * + *

Otherwise this method works in the same manner as the {@link + * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)} + * method. + * + * @param src + * The buffer from which bytes are to be retrieved + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IllegalArgumentException + * If the {@code timeout} parameter is negative + * @throws WritePendingException + * If a write operation is already in progress on this channel + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future write(ByteBuffer src, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + /** + * @throws WritePendingException {@inheritDoc} + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + @Override + public final Future write(ByteBuffer src, + A attachment, + CompletionHandler handler) + + { + return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler); + } + + /** + * @throws WritePendingException {@inheritDoc} + * @throws NotYetConnectedException + * If this channel is not yet connected + */ + @Override + public final Future write(ByteBuffer src) { + return write(src, 0L, TimeUnit.MILLISECONDS, null, null); + } + + /** + * Writes a sequence of bytes to this channel from a subsequence of the given + * buffers. This operation, sometimes called a gathering write, is + * often useful when implementing network protocols that group data into + * segments consisting of one or more fixed-length headers followed by a + * variable-length body. + * + *

This method initiates a write of up to r bytes to this channel, + * where r is the total number of bytes remaining in the specified + * subsequence of the given buffer array, that is, + * + *

+     * srcs[offset].remaining()
+     *     + srcs[offset+1].remaining()
+     *     + ... + srcs[offset+length-1].remaining()
+ * + * at the moment that the write is attempted. + * + *

Suppose that a byte sequence of length n is written, where + * 0 < n <= r. + * Up to the first srcs[offset].remaining() bytes of this sequence + * are written from buffer srcs[offset], up to the next + * srcs[offset+1].remaining() bytes are written from buffer + * srcs[offset+1], and so forth, until the entire byte sequence is + * written. As many bytes as possible are written from each buffer, hence + * the final position of each updated buffer, except the last updated + * buffer, is guaranteed to be equal to that buffer's limit. The underlying + * operating system may impose a limit on the number of buffers that may be + * used in an I/O operation. Where the number of buffers (with bytes + * remaining), exceeds this limit, then the I/O operation is performed with + * the maximum number of buffers allowed by the operating system. + * + *

The return value from this method is a {@code Future} representing + * the pending result of the operation. The {@code Future}'s {@link + * Future#get() get} method will return the number of bytes written. + * + *

If a timeout is specified and the timeout elapses before the operation + * completes then it completes with the exception {@link + * InterruptedByTimeoutException}. Where a timeout occurs, and the + * implementation cannot guarantee that bytes have not been written, or will + * not be written to the channel from the given buffers, then further attempts + * to write to the channel will cause an unspecific runtime exception to be + * thrown. + * + * @param srcs + * The buffers from which bytes are to be retrieved + * @param offset + * The offset within the buffer array of the first buffer from which + * bytes are to be retrieved; must be non-negative and no larger + * than {@code srcs.length} + * @param length + * The maximum number of buffers to be accessed; must be non-negative + * and no larger than {@code srcs.length - offset} + * @param timeout + * The timeout, or {@code 0L} for no timeout + * @param unit + * The time unit of the {@code timeout} argument + * @param attachment + * The object to attach to the I/O operation; can be {@code null} + * @param handler + * The handler for consuming the result; can be {@code null} + * + * @return A {@code Future} object representing the pending result + * + * @throws IndexOutOfBoundsException + * If the pre-conditions for the {@code offset} and {@code length} + * parameter aren't met + * @throws IllegalArgumentException + * If the {@code timeout} parameter is negative + * @throws WritePendingException + * If a write operation is already in progress on this channel + * @throws NotYetConnectedException + * If this channel is not yet connected + * @throws ShutdownChannelGroupException + * If a handler is specified, and the channel group is shutdown + */ + public abstract Future write(ByteBuffer[] srcs, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); +} diff --git a/jdk/src/share/classes/java/nio/channels/Channels.java b/jdk/src/share/classes/java/nio/channels/Channels.java index cab96048629..4fdcef8abb0 100644 --- a/jdk/src/share/classes/java/nio/channels/Channels.java +++ b/jdk/src/share/classes/java/nio/channels/Channels.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,15 +33,12 @@ import java.io.Reader; import java.io.Writer; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.BufferOverflowException; -import java.nio.BufferUnderflowException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; import java.nio.charset.UnsupportedCharsetException; import java.nio.channels.spi.AbstractInterruptibleChannel; +import java.util.concurrent.ExecutionException; import sun.nio.ch.ChannelInputStream; import sun.nio.cs.StreamDecoder; import sun.nio.cs.StreamEncoder; @@ -184,6 +181,155 @@ public final class Channels { }; } + /** + * {@note new} + * Constructs a stream that reads bytes from the given channel. + * + *

The stream will not be buffered, and it will not support the {@link + * InputStream#mark mark} or {@link InputStream#reset reset} methods. The + * stream will be safe for access by multiple concurrent threads. Closing + * the stream will in turn cause the channel to be closed.

+ * + * @param ch + * The channel from which bytes will be read + * + * @return A new input stream + * + * @since 1.7 + */ + public static InputStream newInputStream(final AsynchronousByteChannel ch) { + checkNotNull(ch, "ch"); + return new InputStream() { + + private ByteBuffer bb = null; + private byte[] bs = null; // Invoker's previous array + private byte[] b1 = null; + + @Override + public synchronized int read() throws IOException { + if (b1 == null) + b1 = new byte[1]; + int n = this.read(b1); + if (n == 1) + return b1[0] & 0xff; + return -1; + } + + @Override + public synchronized int read(byte[] bs, int off, int len) + throws IOException + { + if ((off < 0) || (off > bs.length) || (len < 0) || + ((off + len) > bs.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) + return 0; + + ByteBuffer bb = ((this.bs == bs) + ? this.bb + : ByteBuffer.wrap(bs)); + bb.position(off); + bb.limit(Math.min(off + len, bb.capacity())); + this.bb = bb; + this.bs = bs; + + boolean interrupted = false; + try { + for (;;) { + try { + return ch.read(bb).get(); + } catch (ExecutionException ee) { + throw new IOException(ee.getCause()); + } catch (InterruptedException ie) { + interrupted = true; + } + } + } finally { + if (interrupted) + Thread.currentThread().interrupt(); + } + } + + @Override + public void close() throws IOException { + ch.close(); + } + }; + } + + /** + * {@note new} + * Constructs a stream that writes bytes to the given channel. + * + *

The stream will not be buffered. The stream will be safe for access + * by multiple concurrent threads. Closing the stream will in turn cause + * the channel to be closed.

+ * + * @param ch + * The channel to which bytes will be written + * + * @return A new output stream + * + * @since 1.7 + */ + public static OutputStream newOutputStream(final AsynchronousByteChannel ch) { + checkNotNull(ch, "ch"); + return new OutputStream() { + + private ByteBuffer bb = null; + private byte[] bs = null; // Invoker's previous array + private byte[] b1 = null; + + @Override + public synchronized void write(int b) throws IOException { + if (b1 == null) + b1 = new byte[1]; + b1[0] = (byte)b; + this.write(b1); + } + + @Override + public synchronized void write(byte[] bs, int off, int len) + throws IOException + { + if ((off < 0) || (off > bs.length) || (len < 0) || + ((off + len) > bs.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + ByteBuffer bb = ((this.bs == bs) + ? this.bb + : ByteBuffer.wrap(bs)); + bb.limit(Math.min(off + len, bb.capacity())); + bb.position(off); + this.bb = bb; + this.bs = bs; + + boolean interrupted = false; + try { + while (bb.remaining() > 0) { + try { + ch.write(bb).get(); + } catch (ExecutionException ee) { + throw new IOException(ee.getCause()); + } catch (InterruptedException ie) { + interrupted = true; + } + } + } finally { + if (interrupted) + Thread.currentThread().interrupt(); + } + } + + @Override + public void close() throws IOException { + ch.close(); + } + }; + } + // -- Channels from streams -- @@ -468,5 +614,4 @@ public final class Channels { checkNotNull(csName, "csName"); return newWriter(ch, Charset.forName(csName).newEncoder(), -1); } - } diff --git a/jdk/src/share/classes/java/nio/channels/CompletionHandler.java b/jdk/src/share/classes/java/nio/channels/CompletionHandler.java new file mode 100644 index 00000000000..c4d4add8ff9 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/CompletionHandler.java @@ -0,0 +1,77 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +/** + * A handler for consuming the result of an asynchronous I/O operation. + * + *

The asynchronous channels defined in this package allow a completion + * handler to be specified to consume the result of an asynchronous operation. + * The {@link #completed completed} method is invoked when the I/O operation + * completes successfully. The {@link #failed failed} method is invoked if the + * I/O operations fails. The {@link #cancelled cancelled} method is invoked when + * the I/O operation is cancelled by invoking the {@link + * java.util.concurrent.Future#cancel cancel} method. The implementations of + * these methods should complete in a timely manner so as to avoid keeping the + * invoking thread from dispatching to other completion handlers. + * + * @param The result type of the I/O operation + * @param The type of the object attached to the I/O operation + * + * @since 1.7 + */ + +public interface CompletionHandler { + + /** + * Invoked when an operation has completed. + * + * @param result + * The result of the I/O operation. + * @param attachment + * The object attached to the I/O operation when it was initiated. + */ + void completed(V result, A attachment); + + /** + * Invoked when an operation fails. + * + * @param exc + * The exception to indicate why the I/O operation failed + * @param attachment + * The object attached to the I/O operation when it was initiated. + */ + void failed(Throwable exc, A attachment); + + /** + * Invoked when an operation is cancelled by invoking the {@link + * java.util.concurrent.Future#cancel cancel} method. + * + * @param attachment + * The object attached to the I/O operation when it was initiated. + */ + void cancelled(A attachment); +} diff --git a/jdk/src/share/classes/java/nio/channels/DatagramChannel.java b/jdk/src/share/classes/java/nio/channels/DatagramChannel.java index b8697fa1dc6..c7bd3df8b83 100644 --- a/jdk/src/share/classes/java/nio/channels/DatagramChannel.java +++ b/jdk/src/share/classes/java/nio/channels/DatagramChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,8 @@ import java.net.DatagramSocket; import java.net.SocketOption; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.nio.channels.spi.*; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; /** * A selectable channel for datagram-oriented sockets. @@ -53,7 +54,8 @@ import java.nio.channels.spi.*; * be determined by invoking its {@link #isConnected isConnected} method. * *

Socket options are configured using the {@link #setOption(SocketOption,Object) - * setOption} method. Datagram channels support the following options: + * setOption} method. A datagram channel to an Internet Protocol socket supports + * the following options: *

* * @@ -211,6 +213,7 @@ public abstract class DatagramChannel throws IOException; /** + * @throws UnsupportedOperationException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws ClosedChannelException {@inheritDoc} * @throws IOException {@inheritDoc} @@ -220,7 +223,6 @@ public abstract class DatagramChannel public abstract DatagramChannel setOption(SocketOption name, T value) throws IOException; - /** * Retrieves a datagram socket associated with this channel. * @@ -313,15 +315,17 @@ public abstract class DatagramChannel /** * Returns the remote address to which this channel's socket is connected. * - * @return The remote address; {@code null} if the channel is not {@link - * #isOpen open} or the channel's socket is not connected + * @return The remote address; {@code null} if the channel's socket is not + * connected * + * @throws ClosedChannelException + * If the channel is closed * @throws IOException * If an I/O error occurs * * @since 1.7 */ - public abstract SocketAddress getConnectedAddress() throws IOException; + public abstract SocketAddress getRemoteAddress() throws IOException; /** * Receives a datagram via this channel. diff --git a/jdk/src/share/classes/java/nio/channels/FileChannel.java b/jdk/src/share/classes/java/nio/channels/FileChannel.java index e3b5f5bcb79..ab780a520a9 100644 --- a/jdk/src/share/classes/java/nio/channels/FileChannel.java +++ b/jdk/src/share/classes/java/nio/channels/FileChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,16 +29,23 @@ import java.io.*; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.spi.AbstractInterruptibleChannel; - +import java.nio.file.*; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.spi.*; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; /** * A channel for reading, writing, mapping, and manipulating a file. * - *

A file channel has a current position within its file which can - * be both {@link #position() queried} and {@link #position(long) - * modified}. The file itself contains a variable-length sequence + *

{@note revised} + * A file channel is a {@link SeekableByteChannel} that is connected to + * a file. It has a current position within its file which can + * be both {@link #position() queried} and {@link #position(long) + * modified}. The file itself contains a variable-length sequence * of bytes that can be read and written and whose current {@link #size - * size} can be queried. The size of the file increases + * size} can be queried. The size of the file increases * when bytes are written beyond its current size; the size of the file * decreases when it is {@link #truncate truncated}. The * file may also have some associated metadata such as access @@ -50,27 +57,27 @@ import java.nio.channels.spi.AbstractInterruptibleChannel; * *

    * - *
  • Bytes may be {@link #read(ByteBuffer, long) read} or - * {@link #write(ByteBuffer, long) written} at an absolute + *

  • Bytes may be {@link #read(ByteBuffer, long) read} or + * {@link #write(ByteBuffer, long) written} at an absolute * position in a file in a way that does not affect the channel's current * position.

  • * - *
  • A region of a file may be {@link #map mapped} + *

  • A region of a file may be {@link #map mapped} * directly into memory; for large files this is often much more efficient * than invoking the usual read or write methods. *

  • * - *
  • Updates made to a file may be {@link #force forced - * out} to the underlying storage device, ensuring that data are not + *

  • Updates made to a file may be {@link #force forced + * out} to the underlying storage device, ensuring that data are not * lost in the event of a system crash.

  • * - *
  • Bytes can be transferred from a file {@link #transferTo to - * some other channel}, and {@link #transferFrom vice - * versa}, in a way that can be optimized by many operating systems + *

  • Bytes can be transferred from a file {@link #transferTo to + * some other channel}, and {@link #transferFrom vice + * versa}, in a way that can be optimized by many operating systems * into a very fast transfer directly to or from the filesystem cache. *

  • * - *
  • A region of a file may be {@link FileLock locked} + *

  • A region of a file may be {@link FileLock locked} * against access by other programs.

  • * *
@@ -96,25 +103,23 @@ import java.nio.channels.spi.AbstractInterruptibleChannel; * machine. The exact nature of any such inconsistencies are system-dependent * and are therefore unspecified. * - *

This class does not define methods for opening existing files or for - * creating new ones; such methods may be added in a future release. In this - * release a file channel can be obtained from an existing {@link - * java.io.FileInputStream#getChannel FileInputStream}, {@link + *

A file channel is created by invoking one of the {@link #open open} + * methods defined by this class. A file channel can also be obtained from an + * existing {@link java.io.FileInputStream#getChannel FileInputStream}, {@link * java.io.FileOutputStream#getChannel FileOutputStream}, or {@link * java.io.RandomAccessFile#getChannel RandomAccessFile} object by invoking * that object's getChannel method, which returns a file channel that - * is connected to the same underlying file. + * is connected to the same underlying file. Where the file channel is obtained + * from an existing stream or random access file then the state of the file + * channel is intimately connected to that of the object whose getChannel + * method returned the channel. Changing the channel's position, whether + * explicitly or by reading or writing bytes, will change the file position of + * the originating object, and vice versa. Changing the file's length via the + * file channel will change the length seen via the originating object, and vice + * versa. Changing the file's content by writing bytes will change the content + * seen by the originating object, and vice versa. * - *

The state of a file channel is intimately connected to that of the - * object whose getChannel method returned the channel. Changing the - * channel's position, whether explicitly or by reading or writing bytes, will - * change the file position of the originating object, and vice versa. - * Changing the file's length via the file channel will change the length seen - * via the originating object, and vice versa. Changing the file's content by - * writing bytes will change the content seen by the originating object, and - * vice versa. - * - *

At various points this class specifies that an + *

At various points this class specifies that an * instance that is "open for reading," "open for writing," or "open for * reading and writing" is required. A channel obtained via the {@link * java.io.FileInputStream#getChannel getChannel} method of a {@link @@ -127,7 +132,7 @@ import java.nio.channels.spi.AbstractInterruptibleChannel; * was created with mode "r" and will be open for reading and writing * if the instance was created with mode "rw". * - *

A file channel that is open for writing may be in + *

A file channel that is open for writing may be in * append mode, for example if it was obtained from a file-output stream * that was created by invoking the {@link * java.io.FileOutputStream#FileOutputStream(java.io.File,boolean) @@ -138,7 +143,6 @@ import java.nio.channels.spi.AbstractInterruptibleChannel; * of the data are done in a single atomic operation is system-dependent and * therefore unspecified. * - * * @see java.io.FileInputStream#getChannel() * @see java.io.FileOutputStream#getChannel() * @see java.io.RandomAccessFile#getChannel() @@ -147,18 +151,190 @@ import java.nio.channels.spi.AbstractInterruptibleChannel; * @author Mike McCloskey * @author JSR-51 Expert Group * @since 1.4 + * @updated 1.7 */ public abstract class FileChannel extends AbstractInterruptibleChannel - implements ByteChannel, GatheringByteChannel, ScatteringByteChannel + implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel { - /** * Initializes a new instance of this class. */ protected FileChannel() { } + /** + * {@note new} + * Opens or creates a file, returning a file channel to access the file. + * + *

The {@code options} parameter determines how the file is opened. + * The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE + * WRITE} options determine if the file should be opened for reading and/or + * writing. If neither option (or the {@link StandardOpenOption#APPEND APPEND} + * option) is contained in the array then the file is opened for reading. + * By default reading or writing commences at the beginning of the file. + * + *

In the addition to {@code READ} and {@code WRITE}, the following + * options may be present: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option Description
{@link StandardOpenOption#APPEND APPEND} If this option is present then the file is opened for writing and + * each invocation of the channel's {@code write} method first advances + * the position to the end of the file and then writes the requested + * data. Whether the advancement of the position and the writing of the + * data are done in a single atomic operation is system-dependent and + * therefore unspecified. This option may not be used in conjunction + * with the {@code READ} or {@code TRUNCATE_EXISTING} options.
{@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} If this option is present then the existing file is truncated to + * a size of 0 bytes. This option is ignored when the file is opened only + * for reading.
{@link StandardOpenOption#CREATE_NEW CREATE_NEW} If this option is present then a new file is created, failing if + * the file already exists. When creating a file the check for the + * existence of the file and the creation of the file if it does not exist + * is atomic with respect to other file system operations. This option is + * ignored when the file is opened only for reading.
{@link StandardOpenOption#CREATE CREATE} If this option is present then an existing file is opened if it + * exists, otherwise a new file is created. When creating a file the check + * for the existence of the file and the creation of the file if it does + * not exist is atomic with respect to other file system operations. This + * option is ignored if the {@code CREATE_NEW} option is also present or + * the file is opened only for reading.
{@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} When this option is present then the implementation makes a + * best effort attempt to delete the file when closed by the + * the {@link #close close} method. If the {@code close} method is not + * invoked then a best effort attempt is made to delete the file + * when the Java virtual machine terminates.
{@link StandardOpenOption#SPARSE SPARSE} When creating a new file this option is a hint that the + * new file will be sparse. This option is ignored when not creating + * a new file.
{@link StandardOpenOption#SYNC SYNC} Requires that every update to the file's content or metadata be + * written synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
{@link StandardOpenOption#DSYNC DSYNC} Requires that every update to the file's content be written + * synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
+ * + *

An implementation may also support additional options. + * + *

The {@code attrs} parameter is an optional array of file {@link + * FileAttribute file-attributes} to set atomically when creating the file. + * + *

The new channel is created by invoking the {@link + * FileSystemProvider#newFileChannel newFileChannel} method on the + * provider that created the {@code Path}. + * + * @param file + * The path of the file to open or create + * @param options + * Options specifying how the file is opened + * @param attrs + * An optional list of file attributes to set atomically when + * creating the file + * + * @return A new file channel + * + * @throws IllegalArgumentException + * If the set contains an invalid combination of options + * @throws UnsupportedOperationException + * If the {@code file} is associated with a provider that does not + * support creating file channels, or an unsupported open option is + * specified, or the array contains an attribute that cannot be set + * atomically when creating the file + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * If a security manager is installed and it denies an + * unspecified permission required by the implementation. + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} method is invoked to check + * read access if the file is opened for reading. The {@link + * SecurityManager#checkWrite(String)} method is invoked to check + * write access if the file is opened for writing + * + * @since 1.7 + */ + public static FileChannel open(Path file, + Set options, + FileAttribute... attrs) + throws IOException + { + FileSystemProvider provider = file.getFileSystem().provider(); + return provider.newFileChannel(file, options, attrs); + } + + private static final FileAttribute[] NO_ATTRIBUTES = new FileAttribute[0]; + + /** + * {@note new} + * Opens or creates a file, returning a file channel to access the file. + * + *

An invocation of this method behaves in exactly the same way as the + * invocation + *

+     *     fc.{@link #open(Path,Set,FileAttribute[]) open}(file, options, new FileAttribute<?>[0]);
+     * 
+ * + * @param file + * The path of the file to open or create + * @param options + * Options specifying how the file is opened + * + * @return A new file channel + * + * @throws IllegalArgumentException + * If the set contains an invalid combination of options + * @throws UnsupportedOperationException + * If the {@code file} is associated with a provider that does not + * support creating file channels, or an unsupported open option is + * specified + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * If a security manager is installed and it denies an + * unspecified permission required by the implementation. + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} method is invoked to check + * read access if the file is opened for reading. The {@link + * SecurityManager#checkWrite(String)} method is invoked to check + * write access if the file is opened for writing + * + * @since 1.7 + */ + public static FileChannel open(Path file, OpenOption... options) + throws IOException + { + Set set = new HashSet(options.length); + Collections.addAll(set, options); + return open(file, set, NO_ATTRIBUTES); + } // -- Channel operations -- @@ -286,7 +462,7 @@ public abstract class FileChannel public abstract FileChannel position(long newPosition) throws IOException; /** - * Returns the current size of this channel's file.

+ * Returns the current size of this channel's file.

* * @return The current size of this channel's file, * measured in bytes @@ -359,7 +535,7 @@ public abstract class FileChannel *

This method is only guaranteed to force changes that were made to * this channel's file via the methods defined in this class. It may or * may not force changes that were made by modifying the content of a - * {@link MappedByteBuffer mapped byte buffer} obtained by + * {@link MappedByteBuffer mapped byte buffer} obtained by * invoking the {@link #map map} method. Invoking the {@link * MappedByteBuffer#force force} method of the mapped byte buffer will * force changes made to the buffer's content to be written.

@@ -678,7 +854,7 @@ public abstract class FileChannel * reading; for a read/write or private mapping, this channel must have * been opened for both reading and writing. * - *

The {@link MappedByteBuffer mapped byte buffer} + *

The {@link MappedByteBuffer mapped byte buffer} * returned by this method will have a position of zero and a limit and * capacity of size; its mark will be undefined. The buffer and * the mapping that it represents will remain valid until the buffer itself @@ -717,6 +893,8 @@ public abstract class FileChannel * The size of the region to be mapped; must be non-negative and * no greater than {@link java.lang.Integer#MAX_VALUE} * + * @return The mapped byte buffer + * * @throws NonReadableChannelException * If the mode is {@link MapMode#READ_ONLY READ_ONLY} but * this channel was not opened for reading diff --git a/jdk/src/share/classes/java/nio/channels/FileLock.java b/jdk/src/share/classes/java/nio/channels/FileLock.java index 921922242d7..b0ec37f1ba5 100644 --- a/jdk/src/share/classes/java/nio/channels/FileLock.java +++ b/jdk/src/share/classes/java/nio/channels/FileLock.java @@ -1,5 +1,5 @@ /* - * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,16 @@ package java.nio.channels; import java.io.IOException; - /** * A token representing a lock on a region of a file. * *

A file-lock object is created each time a lock is acquired on a file via * one of the {@link FileChannel#lock(long,long,boolean) lock} or {@link - * FileChannel#tryLock(long,long,boolean) tryLock} methods of the {@link - * FileChannel} class. + * FileChannel#tryLock(long,long,boolean) tryLock} methods of the + * {@link FileChannel} class, or the {@link + * AsynchronousFileChannel#lock(long,long,boolean,Object,CompletionHandler) lock} + * or {@link AsynchronousFileChannel#tryLock(long,long,boolean) tryLock} + * methods of the {@link AsynchronousFileChannel} class. * *

A file-lock object is initially valid. It remains valid until the lock * is released by invoking the {@link #release release} method, by closing the @@ -70,8 +72,7 @@ import java.io.IOException; *

File-lock objects are safe for use by multiple concurrent threads. * * - * - *

Platform dependencies

+ *

Platform dependencies

* *

This file-locking API is intended to map directly to the native locking * facility of the underlying operating system. Thus the locks held on a file @@ -93,7 +94,7 @@ import java.io.IOException; * *

On some systems, acquiring a mandatory lock on a region of a file * prevents that region from being {@link java.nio.channels.FileChannel#map - * mapped into memory}, and vice versa. Programs that combine + * mapped into memory}, and vice versa. Programs that combine * locking and mapping should be prepared for this combination to fail. * *

On some systems, closing a channel releases all locks held by the Java @@ -113,11 +114,12 @@ import java.io.IOException; * @author Mark Reinhold * @author JSR-51 Expert Group * @since 1.4 + * @updated 1.7 */ public abstract class FileLock { - private final FileChannel channel; + private final Channel channel; private final long position; private final long size; private final boolean shared; @@ -159,11 +161,66 @@ public abstract class FileLock { } /** - * Returns the file channel upon whose file this lock is held.

+ * {@note new} Initializes a new instance of this class. * - * @return The file channel + * @param channel + * The channel upon whose file this lock is held + * + * @param position + * The position within the file at which the locked region starts; + * must be non-negative + * + * @param size + * The size of the locked region; must be non-negative, and the sum + * position + size must be non-negative + * + * @param shared + * true if this lock is shared, + * false if it is exclusive + * + * @throws IllegalArgumentException + * If the preconditions on the parameters do not hold + * + * @since 1.7 + */ + protected FileLock(AsynchronousFileChannel channel, + long position, long size, boolean shared) + { + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (size < 0) + throw new IllegalArgumentException("Negative size"); + if (position + size < 0) + throw new IllegalArgumentException("Negative position + size"); + this.channel = channel; + this.position = position; + this.size = size; + this.shared = shared; + } + + /** + * {@note revised} + * Returns the file channel upon whose file this lock was acquired. + * + *

This method has been superseded by the {@link #acquiredBy acquiredBy} + * method. + * + * @return The file channel, or {@code null} if the file lock was not + * acquired by a file channel. */ public final FileChannel channel() { + return (channel instanceof FileChannel) ? (FileChannel)channel : null; + } + + /** + * {@note new} + * Returns the channel upon whose file this lock was acquired. + * + * @return The channel upon whose file this lock was acquired. + * + * @since 1.7 + */ + public Channel acquiredBy() { return channel; } diff --git a/jdk/src/share/classes/java/nio/channels/MembershipKey.java b/jdk/src/share/classes/java/nio/channels/MembershipKey.java index 0d2fc52bc4d..804e6724ad0 100644 --- a/jdk/src/share/classes/java/nio/channels/MembershipKey.java +++ b/jdk/src/share/classes/java/nio/channels/MembershipKey.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ package java.nio.channels; import java.net.InetAddress; import java.net.NetworkInterface; import java.io.IOException; -import java.util.List; /** * A token representing the membership of an Internet Protocol (IP) multicast @@ -38,7 +37,7 @@ import java.util.List; * to the group, or it may be source-specific, meaning that it * represents a membership that receives only datagrams from a specific source * address. Whether or not a membership key is source-specific may be determined - * by invoking its {@link #getSourceAddress() getSourceAddress} method. + * by invoking its {@link #sourceAddress() sourceAddress} method. * *

A membership key is valid upon creation and remains valid until the * membership is dropped by invoking the {@link #drop() drop} method, or @@ -93,11 +92,8 @@ public abstract class MembershipKey { * If the multicast group membership is already invalid then invoking this * method has no effect. Once a multicast group membership is invalid, * it remains invalid forever. - * - * @throws IOException - * If an I/O error occurs */ - public abstract void drop() throws IOException; + public abstract void drop(); /** * Block multicast datagrams from the given source address. @@ -140,10 +136,8 @@ public abstract class MembershipKey { * @throws IllegalStateException * If the given source address is not currently blocked or the * membership key is no longer valid - * @throws IOException - * If an I/O error occurs */ - public abstract MembershipKey unblock(InetAddress source) throws IOException; + public abstract MembershipKey unblock(InetAddress source); /** * Returns the channel for which this membership key was created. This @@ -152,7 +146,7 @@ public abstract class MembershipKey { * * @return the channel */ - public abstract MulticastChannel getChannel(); + public abstract MulticastChannel channel(); /** * Returns the multicast group for which this membership key was created. @@ -161,7 +155,7 @@ public abstract class MembershipKey { * * @return the multicast group */ - public abstract InetAddress getGroup(); + public abstract InetAddress group(); /** * Returns the network interface for which this membership key was created. @@ -170,7 +164,7 @@ public abstract class MembershipKey { * * @return the network interface */ - public abstract NetworkInterface getNetworkInterface(); + public abstract NetworkInterface networkInterface(); /** * Returns the source address if this membership key is source-specific, @@ -179,5 +173,5 @@ public abstract class MembershipKey { * @return The source address if this membership key is source-specific, * otherwise {@code null} */ - public abstract InetAddress getSourceAddress(); + public abstract InetAddress sourceAddress(); } diff --git a/jdk/src/share/classes/java/nio/channels/MulticastChannel.java b/jdk/src/share/classes/java/nio/channels/MulticastChannel.java index 440dd2a8b85..1cacf98e69c 100644 --- a/jdk/src/share/classes/java/nio/channels/MulticastChannel.java +++ b/jdk/src/share/classes/java/nio/channels/MulticastChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,22 @@ import java.net.StandardSocketOption; // javadoc public interface MulticastChannel extends NetworkChannel { + /** + * Closes this channel. + * + *

If the channel is a member of a multicast group then the membership + * is {@link MembershipKey#drop dropped}. Upon return, the {@link + * MembershipKey membership-key} will be {@link MembershipKey#isValid + * invalid}. + * + *

This method otherwise behaves exactly as specified by the {@link + * Channel} interface. + * + * @throws IOException + * If an I/O error occurs + */ + @Override void close() throws IOException; + /** * Joins a multicast group to begin receiving all datagrams sent to the group, * returning a membership key. @@ -130,7 +146,7 @@ public interface MulticastChannel * interface to receive all datagrams then the membership key, representing * that membership, is returned. Otherwise this channel joins the group and * the resulting new membership key is returned. The resulting membership key - * is not {@link MembershipKey#getSourceAddress source-specific}. + * is not {@link MembershipKey#sourceAddress source-specific}. * *

A multicast channel may join several multicast groups, including * the same group on more than one interface. An implementation may impose a @@ -150,6 +166,8 @@ public interface MulticastChannel * @throws IllegalStateException * If the channel already has source-specific membership of the * group on the interface + * @throws UnsupportedOperationException + * If the channel's socket is not an Internet Protocol socket * @throws ClosedChannelException * If this channel is closed * @throws IOException @@ -170,7 +188,7 @@ public interface MulticastChannel * interface to receive datagrams from the given source address then the * membership key, representing that membership, is returned. Otherwise this * channel joins the group and the resulting new membership key is returned. - * The resulting membership key is {@link MembershipKey#getSourceAddress + * The resulting membership key is {@link MembershipKey#sourceAddress * source-specific}. * *

Membership is cumulative and this method may be invoked @@ -196,7 +214,8 @@ public interface MulticastChannel * If the channel is currently a member of the group on the given * interface to receive all datagrams * @throws UnsupportedOperationException - * If the underlying operation system does not support source filtering + * If the channel's socket is not an Internet Protocol socket or + * source filtering is not supported * @throws ClosedChannelException * If this channel is closed * @throws IOException diff --git a/jdk/src/share/classes/java/nio/channels/NetworkChannel.java b/jdk/src/share/classes/java/nio/channels/NetworkChannel.java index fae642fcbdb..103427759e7 100644 --- a/jdk/src/share/classes/java/nio/channels/NetworkChannel.java +++ b/jdk/src/share/classes/java/nio/channels/NetworkChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,9 +95,10 @@ public interface NetworkChannel * java.net.InetSocketAddress}. * * @return The socket address that the socket is bound to, or {@code null} - * if the channel is not {@link #isOpen open} or the channel's socket - * is not bound + * if the channel's socket is not bound * + * @throws ClosedChannelException + * If the channel is closed * @throws IOException * If an I/O error occurs */ @@ -114,9 +115,10 @@ public interface NetworkChannel * * @return This channel * + * @throws UnsupportedOperationException + * If the socket option is not supported by this channel * @throws IllegalArgumentException - * If the socket option is not supported by this channel, or - * the value is not a valid value for this socket option + * If the value is not a valid value for this socket option * @throws ClosedChannelException * If this channel is closed * @throws IOException @@ -135,7 +137,7 @@ public interface NetworkChannel * @return The value of the socket option. A value of {@code null} may be * a valid value for some socket options. * - * @throws IllegalArgumentException + * @throws UnsupportedOperationException * If the socket option is not supported by this channel * @throws ClosedChannelException * If this channel is closed @@ -154,5 +156,5 @@ public interface NetworkChannel * * @return A set of the socket options supported by this channel */ - Set> options(); + Set> supportedOptions(); } diff --git a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java new file mode 100644 index 00000000000..33efc248861 --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java @@ -0,0 +1,168 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels; + +import java.nio.ByteBuffer; +import java.io.IOException; + +/** + * A byte channel that maintains a current position and allows the + * position to be changed. + * + *

A seekable byte channel is connected to an entity, typically a file, + * that contains a variable-length sequence of bytes that can be read and + * written. The current position can be {@link #position() queried} and + * {@link #position(long) modified}. The channel also provides access to + * the current size of the entity to which the channel is connected. The + * size increases when bytes are written beyond its current size; the size + * decreases when it is {@link #truncate truncated}. + * + *

The {@link #position(long) position} and {@link #truncate truncate} methods + * which do not otherwise have a value to return are specified to return the + * channel upon which they are invoked. This allows method invocations to be + * chained. Implementations of this interface should specialize the return type + * so that method invocations on the implementation class can be chained. + * + * @since 1.7 + * @see java.nio.file.FileRef#newByteChannel + */ + +public interface SeekableByteChannel + extends ByteChannel +{ + /** + * Reads a sequence of bytes from this channel into the given buffer. + * + *

Bytes are read starting at this channel's current position, and + * then the position is updated with the number of bytes actually read. + * Otherwise this method behaves exactly as specified in the {@link + * ReadableByteChannel} interface. + */ + @Override + int read(ByteBuffer dst) throws IOException; + + /** + * Writes a sequence of bytes to this channel from the given buffer. + * + *

Bytes are written starting at this channel's current position, unless + * the channel is connected to an entity such as a file that is opened with + * the {@link java.nio.file.StandardOpenOption#APPEND APPEND} option, in + * which case the position is first advanced to the end. The entity to which + * the channel is connected is grown, if necessary, to accommodate the + * written bytes, and then the position is updated with the number of bytes + * actually written. Otherwise this method behaves exactly as specified by + * the {@link WritableByteChannel} interface. + */ + @Override + int write(ByteBuffer src) throws IOException; + + /** + * Returns this channel's position. + * + * @return This channel's position, + * a non-negative integer counting the number of bytes + * from the beginning of the entity to the current position + * + * @throws ClosedChannelException + * If this channel is closed + * @throws IOException + * If some other I/O error occurs + */ + long position() throws IOException; + + /** + * Sets this channel's position. + * + *

Setting the position to a value that is greater than the current size + * is legal but does not change the size of the entity. A later attempt to + * read bytes at such a position will immediately return an end-of-file + * indication. A later attempt to write bytes at such a position will cause + * the entity to grow to accommodate the new bytes; the values of any bytes + * between the previous end-of-file and the newly-written bytes are + * unspecified. + * + *

Setting the channel's position is not recommended when connected to + * an entity, typically a file, that is opened with the {@link + * java.nio.file.StandardOpenOption#APPEND APPEND} option. When opened for + * append, the position is first advanced to the end before writing. + * + * @param newPosition + * The new position, a non-negative integer counting + * the number of bytes from the beginning of the entity + * + * @return This channel + * + * @throws ClosedChannelException + * If this channel is closed + * @throws IllegalArgumentException + * If the new position is negative + * @throws IOException + * If some other I/O error occurs + */ + SeekableByteChannel position(long newPosition) throws IOException; + + /** + * Returns the current size of entity to which this channel is connected. + * + * @return The current size, measured in bytes + * + * @throws ClosedChannelException + * If this channel is closed + * @throws IOException + * If some other I/O error occurs + */ + long size() throws IOException; + + /** + * Truncates the entity, to which this channel is connected, to the given + * size. + * + *

If the given size is less than the current size then the entity is + * truncated, discarding any bytes beyond the new end. If the given size is + * greater than or equal to the current size then the entity is not modified. + * In either case, if the current position is greater than the given size + * then it is set to that size. + * + *

An implementation of this interface may prohibit truncation when + * connected to an entity, typically a file, opened with the {@link + * java.nio.file.StandardOpenOption#APPEND APPEND} option. + * + * @param size + * The new size, a non-negative byte count + * + * @return This channel + * + * @throws NonWritableChannelException + * If this channel was not opened for writing + * @throws ClosedChannelException + * If this channel is closed + * @throws IllegalArgumentException + * If the new size is negative + * @throws IOException + * If some other I/O error occurs + */ + SeekableByteChannel truncate(long size) throws IOException; +} diff --git a/jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java b/jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java index 84ea062c9f0..5be9bc7cb15 100644 --- a/jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java +++ b/jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,8 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.SocketOption; import java.net.SocketAddress; -import java.nio.channels.spi.*; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; /** * A selectable channel for stream-oriented listening sockets. @@ -195,6 +196,7 @@ public abstract class ServerSocketChannel throws IOException; /** + * @throws UnsupportedOperationException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws ClosedChannelException {@inheritDoc} * @throws IOException {@inheritDoc} diff --git a/jdk/src/share/classes/java/nio/channels/SocketChannel.java b/jdk/src/share/classes/java/nio/channels/SocketChannel.java index 2e96bd2e4ce..975048df0c0 100644 --- a/jdk/src/share/classes/java/nio/channels/SocketChannel.java +++ b/jdk/src/share/classes/java/nio/channels/SocketChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,8 @@ import java.net.Socket; import java.net.SocketOption; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.nio.channels.spi.*; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; /** * A selectable channel for stream-oriented connecting sockets. @@ -212,7 +213,7 @@ public abstract class SocketChannel /** * @throws ConnectionPendingException - * If a non-blocking connection operation is already in progress on + * If a non-blocking connect operation is already in progress on * this channel * @throws AlreadyBoundException {@inheritDoc} * @throws UnsupportedAddressTypeException {@inheritDoc} @@ -226,6 +227,7 @@ public abstract class SocketChannel throws IOException; /** + * @throws UnsupportedOperationException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} * @throws ClosedChannelException {@inheritDoc} * @throws IOException {@inheritDoc} @@ -432,15 +434,17 @@ public abstract class SocketChannel * socket address then the return value from this method is of type {@link * java.net.InetSocketAddress}. * - * @return The remote address; {@code null} if the channel is not {@link - * #isOpen open} or the channel's socket is not connected + * @return The remote address; {@code null} if the channel's socket is not + * connected * + * @throws ClosedChannelException + * If the channel is closed * @throws IOException * If an I/O error occurs * * @since 1.7 */ - public abstract SocketAddress getConnectedAddress() throws IOException; + public abstract SocketAddress getRemoteAddress() throws IOException; // -- ByteChannel operations -- diff --git a/jdk/src/share/classes/java/nio/channels/exceptions b/jdk/src/share/classes/java/nio/channels/exceptions index 04cfbe03e29..fed9f72ab2e 100644 --- a/jdk/src/share/classes/java/nio/channels/exceptions +++ b/jdk/src/share/classes/java/nio/channels/exceptions @@ -1,5 +1,5 @@ # -# Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -150,6 +150,21 @@ gen OverlappingFileLockException " SINCE=1.7 +SUPER=java.io.IOException + +gen InterruptedByTimeoutException " + * Checked exception received by a thread when a timeout elapses before an + * asynchronous operation completes." \ + -4268008601014042947L + +SUPER=IllegalArgumentException + +gen IllegalChannelGroupException " + * Unchecked exception thrown when an attempt is made to open a channel + * in a group that was not created by the same provider. " \ + -2495041211157744253L + + SUPER=IllegalStateException gen AlreadyBoundException " @@ -157,3 +172,23 @@ gen AlreadyBoundException " * network oriented channel that is already bound." \ 6796072983322737592L +gen AcceptPendingException " + * Unchecked exception thrown when an attempt is made to initiate an accept + * operation on a channel and a previous accept operation has not completed." \ + 2721339977965416421L + +gen ReadPendingException " + * Unchecked exception thrown when an attempt is made to read from an + * asynchronous socket channel and a previous read has not completed." \ + 1986315242191227217L + +gen WritePendingException " + * Unchecked exception thrown when an attempt is made to write to an + * asynchronous socket channel and a previous write has not completed." \ + 7031871839266032276L + +gen ShutdownChannelGroupException " + * Unchecked exception thrown when an attempt is made to construct a channel in + * a group that is shutdown or the completion handler for an I/O operation + * cannot be invoked because the channel group is shutdown." \ + -3903801676350154157L diff --git a/jdk/src/share/classes/java/nio/channels/package-info.java b/jdk/src/share/classes/java/nio/channels/package-info.java index e8c2a929d4b..47a1cb5f979 100644 --- a/jdk/src/share/classes/java/nio/channels/package-info.java +++ b/jdk/src/share/classes/java/nio/channels/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,10 @@ * Can read/write to/from a buffer *     {@link java.nio.channels.SeekableByteChannel} * A {@code ByteChannel} connected to an entity that contains a variable-length sequence of bytes + *   {@link java.nio.channels.AsynchronousChannel} + * Supports asynchronous I/O operations. + *     {@link java.nio.channels.AsynchronousByteChannel} + * Can read and write bytes asynchronously *   {@link java.nio.channels.NetworkChannel} * A channel to a network socket *     {@link java.nio.channels.MulticastChannel} @@ -218,12 +222,70 @@ * directly; custom channel classes should extend the appropriate {@link * java.nio.channels.SelectableChannel} subclasses defined in this package. * + * + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + *

Asynchronous I/O

Description

{@link java.nio.channels.AsynchronousFileChannel}An asynchronous channel for reading, writing, and manipulating a file
{@link java.nio.channels.AsynchronousSocketChannel}An asynchronous channel to a stream-oriented connecting socket
{@link java.nio.channels.AsynchronousServerSocketChannel}  An asynchronous channel to a stream-oriented listening socket
{@link java.nio.channels.AsynchronousDatagramChannel}An asynchronous channel to a datagram-oriented socket
{@link java.nio.channels.CompletionHandler}A handler for consuming the result of an asynchronous operation
{@link java.nio.channels.AsynchronousChannelGroup}A grouping of asynchronous channels for the purpose of resource sharing
+ * + *

{@link java.nio.channels.AsynchronousChannel Asynchronous channels} are a + * special type of channel capable of asynchronous I/O operations. Asynchronous + * channels are non-blocking and define methods to initiate asynchronous + * operations, returning a {@link java.util.concurrent.Future} representing the + * pending result of each operation. The {@code Future} can be used to poll or + * wait for the result of the operation. Asynchronous I/O operations can also + * specify a {@link java.nio.channels.CompletionHandler} to invoke when the + * operation completes. A completion handler is user provided code that is executed + * to consume the result of I/O operation. + * + *

This package defines asynchronous-channel classes that are connected to + * a stream-oriented connecting or listening socket, or a datagram-oriented socket. + * It also defines the {@link java.nio.channels.AsynchronousFileChannel} class + * for asynchronous reading, writing, and manipulating a file. As with the {@link + * java.nio.channels.FileChannel} it supports operations to truncate the file + * to a specific size, force updates to the file to be written to the storage + * device, or acquire locks on the whole file or on a specific region of the file. + * Unlike the {@code FileChannel} it does not define methods for mapping a + * region of the file directly into memory. Where memory mapped I/O is required, + * then a {@code FileChannel} can be used. + * + *

Asynchronous channels are bound to an asynchronous channel group for the + * purpose of resource sharing. A group has an associated {@link + * java.util.concurrent.ExecutorService} to which tasks are submitted to handle + * I/O events and dispatch to completion handlers that consume the result of + * asynchronous operations performed on channels in the group. The group can + * optionally be specified when creating the channel or the channel can be bound + * to a default group. Sophisticated users may wish to create their + * own asynchronous channel groups or configure the {@code ExecutorService} + * that will be used for the default group. + * + *

As with selectors, the implementatin of asynchronous channels can be + * replaced by "plugging in" an alternative definition or instance of the {@link + * java.nio.channels.spi.AsynchronousChannelProvider} class defined in the + * {@link java.nio.channels.spi} package. It is not expected that many + * developers will actually make use of this facility; it is provided primarily + * so that sophisticated users can take advantage of operating-system-specific + * asynchronous I/O mechanisms when very high performance is required. + * *


*

Unless otherwise noted, passing a null argument to a constructor * or method in any class or interface in this package will cause a {@link * java.lang.NullPointerException NullPointerException} to be thrown. * * @since 1.4 + * @updated 1.7 * @author Mark Reinhold * @author JSR-51 Expert Group */ diff --git a/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java b/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java new file mode 100644 index 00000000000..941364876ed --- /dev/null +++ b/jdk/src/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java @@ -0,0 +1,264 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.nio.channels.spi; + +import java.nio.channels.*; +import java.net.ProtocolFamily; +import java.io.IOException; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.ServiceConfigurationError; +import java.util.concurrent.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Service-provider class for asynchronous channels. + * + *

An asynchronous channel provider is a concrete subclass of this class that + * has a zero-argument constructor and implements the abstract methods specified + * below. A given invocation of the Java virtual machine maintains a single + * system-wide default provider instance, which is returned by the {@link + * #provider() provider} method. The first invocation of that method will locate + * the default provider as specified below. + * + *

All of the methods in this class are safe for use by multiple concurrent + * threads.

+ * + * @since 1.7 + */ + +public abstract class AsynchronousChannelProvider { + private static Void checkPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("asynchronousChannelProvider")); + return null; + } + private AsynchronousChannelProvider(Void ignore) { } + + /** + * Initializes a new instance of this class. + * + * @throws SecurityException + * If a security manager has been installed and it denies + * {@link RuntimePermission}("asynchronousChannelProvider") + */ + protected AsynchronousChannelProvider() { + this(checkPermission()); + } + + // lazy initialization of default provider + private static class ProviderHolder { + static final AsynchronousChannelProvider provider = load(); + + private static AsynchronousChannelProvider load() { + return AccessController + .doPrivileged(new PrivilegedAction() { + public AsynchronousChannelProvider run() { + AsynchronousChannelProvider p; + p = loadProviderFromProperty(); + if (p != null) + return p; + p = loadProviderAsService(); + if (p != null) + return p; + return sun.nio.ch.DefaultAsynchronousChannelProvider.create(); + }}); + } + + private static AsynchronousChannelProvider loadProviderFromProperty() { + String cn = System.getProperty("java.nio.channels.spi.AsynchronousChannelProvider"); + if (cn == null) + return null; + try { + Class c = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()); + return (AsynchronousChannelProvider)c.newInstance(); + } catch (ClassNotFoundException x) { + throw new ServiceConfigurationError(null, x); + } catch (IllegalAccessException x) { + throw new ServiceConfigurationError(null, x); + } catch (InstantiationException x) { + throw new ServiceConfigurationError(null, x); + } catch (SecurityException x) { + throw new ServiceConfigurationError(null, x); + } + } + + private static AsynchronousChannelProvider loadProviderAsService() { + ServiceLoader sl = + ServiceLoader.load(AsynchronousChannelProvider.class, + ClassLoader.getSystemClassLoader()); + Iterator i = sl.iterator(); + for (;;) { + try { + return (i.hasNext()) ? i.next() : null; + } catch (ServiceConfigurationError sce) { + if (sce.getCause() instanceof SecurityException) { + // Ignore the security exception, try the next provider + continue; + } + throw sce; + } + } + } + } + + /** + * Returns the system-wide default asynchronous channel provider for this + * invocation of the Java virtual machine. + * + *

The first invocation of this method locates the default provider + * object as follows:

+ * + *
    + * + *
  1. If the system property + * java.nio.channels.spi.AsynchronousChannelProvider is defined + * then it is taken to be the fully-qualified name of a concrete provider class. + * The class is loaded and instantiated; if this process fails then an + * unspecified error is thrown.

  2. + * + *
  3. If a provider class has been installed in a jar file that is + * visible to the system class loader, and that jar file contains a + * provider-configuration file named + * java.nio.channels.spi.AsynchronousChannelProvider in the resource + * directory META-INF/services, then the first class name + * specified in that file is taken. The class is loaded and + * instantiated; if this process fails then an unspecified error is + * thrown.

  4. + * + *
  5. Finally, if no provider has been specified by any of the above + * means then the system-default provider class is instantiated and the + * result is returned.

  6. + * + *
+ * + *

Subsequent invocations of this method return the provider that was + * returned by the first invocation.

+ * + * @return The system-wide default AsynchronousChannel provider + */ + public static AsynchronousChannelProvider provider() { + return ProviderHolder.provider; + } + + /** + * Constructs a new asynchronous channel group with a fixed thread pool. + * + * @param nThreads + * The number of threads in the pool + * @param threadFactory + * The factory to use when creating new threads + * + * @throws IllegalArgumentException + * If {@code nThreads <= 0} + * @throws IOException + * If an I/O error occurs + * + * @see AsynchronousChannelGroup#withFixedThreadPool + */ + public abstract AsynchronousChannelGroup + openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) throws IOException; + + /** + * Constructs a new asynchronous channel group with the given thread pool. + * + * @param executor + * The thread pool + * @param initialSize + * A value {@code >=0} or a negative value for implementation + * specific default + * + * @throws IOException + * If an I/O error occurs + * + * @see AsynchronousChannelGroup#withCachedThreadPool + */ + public abstract AsynchronousChannelGroup + openAsynchronousChannelGroup(ExecutorService executor, int initialSize) throws IOException; + + /** + * Opens an asynchronous server-socket channel. + * + * @param group + * The group to which the channel is bound, or {@code null} to + * bind to the default group + * + * @return The new channel + * + * @throws IllegalChannelGroupException + * If the provider that created the group differs from this provider + * @throws ShutdownChannelGroupException + * The group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public abstract AsynchronousServerSocketChannel openAsynchronousServerSocketChannel + (AsynchronousChannelGroup group) throws IOException; + + /** + * Opens an asynchronous socket channel. + * + * @param group + * The group to which the channel is bound, or {@code null} to + * bind to the default group + * + * @return The new channel + * + * @throws IllegalChannelGroupException + * If the provider that created the group differs from this provider + * @throws ShutdownChannelGroupException + * The group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public abstract AsynchronousSocketChannel openAsynchronousSocketChannel + (AsynchronousChannelGroup group) throws IOException; + + /** + * Opens an asynchronous datagram channel. + * + * @param family + * The protocol family, or {@code null} for the default protocol + * family + * @param group + * The group to which the channel is bound, or {@code null} to + * bind to the default group + * + * @return The new channel + * + * @throws IllegalChannelGroupException + * If the provider that created the group differs from this provider + * @throws ShutdownChannelGroupException + * The group is shutdown + * @throws IOException + * If an I/O error occurs + */ + public abstract AsynchronousDatagramChannel openAsynchronousDatagramChannel + (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException; +} diff --git a/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java b/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java index dc61c9c270a..d03800e22f3 100644 --- a/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java +++ b/jdk/src/share/classes/java/nio/channels/spi/SelectorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,8 @@ public abstract class SelectorProvider { if (cn == null) return false; try { - Class c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); + Class c = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()); provider = (SelectorProvider)c.newInstance(); return true; } catch (ClassNotFoundException x) { diff --git a/jdk/src/share/classes/java/nio/channels/spi/package.html b/jdk/src/share/classes/java/nio/channels/spi/package.html index 5b3ddd299f9..5960da38e82 100644 --- a/jdk/src/share/classes/java/nio/channels/spi/package.html +++ b/jdk/src/share/classes/java/nio/channels/spi/package.html @@ -1,5 +1,5 @@ * *   - * Special constructs (non-capturing) + * Special constructs (named-capturing and non-capturing) * + * (?<name>X) + * X, as a named-capturing group * (?:X) * X, as a non-capturing group * (?idmsux-idmsux)  @@ -449,6 +456,8 @@ import java.util.Arrays; * *

Groups and capturing

* + *
+ *
Group number
*

Capturing groups are numbered by counting their opening parentheses from * left to right. In the expression ((A)(B(C))), for example, there * are four such groups:

@@ -471,6 +480,24 @@ import java.util.Arrays; * subsequence may be used later in the expression, via a back reference, and * may also be retrieved from the matcher once the match operation is complete. * + *
+ *
Group name
+ *

A capturing group can also be assigned a "name", a named-capturing group, + * and then be back-referenced later by the "name". Group names are composed of + * the following characters: + * + *

    + *
  • The uppercase letters 'A' through 'Z' + * ('\u0041' through '\u005a'), + *
  • The lowercase letters 'a' through 'z' + * ('\u0061' through '\u007a'), + *
  • The digits '0' through '9' + * ('\u0030' through '\u0039'), + *
+ * + *

A named-capturing group is still numbered as described in + * Group number. + * *

The captured input associated with a group is always the subsequence * that the group most recently matched. If a group is evaluated a second time * because of quantification then its previously-captured value, if any, will @@ -479,9 +506,9 @@ import java.util.Arrays; * group two set to "b". All captured input is discarded at the * beginning of each match. * - *

Groups beginning with (? are pure, non-capturing groups - * that do not capture text and do not count towards the group total. - * + *

Groups beginning with (? are either pure, non-capturing groups + * that do not capture text and do not count towards the group total, or + * named-capturing group. * *

Unicode support

* @@ -794,6 +821,12 @@ public final class Pattern */ transient int[] buffer; + /** + * Map the "name" of the "named capturing group" to its group id + * node. + */ + transient volatile Map namedGroups; + /** * Temporary storage used while parsing group references. */ @@ -1467,6 +1500,7 @@ loop: for(int x=0, offset=0; x namedGroups() { + if (namedGroups == null) + namedGroups = new HashMap(2); + return namedGroups; + } + /** * Used to print out a subtree of the Pattern to help with debugging. */ @@ -2156,7 +2196,22 @@ loop: for(int x=0, offset=0; x does not exit"); + if (create) { + if (has(CASE_INSENSITIVE)) + root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE)); + else + root = new BackRef(namedGroups().get(name)); + } + return -1; case 'l': case 'm': break; @@ -2455,6 +2510,24 @@ loop: for(int x=0, offset=0; x" is consumed after parsing. + */ + private String groupname(int ch) { + StringBuilder sb = new StringBuilder(); + sb.append(Character.toChars(ch)); + while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) || + ASCII.isDigit(ch)) { + sb.append(Character.toChars(ch)); + } + if (sb.length() == 0) + throw error("named capturing group has 0 length name"); + if (ch != '>') + throw error("named capturing group is missing trailing '>'"); + return sb.toString(); + } + /** * Parses a group and returns the head node of a set of nodes that process * the group. Sometimes a double return system is used where the tail is @@ -2494,6 +2567,18 @@ loop: for(int x=0, offset=0; x is already defined"); + capturingGroup = true; + head = createGroup(false); + tail = root; + namedGroups().put(name, capturingGroupCount-1); + head.next = expr(tail); + break; + } int start = cursor; head = createGroup(true); tail = root; diff --git a/jdk/src/share/classes/javax/swing/ImageIcon.java b/jdk/src/share/classes/javax/swing/ImageIcon.java index 74788f1a803..7f1fd02e003 100644 --- a/jdk/src/share/classes/javax/swing/ImageIcon.java +++ b/jdk/src/share/classes/javax/swing/ImageIcon.java @@ -86,7 +86,7 @@ public class ImageIcon implements Icon, Serializable, Accessible { static { component = new Component() {}; - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { // 6482575 - clear the appContext field so as not to leak it diff --git a/jdk/src/share/classes/javax/swing/JRootPane.java b/jdk/src/share/classes/javax/swing/JRootPane.java index c9696246e06..a210c3791c4 100644 --- a/jdk/src/share/classes/javax/swing/JRootPane.java +++ b/jdk/src/share/classes/javax/swing/JRootPane.java @@ -34,6 +34,7 @@ import javax.swing.plaf.RootPaneUI; import java.util.Vector; import java.io.Serializable; import javax.swing.border.*; +import sun.awt.AWTAccessor; import sun.security.action.GetBooleanAction; @@ -688,6 +689,9 @@ public class JRootPane extends JComponent implements Accessible { throw new NullPointerException("glassPane cannot be set to null."); } + AWTAccessor.getComponentAccessor().setMixingCutoutShape(glass, + new Rectangle()); + boolean visible = false; if (glassPane != null && glassPane.getParent() == this) { this.remove(glassPane); diff --git a/jdk/src/share/classes/javax/swing/ProgressMonitor.java b/jdk/src/share/classes/javax/swing/ProgressMonitor.java index 36366df170c..73a2b656b0d 100644 --- a/jdk/src/share/classes/javax/swing/ProgressMonitor.java +++ b/jdk/src/share/classes/javax/swing/ProgressMonitor.java @@ -78,7 +78,7 @@ import javax.swing.text.*; * @author James Gosling * @author Lynn Monsanto (accessibility) */ -public class ProgressMonitor extends Object implements Accessible +public class ProgressMonitor implements Accessible { private ProgressMonitor root; private JDialog dialog; @@ -186,7 +186,7 @@ public class ProgressMonitor extends Object implements Accessible } if (window instanceof SwingUtilities.SharedOwnerFrame) { WindowListener ownerShutdownListener = - (WindowListener)SwingUtilities.getSharedOwnerFrameShutdownListener(); + SwingUtilities.getSharedOwnerFrameShutdownListener(); dialog.addWindowListener(ownerShutdownListener); } Container contentPane = dialog.getContentPane(); @@ -273,7 +273,7 @@ public class ProgressMonitor extends Object implements Accessible if (dT >= millisToDecideToPopup) { int predictedCompletionTime; if (nv > min) { - predictedCompletionTime = (int)((long)dT * + predictedCompletionTime = (int)(dT * (max - min) / (nv - min)); } @@ -691,10 +691,7 @@ public class ProgressMonitor extends Object implements Accessible * object does not have an Accessible parent */ public Accessible getAccessibleParent() { - if (dialog != null) { - return (Accessible)dialog; - } - return null; + return dialog; } /* @@ -768,7 +765,7 @@ public class ProgressMonitor extends Object implements Accessible if (myBar != null) { Component c = myBar.getParent(); if (c instanceof Accessible) { - return ((Accessible)c).getAccessibleContext(); + return c.getAccessibleContext(); } } return null; diff --git a/jdk/src/share/classes/javax/swing/RepaintManager.java b/jdk/src/share/classes/javax/swing/RepaintManager.java index f051acdc675..f51bf4ec27a 100644 --- a/jdk/src/share/classes/javax/swing/RepaintManager.java +++ b/jdk/src/share/classes/javax/swing/RepaintManager.java @@ -1305,9 +1305,12 @@ public class RepaintManager if (doubleBufferingEnabled && !nativeDoubleBuffering) { switch (bufferStrategyType) { case BUFFER_STRATEGY_NOT_SPECIFIED: - if (((SunToolkit)Toolkit.getDefaultToolkit()). - useBufferPerWindow()) { - paintManager = new BufferStrategyPaintManager(); + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + SunToolkit stk = (SunToolkit) tk; + if (stk.useBufferPerWindow()) { + paintManager = new BufferStrategyPaintManager(); + } } break; case BUFFER_STRATEGY_SPECIFIED_ON: @@ -1329,9 +1332,16 @@ public class RepaintManager private void scheduleProcessingRunnable(AppContext context) { if (processingRunnable.markPending()) { - SunToolkit.getSystemEventQueueImplPP(context). - postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), - processingRunnable)); + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + SunToolkit.getSystemEventQueueImplPP(context). + postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), + processingRunnable)); + } else { + Toolkit.getDefaultToolkit().getSystemEventQueue(). + postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), + processingRunnable)); + } } } diff --git a/jdk/src/share/classes/javax/swing/SwingWorker.java b/jdk/src/share/classes/javax/swing/SwingWorker.java index de00ddc381d..9eca7d535f6 100644 --- a/jdk/src/share/classes/javax/swing/SwingWorker.java +++ b/jdk/src/share/classes/javax/swing/SwingWorker.java @@ -282,7 +282,7 @@ public abstract class SwingWorker implements RunnableFuture { * is finished. */ DONE - }; + } /** * Constructs this {@code SwingWorker}. @@ -825,7 +825,7 @@ public abstract class SwingWorker implements RunnableFuture { } private static class DoSubmitAccumulativeRunnable extends AccumulativeRunnable implements ActionListener { - private final static int DELAY = (int) (1000 / 30); + private final static int DELAY = 1000 / 30; @Override protected void run(List args) { for (Runnable runnable : args) { diff --git a/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java index c9ea9d77494..3980a40a6c1 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java @@ -26,6 +26,8 @@ package javax.swing.colorchooser; import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.*; /** @@ -47,6 +49,15 @@ import javax.swing.*; */ public abstract class AbstractColorChooserPanel extends JPanel { + private final PropertyChangeListener enabledListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + Object value = event.getNewValue(); + if (value instanceof Boolean) { + setEnabled((Boolean) value); + } + } + }; + /** * */ @@ -142,6 +153,8 @@ public abstract class AbstractColorChooserPanel extends JPanel { throw new RuntimeException ("This chooser panel is already installed"); } chooser = enclosingChooser; + chooser.addPropertyChangeListener("enabled", enabledListener); + setEnabled(chooser.isEnabled()); buildChooser(); updateChooser(); } @@ -151,6 +164,7 @@ public abstract class AbstractColorChooserPanel extends JPanel { * If override this, be sure to call super. */ public void uninstallChooserPanel(JColorChooser enclosingChooser) { + chooser.removePropertyChangeListener("enabled", enabledListener); chooser = null; } diff --git a/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java index acd6cdcc3fc..cc4fa5d53f2 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/ColorChooserPanel.java @@ -26,6 +26,8 @@ package javax.swing.colorchooser; import java.awt.Color; +import java.awt.Component; +import java.awt.Container; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.beans.PropertyChangeEvent; @@ -56,6 +58,21 @@ final class ColorChooserPanel extends AbstractColorChooserPanel implements Prope ValueFormatter.init(6, true, this.text); } + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setEnabled(this, enabled); + } + + private static void setEnabled(Container container, boolean enabled) { + for (Component component : container.getComponents()) { + component.setEnabled(enabled); + if (component instanceof Container) { + setEnabled((Container) component, enabled); + } + } + } + @Override public void updateChooser() { Color color = getColorFromModel(); diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DefaultColorSelectionModel.java b/jdk/src/share/classes/javax/swing/colorchooser/DefaultColorSelectionModel.java index e3cf261bd02..e437dd96dd3 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultColorSelectionModel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/DefaultColorSelectionModel.java @@ -128,8 +128,7 @@ public class DefaultColorSelectionModel implements ColorSelectionModel, Serializ * @since 1.4 */ public ChangeListener[] getChangeListeners() { - return (ChangeListener[])listenerList.getListeners( - ChangeListener.class); + return listenerList.getListeners(ChangeListener.class); } /** diff --git a/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java index 3cbd0df3b85..76896a90c64 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java @@ -170,7 +170,6 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { superHolder.add(mainHolder, gbc); gbc.insets = oldInsets; - recentSwatchPanel.addMouseListener(recentSwatchListener); recentSwatchPanel.setInheritsPopupMenu(true); JPanel recentHolder = new JPanel( new BorderLayout() ); recentHolder.setBorder(border); @@ -212,16 +211,20 @@ class DefaultSwatchChooserPanel extends AbstractColorChooserPanel { class RecentSwatchListener extends MouseAdapter implements Serializable { public void mousePressed(MouseEvent e) { - Color color = recentSwatchPanel.getColorForLocation(e.getX(), e.getY()); - setSelectedColor(color); + if (isEnabled()) { + Color color = recentSwatchPanel.getColorForLocation(e.getX(), e.getY()); + setSelectedColor(color); + } } } class MainSwatchListener extends MouseAdapter implements Serializable { public void mousePressed(MouseEvent e) { - Color color = swatchPanel.getColorForLocation(e.getX(), e.getY()); - setSelectedColor(color); - recentSwatchPanel.setMostRecentColor(color); + if (isEnabled()) { + Color color = swatchPanel.getColorForLocation(e.getX(), e.getY()); + setSelectedColor(color); + recentSwatchPanel.setMostRecentColor(color); + } } } diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java index 13d13cdcefe..44f99d6d3e3 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -1132,13 +1132,18 @@ public class BasicFileChooserUI extends FileChooserUI { private void changeDirectory(File dir) { JFileChooser fc = getFileChooser(); // Traverse shortcuts on Windows - if (dir != null && File.separatorChar == '\\' && dir.getPath().endsWith(".lnk")) { + if (dir != null && FilePane.usesShellFolder(fc)) { try { - File linkedTo = ShellFolder.getShellFolder(dir).getLinkLocation(); - if (linkedTo != null && fc.isTraversable(linkedTo)) { - dir = linkedTo; - } else { - return; + ShellFolder shellFolder = ShellFolder.getShellFolder(dir); + + if (shellFolder.isLink()) { + File linkedTo = shellFolder.getLinkLocation(); + + if (linkedTo != null && fc.isTraversable(linkedTo)) { + dir = linkedTo; + } else { + return; + } } } catch (FileNotFoundException ex) { return; diff --git a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index 1d16e1d8893..864ad13264a 100644 --- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -836,18 +836,24 @@ public class BasicSliderUI extends SliderUI{ */ protected Integer getHighestValue() { Dictionary dictionary = slider.getLabelTable(); - if (dictionary != null) { - Enumeration keys = dictionary.keys(); - int max = slider.getMinimum() - 1; - while (keys.hasMoreElements()) { - max = Math.max(max, ((Integer)keys.nextElement()).intValue()); - } - if (max == slider.getMinimum() - 1) { - return null; - } - return max; + + if (dictionary == null) { + return null; } - return null; + + Enumeration keys = dictionary.keys(); + + Integer max = null; + + while (keys.hasMoreElements()) { + Integer i = (Integer) keys.nextElement(); + + if (max == null || i > max) { + max = i; + } + } + + return max; } /** @@ -859,18 +865,24 @@ public class BasicSliderUI extends SliderUI{ */ protected Integer getLowestValue() { Dictionary dictionary = slider.getLabelTable(); - if (dictionary != null) { - Enumeration keys = dictionary.keys(); - int min = slider.getMaximum() + 1; - while (keys.hasMoreElements()) { - min = Math.min(min, ((Integer)keys.nextElement()).intValue()); - } - if (min == slider.getMaximum() + 1) { - return null; - } - return min; + + if (dictionary == null) { + return null; } - return null; + + Enumeration keys = dictionary.keys(); + + Integer min = null; + + while (keys.hasMoreElements()) { + Integer i = (Integer) keys.nextElement(); + + if (min == null || i < min) { + min = i; + } + } + + return min; } diff --git a/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java b/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java index 763dfdc3fc1..4636e07c4fd 100644 --- a/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -68,8 +68,6 @@ public class MetalFileChooserUI extends BasicFileChooserUI { private JToggleButton listViewButton; private JToggleButton detailsViewButton; - private boolean useShellFolder; - private JButton approveButton; private JButton cancelButton; @@ -204,10 +202,6 @@ public class MetalFileChooserUI extends BasicFileChooserUI { public ListSelectionListener createListSelectionListener() { return MetalFileChooserUI.this.createListSelectionListener(getFileChooser()); } - - public boolean usesShellFolder() { - return useShellFolder; - } } public void installComponents(JFileChooser fc) { @@ -219,8 +213,6 @@ public class MetalFileChooserUI extends BasicFileChooserUI { filePane = new FilePane(new MetalFileChooserUIAccessor()); fc.addPropertyChangeListener(filePane); - updateUseShellFolder(); - // ********************************* // // **** Construct the top panel **** // // ********************************* // @@ -448,19 +440,6 @@ public class MetalFileChooserUI extends BasicFileChooserUI { groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel }); } - private void updateUseShellFolder() { - // Decide whether to use the ShellFolder class to populate shortcut - // panel and combobox. - JFileChooser fc = getFileChooser(); - Boolean prop = - (Boolean)fc.getClientProperty("FileChooser.useShellFolder"); - if (prop != null) { - useShellFolder = prop.booleanValue(); - } else { - useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView()); - } - } - protected JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(); @@ -786,7 +765,6 @@ public class MetalFileChooserUI extends BasicFileChooserUI { cc.applyComponentOrientation(o); } } else if (s == "FileChooser.useShellFolder") { - updateUseShellFolder(); doDirectoryChanged(e); } else if (s.equals("ancestor")) { if (e.getOldValue() == null && e.getNewValue() != null) { @@ -953,6 +931,8 @@ public class MetalFileChooserUI extends BasicFileChooserUI { return; } + boolean useShellFolder = FilePane.usesShellFolder(chooser); + directories.clear(); File[] baseFolders; diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java index 0ff3307cdb5..7fe2278fd20 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthParser.java @@ -59,16 +59,16 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import org.xml.sax.AttributeList; -import org.xml.sax.HandlerBase; +import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; -import com.sun.beans.ObjectHandler; +import com.sun.beans.decoder.DocumentHandler; -class SynthParser extends HandlerBase { +class SynthParser extends DefaultHandler { // // Known element names // @@ -119,7 +119,7 @@ class SynthParser extends HandlerBase { /** * Lazily created, used for anything we don't understand. */ - private ObjectHandler _handler; + private DocumentHandler _handler; /** * Indicates the depth of how many elements we've encountered but don't @@ -292,8 +292,9 @@ class SynthParser extends HandlerBase { /** * Handles beans persistance. */ - private ObjectHandler getHandler() { + private DocumentHandler getHandler() { if (_handler == null) { + _handler = new DocumentHandler(); if (_urlResourceBase != null) { // getHandler() is never called before parse() so it is safe // to create a URLClassLoader with _resourceBase. @@ -304,14 +305,13 @@ class SynthParser extends HandlerBase { URL[] urls = new URL[] { getResource(".") }; ClassLoader parent = Thread.currentThread().getContextClassLoader(); ClassLoader urlLoader = new URLClassLoader(urls, parent); - _handler = new ObjectHandler(null, urlLoader); + _handler.setClassLoader(urlLoader); } else { - _handler = new ObjectHandler(null, - _classResourceBase.getClassLoader()); + _handler.setClassLoader(_classResourceBase.getClassLoader()); } for (String key : _mapping.keySet()) { - _handler.register(key, _mapping.get(key)); + _handler.setVariable(key, _mapping.get(key)); } } return _handler; @@ -336,8 +336,8 @@ class SynthParser extends HandlerBase { private Object lookup(String key, Class type) throws SAXException { Object value; if (_handler != null) { - if ((value = _handler.lookup(key)) != null) { - return checkCast(value, type); + if (_handler.hasVariable(key)) { + return checkCast(_handler.getVariable(key), type); } } value = _mapping.get(key); @@ -354,11 +354,11 @@ class SynthParser extends HandlerBase { private void register(String key, Object value) throws SAXException { if (key != null) { if (_mapping.get(key) != null || - (_handler != null && _handler.lookup(key) != null)) { + (_handler != null && _handler.hasVariable(key))) { throw new SAXException("ID " + key + " is already defined"); } if (_handler != null) { - _handler.register(key, value); + _handler.setVariable(key, value); } else { _mapping.put(key, value); @@ -400,12 +400,12 @@ class SynthParser extends HandlerBase { // The following methods are invoked from startElement/stopElement // - private void startStyle(AttributeList attributes) throws SAXException { + private void startStyle(Attributes attributes) throws SAXException { String id = null; _style = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_CLONE)) { _style = (ParsedSynthStyle)((ParsedSynthStyle)lookup( attributes.getValue(i), ParsedSynthStyle.class)). @@ -421,7 +421,7 @@ class SynthParser extends HandlerBase { register(id, _style); } - private void endStyle() throws SAXException { + private void endStyle() { int size = _stylePainters.size(); if (size > 0) { _style.setPainters(_stylePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); @@ -435,14 +435,14 @@ class SynthParser extends HandlerBase { _style = null; } - private void startState(AttributeList attributes) throws SAXException { + private void startState(Attributes attributes) throws SAXException { ParsedSynthStyle.StateInfo stateInfo = null; int state = 0; String id = null; _stateInfo = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -496,7 +496,7 @@ class SynthParser extends HandlerBase { _stateInfos.add(_stateInfo); } - private void endState() throws SAXException { + private void endState() { int size = _statePainters.size(); if (size > 0) { _stateInfo.setPainters(_statePainters.toArray(new ParsedSynthStyle.PainterInfo[size])); @@ -505,7 +505,7 @@ class SynthParser extends HandlerBase { _stateInfo = null; } - private void startFont(AttributeList attributes) throws SAXException { + private void startFont(Attributes attributes) throws SAXException { Font font = null; int style = Font.PLAIN; int size = 0; @@ -513,7 +513,7 @@ class SynthParser extends HandlerBase { String name = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -568,13 +568,13 @@ class SynthParser extends HandlerBase { } } - private void startColor(AttributeList attributes) throws SAXException { + private void startColor(Attributes attributes) throws SAXException { Color color = null; String id = null; _colorTypes.clear(); for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); } @@ -697,7 +697,7 @@ class SynthParser extends HandlerBase { } } - private void startProperty(AttributeList attributes, + private void startProperty(Attributes attributes, Object property) throws SAXException { Object value = null; String key = null; @@ -707,7 +707,7 @@ class SynthParser extends HandlerBase { String aValue = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String aName = attributes.getName(i); + String aName = attributes.getQName(i); if (aName.equals(ATTRIBUTE_TYPE)) { String type = attributes.getValue(i).toUpperCase(); if (type.equals("IDREF")) { @@ -795,11 +795,11 @@ class SynthParser extends HandlerBase { } } - private void startGraphics(AttributeList attributes) throws SAXException { + private void startGraphics(Attributes attributes) throws SAXException { SynthGraphicsUtils graphics = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_IDREF)) { graphics = (SynthGraphicsUtils)lookup(attributes.getValue(i), SynthGraphicsUtils.class); @@ -813,7 +813,7 @@ class SynthParser extends HandlerBase { } } - private void startInsets(AttributeList attributes) throws SAXException { + private void startInsets(Attributes attributes) throws SAXException { int top = 0; int bottom = 0; int left = 0; @@ -822,7 +822,7 @@ class SynthParser extends HandlerBase { String id = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); try { if (key.equals(ATTRIBUTE_IDREF)) { @@ -858,13 +858,13 @@ class SynthParser extends HandlerBase { } } - private void startBind(AttributeList attributes) throws SAXException { + private void startBind(Attributes attributes) throws SAXException { ParsedSynthStyle style = null; String path = null; int type = -1; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_STYLE)) { style = (ParsedSynthStyle)lookup(attributes.getValue(i), @@ -899,7 +899,7 @@ class SynthParser extends HandlerBase { } } - private void startPainter(AttributeList attributes, String type) throws SAXException { + private void startPainter(Attributes attributes, String type) throws SAXException { Insets sourceInsets = null; Insets destInsets = null; String path = null; @@ -915,7 +915,7 @@ class SynthParser extends HandlerBase { boolean paintCenterSpecified = false; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); String value = attributes.getValue(i); if (key.equals(ATTRIBUTE_ID)) { @@ -1042,12 +1042,12 @@ class SynthParser extends HandlerBase { painters.add(painterInfo); } - private void startImageIcon(AttributeList attributes) throws SAXException { + private void startImageIcon(Attributes attributes) throws SAXException { String path = null; String id = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { id = attributes.getValue(i); @@ -1062,12 +1062,11 @@ class SynthParser extends HandlerBase { register(id, new LazyImageIcon(getResource(path))); } - private void startOpaque(AttributeList attributes) throws - SAXException { + private void startOpaque(Attributes attributes) { if (_style != null) { _style.setOpaque(true); for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_VALUE)) { _style.setOpaque("true".equals(attributes.getValue(i). @@ -1077,12 +1076,12 @@ class SynthParser extends HandlerBase { } } - private void startInputMap(AttributeList attributes) throws SAXException { + private void startInputMap(Attributes attributes) throws SAXException { _inputMapBindings.clear(); _inputMapID = null; if (_style != null) { for(int i = attributes.getLength() - 1; i >= 0; i--) { - String key = attributes.getName(i); + String key = attributes.getQName(i); if (key.equals(ATTRIBUTE_ID)) { _inputMapID = attributes.getValue(i); @@ -1101,7 +1100,7 @@ class SynthParser extends HandlerBase { _inputMapID = null; } - private void startBindKey(AttributeList attributes) throws SAXException { + private void startBindKey(Attributes attributes) throws SAXException { if (_inputMapID == null) { // Not in an inputmap, bail. return; @@ -1110,7 +1109,7 @@ class SynthParser extends HandlerBase { String key = null; String value = null; for(int i = attributes.getLength() - 1; i >= 0; i--) { - String aKey = attributes.getName(i); + String aKey = attributes.getQName(i); if (aKey.equals(ATTRIBUTE_KEY)) { key = attributes.getValue(i); @@ -1129,26 +1128,26 @@ class SynthParser extends HandlerBase { } // - // SAX methods, these forward to the ObjectHandler if we don't know + // SAX methods, these forward to the DocumentHandler if we don't know // the element name. // public InputSource resolveEntity(String publicId, String systemId) - throws SAXException { + throws IOException, SAXException { if (isForwarding()) { return getHandler().resolveEntity(publicId, systemId); } return null; } - public void notationDecl(String name, String publicId, String systemId) { + public void notationDecl(String name, String publicId, String systemId) throws SAXException { if (isForwarding()) { getHandler().notationDecl(name, publicId, systemId); } } public void unparsedEntityDecl(String name, String publicId, - String systemId, String notationName) { + String systemId, String notationName) throws SAXException { if (isForwarding()) { getHandler().unparsedEntityDecl(name, publicId, systemId, notationName); @@ -1173,7 +1172,7 @@ class SynthParser extends HandlerBase { } } - public void startElement(String name, AttributeList attributes) + public void startElement(String uri, String local, String name, Attributes attributes) throws SAXException { name = name.intern(); if (name == ELEMENT_STYLE) { @@ -1223,18 +1222,18 @@ class SynthParser extends HandlerBase { } else if (name != ELEMENT_SYNTH) { if (_depth++ == 0) { - getHandler().reset(); + getHandler().startDocument(); } - getHandler().startElement(name, attributes); + getHandler().startElement(uri, local, name, attributes); } } - public void endElement(String name) throws SAXException { + public void endElement(String uri, String local, String name) throws SAXException { if (isForwarding()) { - getHandler().endElement(name); + getHandler().endElement(uri, local, name); _depth--; if (!isForwarding()) { - getHandler().reset(); + getHandler().startDocument(); } } else { diff --git a/jdk/src/share/classes/javax/swing/table/DefaultTableColumnModel.java b/jdk/src/share/classes/javax/swing/table/DefaultTableColumnModel.java index 846001b35b1..d3ae8cdd63f 100644 --- a/jdk/src/share/classes/javax/swing/table/DefaultTableColumnModel.java +++ b/jdk/src/share/classes/javax/swing/table/DefaultTableColumnModel.java @@ -190,7 +190,7 @@ public class DefaultTableColumnModel implements TableColumnModel, fireColumnMoved(new TableColumnModelEvent(this, columnIndex, newIndex)); return; } - aColumn = (TableColumn)tableColumns.elementAt(columnIndex); + aColumn = tableColumns.elementAt(columnIndex); tableColumns.removeElementAt(columnIndex); boolean selected = selectionModel.isSelectedIndex(columnIndex); @@ -291,7 +291,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * at columnIndex */ public TableColumn getColumn(int columnIndex) { - return (TableColumn)tableColumns.elementAt(columnIndex); + return tableColumns.elementAt(columnIndex); } /** @@ -504,8 +504,7 @@ public class DefaultTableColumnModel implements TableColumnModel, * @since 1.4 */ public TableColumnModelListener[] getColumnModelListeners() { - return (TableColumnModelListener[])listenerList.getListeners( - TableColumnModelListener.class); + return listenerList.getListeners(TableColumnModelListener.class); } // diff --git a/jdk/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java b/jdk/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java index 11ed3bdd582..34c36ba8957 100644 --- a/jdk/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java +++ b/jdk/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java @@ -84,7 +84,7 @@ import java.util.*; * * @author Rob Davis */ -public class DefaultMutableTreeNode extends Object implements Cloneable, +public class DefaultMutableTreeNode implements Cloneable, MutableTreeNode, Serializable { private static final long serialVersionUID = -4298474751201349152L; @@ -1251,7 +1251,7 @@ public class DefaultMutableTreeNode extends Object implements Cloneable, * @return a copy of this node */ public Object clone() { - DefaultMutableTreeNode newNode = null; + DefaultMutableTreeNode newNode; try { newNode = (DefaultMutableTreeNode)super.clone(); @@ -1297,24 +1297,22 @@ public class DefaultMutableTreeNode extends Object implements Cloneable, userObject = tValues[1]; } - final class PreorderEnumeration implements Enumeration { - protected Stack stack; + private final class PreorderEnumeration implements Enumeration { + private final Stack stack = new Stack(); public PreorderEnumeration(TreeNode rootNode) { super(); - Vector v = new Vector(1); + Vector v = new Vector(1); v.addElement(rootNode); // PENDING: don't really need a vector - stack = new Stack(); stack.push(v.elements()); } public boolean hasMoreElements() { - return (!stack.empty() && - ((Enumeration)stack.peek()).hasMoreElements()); + return (!stack.empty() && stack.peek().hasMoreElements()); } public TreeNode nextElement() { - Enumeration enumer = (Enumeration)stack.peek(); + Enumeration enumer = stack.peek(); TreeNode node = (TreeNode)enumer.nextElement(); Enumeration children = node.children(); @@ -1353,8 +1351,7 @@ public class DefaultMutableTreeNode extends Object implements Cloneable, if (subtree.hasMoreElements()) { retval = subtree.nextElement(); } else if (children.hasMoreElements()) { - subtree = new PostorderEnumeration( - (TreeNode)children.nextElement()); + subtree = new PostorderEnumeration(children.nextElement()); retval = subtree.nextElement(); } else { retval = root; @@ -1373,7 +1370,7 @@ public class DefaultMutableTreeNode extends Object implements Cloneable, public BreadthFirstEnumeration(TreeNode rootNode) { super(); - Vector v = new Vector(1); + Vector v = new Vector(1); v.addElement(rootNode); // PENDING: don't really need a vector queue = new Queue(); queue.enqueue(v.elements()); diff --git a/jdk/src/share/classes/javax/swing/undo/CompoundEdit.java b/jdk/src/share/classes/javax/swing/undo/CompoundEdit.java index 6bc66156029..7aa21d3af8d 100644 --- a/jdk/src/share/classes/javax/swing/undo/CompoundEdit.java +++ b/jdk/src/share/classes/javax/swing/undo/CompoundEdit.java @@ -59,7 +59,7 @@ public class CompoundEdit extends AbstractUndoableEdit { super.undo(); int i = edits.size(); while (i-- > 0) { - UndoableEdit e = (UndoableEdit)edits.elementAt(i); + UndoableEdit e = edits.elementAt(i); e.undo(); } } @@ -85,7 +85,7 @@ public class CompoundEdit extends AbstractUndoableEdit { protected UndoableEdit lastEdit() { int count = edits.size(); if (count > 0) - return (UndoableEdit)edits.elementAt(count-1); + return edits.elementAt(count-1); else return null; } @@ -98,7 +98,7 @@ public class CompoundEdit extends AbstractUndoableEdit { int size = edits.size(); for (int i = size-1; i >= 0; i--) { - UndoableEdit e = (UndoableEdit)edits.elementAt(i); + UndoableEdit e = edits.elementAt(i); // System.out.println("CompoundEdit(" + i + "): Discarding " + // e.getUndoPresentationName()); e.die(); diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java new file mode 100644 index 00000000000..41b933c4a61 --- /dev/null +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -0,0 +1,77 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.awt; + +import java.awt.*; +import sun.misc.Unsafe; + +/** The AWTAccessor utility class. + * The main purpose of this class is to enable accessing + * private and package-private fields of classes from + * different classes/packages. See sun.misc.SharedSecretes + * for another example. + */ +public final class AWTAccessor { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + /** We don't need any objects of this class. + * It's rather a collection of static methods + * and interfaces. + */ + private AWTAccessor() { + } + + /** An accessor for the java.awt.Component class. + */ + public interface ComponentAccessor { + // See 6797587 + // Also see: 6776743, 6768307, and 6768332. + /** + * Sets the shape of a lw component to cut out from hw components. + */ + void setMixingCutoutShape(Component comp, Shape shape); + } + + /* The java.awt.Component class accessor object. + */ + private static ComponentAccessor componentAccessor; + + /** Set an accessor object for the java.awt.Component class. + */ + public static void setComponentAccessor(ComponentAccessor ca) { + componentAccessor = ca; + } + + /** Retrieve the accessor object for the java.awt.Window class. + */ + public static ComponentAccessor getComponentAccessor() { + if (componentAccessor == null) { + unsafe.ensureClassInitialized(Component.class); + } + + return componentAccessor; + } +} diff --git a/jdk/src/share/classes/sun/awt/HeadlessToolkit.java b/jdk/src/share/classes/sun/awt/HeadlessToolkit.java index 97a7686605f..18ccc446be5 100644 --- a/jdk/src/share/classes/sun/awt/HeadlessToolkit.java +++ b/jdk/src/share/classes/sun/awt/HeadlessToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -456,6 +456,10 @@ public class HeadlessToolkit extends Toolkit return tk.getAWTEventListeners(); } + public AWTEventListener[] getAWTEventListeners(long eventMask) { + return tk.getAWTEventListeners(eventMask); + } + public boolean isDesktopSupported() { return false; } @@ -464,4 +468,8 @@ public class HeadlessToolkit extends Toolkit throws HeadlessException{ throw new HeadlessException(); } + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException{ + throw new HeadlessException(); + } } diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 20da8ffe766..7c6f74856a9 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -1972,6 +1972,21 @@ public abstract class SunToolkit extends Toolkit AWTAutoShutdown.getInstance().dumpPeers(aLog); } + private static Boolean sunAwtDisableMixing = null; + + /** + * Returns the value of "sun.awt.disableMixing" property. Default + * value is {@code false}. + */ + public synchronized static boolean getSunAwtDisableMixing() { + if (sunAwtDisableMixing == null) { + sunAwtDisableMixing = Boolean.valueOf( + AccessController.doPrivileged( + new GetBooleanAction("sun.awt.disableMixing"))); + } + return sunAwtDisableMixing.booleanValue(); + } + /** * Returns true if the native GTK libraries are available. The * default implementation returns false, but UNIXToolkit overrides this @@ -2008,26 +2023,12 @@ class PostEventQueue { /* * Continually post pending AWTEvents to the Java EventQueue. */ - public void flush() { - if (queueHead != null) { - EventQueueItem tempQueue; - /* - * We have to execute the loop inside the synchronized block - * to ensure that the flush is completed before a new event - * can be posted to this queue. - */ - synchronized (this) { - tempQueue = queueHead; - queueHead = queueTail = null; - /* - * If this PostEventQueue is flushed in parallel on two - * different threads tempQueue will be null for one of them. - */ - while (tempQueue != null) { - eventQueue.postEvent(tempQueue.event); - tempQueue = tempQueue.next; - } - } + public synchronized void flush() { + EventQueueItem tempQueue = queueHead; + queueHead = queueTail = null; + while (tempQueue != null) { + eventQueue.postEvent(tempQueue.event); + tempQueue = tempQueue.next; } } diff --git a/jdk/src/share/classes/sun/beans/editors/EnumEditor.java b/jdk/src/share/classes/sun/beans/editors/EnumEditor.java index 6a465785c17..201c6f24b81 100644 --- a/jdk/src/share/classes/sun/beans/editors/EnumEditor.java +++ b/jdk/src/share/classes/sun/beans/editors/EnumEditor.java @@ -67,7 +67,7 @@ public final class EnumEditor implements PropertyEditor { } public void setValue( Object value ) { - if ( ( value != null ) && ( this.type != value.getClass() ) ) { + if ( ( value != null ) && !this.type.isInstance( value ) ) { throw new IllegalArgumentException( "Unsupported value: " + value ); } Object oldValue; diff --git a/jdk/src/share/classes/sun/java2d/pipe/Region.java b/jdk/src/share/classes/sun/java2d/pipe/Region.java index 765c4251030..9f395c3b540 100644 --- a/jdk/src/share/classes/sun/java2d/pipe/Region.java +++ b/jdk/src/share/classes/sun/java2d/pipe/Region.java @@ -28,6 +28,7 @@ package sun.java2d.pipe; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; +import java.awt.geom.RectangularShape; /** * This class encapsulates a definition of a two dimensional region which @@ -63,11 +64,28 @@ public class Region { static final int INIT_SIZE = 50; static final int GROW_SIZE = 50; - static final Region EMPTY_REGION = new Region(0, 0, 0, 0); - static final Region WHOLE_REGION = new Region(Integer.MIN_VALUE, - Integer.MIN_VALUE, - Integer.MAX_VALUE, - Integer.MAX_VALUE); + /** + * Immutable Region. + */ + private static final class ImmutableRegion extends Region { + protected ImmutableRegion(int lox, int loy, int hix, int hiy) { + super(lox, loy, hix, hiy); + } + + // Override all the methods that mutate the object + public void appendSpans(sun.java2d.pipe.SpanIterator si) {} + public void setOutputArea(java.awt.Rectangle r) {} + public void setOutputAreaXYWH(int x, int y, int w, int h) {} + public void setOutputArea(int[] box) {} + public void setOutputAreaXYXY(int lox, int loy, int hix, int hiy) {} + } + + public static final Region EMPTY_REGION = new ImmutableRegion(0, 0, 0, 0); + public static final Region WHOLE_REGION = new ImmutableRegion( + Integer.MIN_VALUE, + Integer.MIN_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE); int lox; int loy; @@ -113,7 +131,7 @@ public class Region { return newv; } - private Region(int lox, int loy, int hix, int hiy) { + protected Region(int lox, int loy, int hix, int hiy) { this.lox = lox; this.loy = loy; this.hix = hix; @@ -194,6 +212,13 @@ public class Region { public static Region getInstance(Region devBounds, boolean normalize, Shape s, AffineTransform at) { + // Optimize for empty shapes to avoid involving the SpanIterator + if (s instanceof RectangularShape && + ((RectangularShape)s).isEmpty()) + { + return EMPTY_REGION; + } + int box[] = new int[4]; ShapeSpanIterator sr = new ShapeSpanIterator(normalize); try { @@ -1206,7 +1231,7 @@ public class Region { return false; } if (r.lox != this.lox || r.loy != this.loy || - r.hiy != this.hiy || r.hiy != this.hiy) + r.hix != this.hix || r.hiy != this.hiy) { return false; } diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java index 5e38c767135..28b4441d35d 100644 --- a/jdk/src/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java @@ -25,17 +25,7 @@ package sun.misc; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Hashtable; -import java.util.NoSuchElementException; -import java.util.Stack; -import java.util.Set; -import java.util.HashSet; -import java.util.StringTokenizer; -import java.util.ArrayList; -import java.util.Iterator; +import java.util.*; import java.util.jar.JarFile; import sun.misc.JarIndex; import sun.misc.InvalidJarIndexException; @@ -52,12 +42,7 @@ import java.net.URLConnection; import java.net.HttpURLConnection; import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.DataOutputStream; -import java.io.IOException; +import java.io.*; import java.security.AccessController; import java.security.AccessControlException; import java.security.CodeSigner; @@ -100,6 +85,9 @@ public class URLClassPath { /* The jar protocol handler to use when creating new URLs */ private URLStreamHandler jarHandler; + /* Whether this URLClassLoader has been closed yet */ + private boolean closed = false; + /** * Creates a new URLClassPath for the given URLs. The URLs will be * searched in the order specified for classes and resources. A URL @@ -124,6 +112,22 @@ public class URLClassPath { this(urls, null); } + public synchronized List closeLoaders() { + if (closed) { + return Collections.emptyList(); + } + List result = new LinkedList(); + for (Loader loader : loaders) { + try { + loader.close(); + } catch (IOException e) { + result.add (e); + } + } + closed = true; + return result; + } + /** * Appends the specified URL to the search path of directory and JAR * file URLs from which to load classes and resources. @@ -293,6 +297,9 @@ public class URLClassPath { * if the specified index is out of range. */ private synchronized Loader getLoader(int index) { + if (closed) { + return null; + } // Expand URL search path until the request can be satisfied // or the URL stack is empty. while (loaders.size() < index + 1) { @@ -453,7 +460,7 @@ public class URLClassPath { * Inner class used to represent a loader of resources and classes * from a base URL. */ - private static class Loader { + private static class Loader implements Closeable { private final URL base; /* @@ -544,6 +551,12 @@ public class URLClassPath { return getResource(name, true); } + /* + * close this loader and release all resources + * method overridden in sub-classes + */ + public void close () throws IOException {} + /* * Returns the local class path for this loader, or null if none. */ @@ -562,6 +575,7 @@ public class URLClassPath { private MetaIndex metaIndex; private URLStreamHandler handler; private HashMap lmap; + private boolean closed = false; /* * Creates a new JarLoader for the specified URL referring to @@ -604,6 +618,17 @@ public class URLClassPath { } } + @Override + public void close () throws IOException { + // closing is synchronized at higher level + if (!closed) { + closed = true; + // in case not already open. + ensureOpen(); + jar.close(); + } + } + JarFile getJarFile () { return jar; } diff --git a/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java b/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java new file mode 100644 index 00000000000..f79dc7abbbf --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.AsynchronousChannel; +import java.util.concurrent.Future; + +/** + * Base implementation of Future used for asynchronous I/O + */ + +abstract class AbstractFuture + implements Future +{ + private final AsynchronousChannel channel; + private final A attachment; + + protected AbstractFuture(AsynchronousChannel channel, A attachment) { + this.channel = channel; + this.attachment = attachment; + } + + final AsynchronousChannel channel() { + return channel; + } + + final A attachment() { + return attachment; + } + + /** + * Returns the result of the operation if it has completed successfully. + */ + abstract V value(); + + /** + * Returns the exception if the operation has failed. + */ + abstract Throwable exception(); +} diff --git a/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java b/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java new file mode 100644 index 00000000000..14e33ffe9d1 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java @@ -0,0 +1,341 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.Channel; +import java.nio.channels.AsynchronousChannelGroup; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.io.IOException; +import java.io.FileDescriptor; +import java.util.Queue; +import java.util.concurrent.*; +import java.util.concurrent.locks.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.security.PrivilegedAction; +import java.security.AccessController; +import java.security.AccessControlContext; +import sun.security.action.GetIntegerAction; + +/** + * Base implementation of AsynchronousChannelGroup + */ + +abstract class AsynchronousChannelGroupImpl + extends AsynchronousChannelGroup implements Executor +{ + // number of internal threads handling I/O events when using an unbounded + // thread pool. Internal threads do not dispatch to completion handlers. + private static final int internalThreadCount = AccessController.doPrivileged( + new GetIntegerAction("sun.nio.ch.internalThreadPoolSize", 1)); + + // associated thread pool + private final ThreadPool pool; + + // number of tasks running (including internal) + private final AtomicInteger threadCount = new AtomicInteger(); + + // associated Executor for timeouts + private ScheduledThreadPoolExecutor timeoutExecutor; + + // task queue for when using a fixed thread pool. In that case, thread + // waiting on I/O events must be awokon to poll tasks from this queue. + private final Queue taskQueue; + + // group shutdown + // shutdownLock is RW lock so as to allow for concurrent queuing of tasks + // when using a fixed thread pool. + private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock(); + private final Object shutdownNowLock = new Object(); + private volatile boolean shutdown; + private volatile boolean terminateInitiated; + + AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider, + ThreadPool pool) + { + super(provider); + this.pool = pool; + + if (pool.isFixedThreadPool()) { + taskQueue = new ConcurrentLinkedQueue(); + } else { + taskQueue = null; // not used + } + + // use default thread factory as thread should not be visible to + // application (it doesn't execute completion handlers). + this.timeoutExecutor = (ScheduledThreadPoolExecutor) + Executors.newScheduledThreadPool(1, ThreadPool.defaultThreadFactory()); + this.timeoutExecutor.setRemoveOnCancelPolicy(true); + } + + final ExecutorService executor() { + return pool.executor(); + } + + final boolean isFixedThreadPool() { + return pool.isFixedThreadPool(); + } + + final int fixedThreadCount() { + if (isFixedThreadPool()) { + return pool.poolSize(); + } else { + return pool.poolSize() + internalThreadCount; + } + } + + private Runnable bindToGroup(final Runnable task) { + final AsynchronousChannelGroupImpl thisGroup = this; + return new Runnable() { + public void run() { + Invoker.bindToGroup(thisGroup); + task.run(); + } + }; + } + + private void startInternalThread(final Runnable task) { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + // internal threads should not be visible to application so + // cannot use user-supplied thread factory + ThreadPool.defaultThreadFactory().newThread(task).start(); + return null; + } + }); + } + + protected final void startThreads(Runnable task) { + if (!isFixedThreadPool()) { + for (int i=0; i 0) { + task = bindToGroup(task); + try { + for (int i=0; i schedule(Runnable task, long timeout, TimeUnit unit) { + try { + return timeoutExecutor.schedule(task, timeout, unit); + } catch (RejectedExecutionException rej) { + if (terminateInitiated) { + // no timeout scheduled as group is terminating + return null; + } + throw new AssertionError(rej); + } + } + + @Override + public final boolean isShutdown() { + return shutdown; + } + + @Override + public final boolean isTerminated() { + return pool.executor().isTerminated(); + } + + /** + * Returns true if there are no channels in the group + */ + abstract boolean isEmpty(); + + /** + * Attaches a foreign channel to this group. + */ + abstract Object attachForeignChannel(Channel channel, FileDescriptor fdo) + throws IOException; + + /** + * Detaches a foreign channel from this group. + */ + abstract void detachForeignChannel(Object key); + + /** + * Closes all channels in the group + */ + abstract void closeAllChannels() throws IOException; + + /** + * Shutdown all tasks waiting for I/O events. + */ + abstract void shutdownHandlerTasks(); + + private void shutdownExecutors() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + pool.executor().shutdown(); + timeoutExecutor.shutdown(); + return null; + } + }); + } + + @Override + public final void shutdown() { + shutdownLock.writeLock().lock(); + try { + if (shutdown) { + // already shutdown + return; + } + shutdown = true; + } finally { + shutdownLock.writeLock().unlock(); + } + + // if there are channels in the group then shutdown will continue + // when the last channel is closed + if (!isEmpty()) { + return; + } + // initiate termination (acquire shutdownNowLock to ensure that other + // threads invoking shutdownNow will block). + synchronized (shutdownNowLock) { + if (!terminateInitiated) { + terminateInitiated = true; + shutdownHandlerTasks(); + shutdownExecutors(); + } + } + } + + @Override + public final void shutdownNow() throws IOException { + shutdownLock.writeLock().lock(); + try { + shutdown = true; + } finally { + shutdownLock.writeLock().unlock(); + } + synchronized (shutdownNowLock) { + if (!terminateInitiated) { + terminateInitiated = true; + closeAllChannels(); + shutdownHandlerTasks(); + shutdownExecutors(); + } + } + } + + @Override + public final boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException + { + return pool.executor().awaitTermination(timeout, unit); + } + + /** + * Executes the given command on one of the channel group's pooled threads. + */ + @Override + public final void execute(Runnable task) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // when a security manager is installed then the user's task + // must be run with the current calling context + final AccessControlContext acc = AccessController.getContext(); + final Runnable delegate = task; + task = new Runnable() { + @Override + public void run() { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + delegate.run(); + return null; + } + }, acc); + } + }; + } + executeOnPooledThread(task); + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java new file mode 100644 index 00000000000..2735a5a29cd --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java @@ -0,0 +1,164 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.locks.*; +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * Base implementation of AsynchronousFileChannel. + */ + +abstract class AsynchronousFileChannelImpl + extends AsynchronousFileChannel +{ + // close support + protected final ReadWriteLock closeLock = new ReentrantReadWriteLock(); + protected volatile boolean closed; + + // file descriptor + protected final FileDescriptor fdObj; + + // indicates if open for reading/writing + protected final boolean reading; + protected final boolean writing; + + // associated Executor + protected final ExecutorService executor; + + protected AsynchronousFileChannelImpl(FileDescriptor fdObj, + boolean reading, + boolean writing, + ExecutorService executor) + { + this.fdObj = fdObj; + this.reading = reading; + this.writing = writing; + this.executor = executor; + } + + final ExecutorService executor() { + return executor; + } + + @Override + public final boolean isOpen() { + return !closed; + } + + /** + * Marks the beginning of an I/O operation. + * + * @throws ClosedChannelException If channel is closed + */ + protected final void begin() throws IOException { + closeLock.readLock().lock(); + if (closed) + throw new ClosedChannelException(); + } + + /** + * Marks the end of an I/O operation. + */ + protected final void end() { + closeLock.readLock().unlock(); + } + + /** + * Marks end of I/O operation + */ + protected final void end(boolean completed) throws IOException { + end(); + if (!completed && !isOpen()) + throw new AsynchronousCloseException(); + } + + // -- file locking -- + + private volatile FileLockTable fileLockTable; + + final void ensureFileLockTableInitialized() throws IOException { + if (fileLockTable == null) { + synchronized (this) { + if (fileLockTable == null) { + fileLockTable = FileLockTable.newSharedFileLockTable(this, fdObj); + } + } + } + } + + final void invalidateAllLocks() { + if (fileLockTable != null) { + try { + fileLockTable.removeAll( new FileLockTable.Releaser() { + public void release(FileLock fl) { + ((FileLockImpl)fl).invalidate(); + } + }); + } catch (IOException e) { + throw new AssertionError(e); + } + } + } + + /** + * Adds region to lock table + */ + protected final FileLockImpl addToFileLockTable(long position, long size, boolean shared) { + final FileLockImpl fli; + try { + // like begin() but returns null instead of exception + closeLock.readLock().lock(); + if (closed) + return null; + + try { + ensureFileLockTableInitialized(); + } catch (IOException x) { + // should not happen + throw new AssertionError(x); + } + fli = new FileLockImpl(this, position, size, shared); + // may throw OverlappedFileLockException + fileLockTable.add(fli); + } finally { + end(); + } + return fli; + } + + protected final void removeFromFileLockTable(FileLockImpl fli) { + fileLockTable.remove(fli); + } + + /** + * Invoked by FileLockImpl to release lock acquired by this channel. + */ + abstract void release(FileLockImpl fli) throws IOException; +} diff --git a/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java new file mode 100644 index 00000000000..b4fcb9c2c30 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -0,0 +1,219 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.net.SocketAddress; +import java.net.SocketOption; +import java.net.StandardSocketOption; +import java.net.InetSocketAddress; +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Base implementation of AsynchronousServerSocketChannel. + */ + +abstract class AsynchronousServerSocketChannelImpl + extends AsynchronousServerSocketChannel + implements Cancellable, Groupable +{ + protected final FileDescriptor fd; + + // the local address to which the channel's socket is bound + protected volatile SocketAddress localAddress = null; + + // need this lock to set local address + private final Object stateLock = new Object(); + + // close support + private ReadWriteLock closeLock = new ReentrantReadWriteLock(); + private volatile boolean open = true; + + // set true when accept operation is cancelled + private volatile boolean acceptKilled; + + + AsynchronousServerSocketChannelImpl(AsynchronousChannelGroupImpl group) { + super(group.provider()); + this.fd = Net.serverSocket(true); + } + + @Override + public final boolean isOpen() { + return open; + } + + /** + * Marks beginning of access to file descriptor/handle + */ + final void begin() throws IOException { + closeLock.readLock().lock(); + if (!isOpen()) + throw new ClosedChannelException(); + } + + /** + * Marks end of access to file descriptor/handle + */ + final void end() { + closeLock.readLock().unlock(); + } + + /** + * Invoked to close file descriptor/handle. + */ + abstract void implClose() throws IOException; + + @Override + public final void close() throws IOException { + // synchronize with any threads using file descriptor/handle + closeLock.writeLock().lock(); + try { + if (!open) + return; // already closed + open = false; + } finally { + closeLock.writeLock().unlock(); + } + implClose(); + } + + final boolean isAcceptKilled() { + return acceptKilled; + } + + @Override + public final void onCancel(PendingFuture task) { + acceptKilled = true; + } + + @Override + public final AsynchronousServerSocketChannel bind(SocketAddress local, int backlog) + throws IOException + { + InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : + Net.checkAddress(local); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkListen(isa.getPort()); + + try { + begin(); + synchronized (stateLock) { + if (localAddress != null) + throw new AlreadyBoundException(); + Net.bind(fd, isa.getAddress(), isa.getPort()); + Net.listen(fd, backlog < 1 ? 50 : backlog); + localAddress = Net.localAddress(fd); + } + } finally { + end(); + } + return this; + } + + @Override + public final SocketAddress getLocalAddress() throws IOException { + if (!isOpen()) + throw new ClosedChannelException(); + return localAddress; + } + + @Override + public final AsynchronousServerSocketChannel setOption(SocketOption name, + T value) + throws IOException + { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + try { + begin(); + Net.setSocketOption(fd, Net.UNSPEC, name, value); + return this; + } finally { + end(); + } + } + + @Override + @SuppressWarnings("unchecked") + public final T getOption(SocketOption name) throws IOException { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + try { + begin(); + return (T) Net.getSocketOption(fd, Net.UNSPEC, name); + } finally { + end(); + } + } + + private static class DefaultOptionsHolder { + static final Set> defaultOptions = defaultOptions(); + + private static Set> defaultOptions() { + HashSet> set = new HashSet>(2); + set.add(StandardSocketOption.SO_RCVBUF); + set.add(StandardSocketOption.SO_REUSEADDR); + return Collections.unmodifiableSet(set); + } + } + + @Override + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; + } + + @Override + public final String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getName()); + sb.append('['); + if (!isOpen()) + sb.append("closed"); + else { + if (localAddress == null) { + sb.append("unbound"); + } else { + sb.append(localAddress.toString()); + } + } + sb.append(']'); + return sb.toString(); + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java new file mode 100644 index 00000000000..09637fbae1b --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -0,0 +1,542 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.SocketOption; +import java.net.StandardSocketOption; +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.io.IOException; +import java.io.FileDescriptor; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import java.util.concurrent.*; +import java.util.concurrent.locks.*; + +/** + * Base implementation of AsynchronousSocketChannel + */ + +abstract class AsynchronousSocketChannelImpl + extends AsynchronousSocketChannel + implements Cancellable, Groupable +{ + protected final FileDescriptor fd; + + // protects state, localAddress, and remoteAddress + protected final Object stateLock = new Object(); + + protected volatile SocketAddress localAddress = null; + protected volatile SocketAddress remoteAddress = null; + + // State, increases monotonically + static final int ST_UNINITIALIZED = -1; + static final int ST_UNCONNECTED = 0; + static final int ST_PENDING = 1; + static final int ST_CONNECTED = 2; + protected volatile int state = ST_UNINITIALIZED; + + // reading state + private final Object readLock = new Object(); + private boolean reading; + private boolean readShutdown; + private boolean readKilled; // further reading disallowed due to timeout + + // writing state + private final Object writeLock = new Object(); + private boolean writing; + private boolean writeShutdown; + private boolean writeKilled; // further writing disallowed due to timeout + + // close support + private final ReadWriteLock closeLock = new ReentrantReadWriteLock(); + private volatile boolean open = true; + + AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group) + throws IOException + { + super(group.provider()); + this.fd = Net.socket(true); + this.state = ST_UNCONNECTED; + } + + // Constructor for sockets obtained from AsynchronousServerSocketChannelImpl + AsynchronousSocketChannelImpl(AsynchronousChannelGroupImpl group, + FileDescriptor fd, + InetSocketAddress remote) + throws IOException + { + super(group.provider()); + this.fd = fd; + this.state = ST_CONNECTED; + this.localAddress = Net.localAddress(fd); + this.remoteAddress = remote; + } + + @Override + public final boolean isOpen() { + return open; + } + + /** + * Marks beginning of access to file descriptor/handle + */ + final void begin() throws IOException { + closeLock.readLock().lock(); + if (!isOpen()) + throw new ClosedChannelException(); + } + + /** + * Marks end of access to file descriptor/handle + */ + final void end() { + closeLock.readLock().unlock(); + } + + /** + * Invoked to close socket and release other resources. + */ + abstract void implClose() throws IOException; + + @Override + public final void close() throws IOException { + // synchronize with any threads initiating asynchronous operations + closeLock.writeLock().lock(); + try { + if (!open) + return; // already closed + open = false; + } finally { + closeLock.writeLock().unlock(); + } + implClose(); + } + + final void enableReading(boolean killed) { + synchronized (readLock) { + reading = false; + if (killed) + readKilled = true; + } + } + + final void enableReading() { + enableReading(false); + } + + final void enableWriting(boolean killed) { + synchronized (writeLock) { + writing = false; + if (killed) + writeKilled = true; + } + } + + final void enableWriting() { + enableWriting(false); + } + + final void killReading() { + synchronized (readLock) { + readKilled = true; + } + } + + final void killWriting() { + synchronized (writeLock) { + writeKilled = true; + } + } + + final void killConnect() { + // when a connect is cancelled then the connection may have been + // established so prevent reading or writing. + killReading(); + killWriting(); + } + + /** + * Invoked by read to initiate the I/O operation. + */ + abstract Future readImpl(ByteBuffer[] dsts, + boolean isScatteringRead, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + @SuppressWarnings("unchecked") + private Future read(ByteBuffer[] dsts, + boolean isScatteringRead, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + if (remoteAddress == null) + throw new NotYetConnectedException(); + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + + boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining(); + boolean shutdown = false; + + // check and update state + synchronized (readLock) { + if (readKilled) + throw new RuntimeException("Reading not allowed due to timeout or cancellation"); + if (reading) + throw new ReadPendingException(); + if (readShutdown) { + shutdown = true; + } else { + if (hasSpaceToRead) { + reading = true; + } + } + } + + // immediately complete with -1 if shutdown for read + // immediately complete with 0 if no space remaining + if (shutdown || !hasSpaceToRead) { + CompletedFuture result; + if (isScatteringRead) { + Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L); + result = (CompletedFuture)CompletedFuture.withResult(this, value, attachment); + } else { + int value = (shutdown) ? -1 : 0; + result = (CompletedFuture)CompletedFuture.withResult(this, value, attachment); + } + Invoker.invoke(handler, result); + return result; + } + + return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler); + } + + @Override + public final Future read(ByteBuffer dst, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = dst; + return read(bufs, false, timeout, unit, attachment, handler); + } + + @Override + public final Future read(ByteBuffer[] dsts, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) + throw new IndexOutOfBoundsException(); + ByteBuffer[] bufs = Util.subsequence(dsts, offset, length); + for (int i=0; i Future writeImpl(ByteBuffer[] srcs, + boolean isGatheringWrite, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler); + + @SuppressWarnings("unchecked") + private Future write(ByteBuffer[] srcs, + boolean isGatheringWrite, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining(); + + boolean closed = false; + if (isOpen()) { + if (remoteAddress == null) + throw new NotYetConnectedException(); + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + // check and update state + synchronized (writeLock) { + if (writeKilled) + throw new RuntimeException("Writing not allowed due to timeout or cancellation"); + if (writing) + throw new WritePendingException(); + if (writeShutdown) { + closed = true; + } else { + if (hasDataToWrite) + writing = true; + } + } + } else { + closed = true; + } + + // channel is closed or shutdown for write + if (closed) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + // nothing to write so complete immediately + if (!hasDataToWrite) { + CompletedFuture result; + if (isGatheringWrite) { + result = (CompletedFuture)CompletedFuture.withResult(this, 0L, attachment); + } else { + result = (CompletedFuture)CompletedFuture.withResult(this, 0, attachment); + } + Invoker.invoke(handler, result); + return result; + } + + return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler); + } + + @Override + public final Future write(ByteBuffer src, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = src; + return write(bufs, false, timeout, unit, attachment, handler); + } + + @Override + public final Future write(ByteBuffer[] srcs, + int offset, + int length, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) + throw new IndexOutOfBoundsException(); + srcs = Util.subsequence(srcs, offset, length); + return write(srcs, true, timeout, unit, attachment, handler); + } + + @Override + public final AsynchronousSocketChannel bind(SocketAddress local) + throws IOException + { + try { + begin(); + synchronized (stateLock) { + if (state == ST_PENDING) + throw new ConnectionPendingException(); + if (localAddress != null) + throw new AlreadyBoundException(); + InetSocketAddress isa = (local == null) ? + new InetSocketAddress(0) : Net.checkAddress(local); + Net.bind(fd, isa.getAddress(), isa.getPort()); + localAddress = Net.localAddress(fd); + } + } finally { + end(); + } + return this; + } + + @Override + public final SocketAddress getLocalAddress() throws IOException { + if (!isOpen()) + throw new ClosedChannelException(); + return localAddress; + } + + @Override + public final AsynchronousSocketChannel setOption(SocketOption name, T value) + throws IOException + { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + try { + begin(); + if (writeShutdown) + throw new IOException("Connection has been shutdown for writing"); + Net.setSocketOption(fd, Net.UNSPEC, name, value); + return this; + } finally { + end(); + } + } + + @Override + @SuppressWarnings("unchecked") + public final T getOption(SocketOption name) throws IOException { + if (name == null) + throw new NullPointerException(); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); + + try { + begin(); + return (T) Net.getSocketOption(fd, Net.UNSPEC, name); + } finally { + end(); + } + } + + private static class DefaultOptionsHolder { + static final Set> defaultOptions = defaultOptions(); + + private static Set> defaultOptions() { + HashSet> set = new HashSet>(5); + set.add(StandardSocketOption.SO_SNDBUF); + set.add(StandardSocketOption.SO_RCVBUF); + set.add(StandardSocketOption.SO_KEEPALIVE); + set.add(StandardSocketOption.SO_REUSEADDR); + set.add(StandardSocketOption.TCP_NODELAY); + return Collections.unmodifiableSet(set); + } + } + + @Override + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; + } + + @Override + @SuppressWarnings("unchecked") + public final SocketAddress getRemoteAddress() throws IOException { + if (!isOpen()) + throw new ClosedChannelException(); + return remoteAddress; + } + + @Override + public final AsynchronousSocketChannel shutdownInput() throws IOException { + try { + begin(); + if (remoteAddress == null) + throw new NotYetConnectedException(); + synchronized (readLock) { + if (!readShutdown) { + Net.shutdown(fd, Net.SHUT_RD); + readShutdown = true; + } + } + } finally { + end(); + } + return this; + } + + @Override + public final AsynchronousSocketChannel shutdownOutput() throws IOException { + try { + begin(); + if (remoteAddress == null) + throw new NotYetConnectedException(); + synchronized (writeLock) { + if (!writeShutdown) { + Net.shutdown(fd, Net.SHUT_WR); + writeShutdown = true; + } + } + } finally { + end(); + } + return this; + } + + @Override + public final String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getName()); + sb.append('['); + synchronized (stateLock) { + if (!isOpen()) { + sb.append("closed"); + } else { + switch (state) { + case ST_UNCONNECTED: + sb.append("unconnected"); + break; + case ST_PENDING: + sb.append("connection-pending"); + break; + case ST_CONNECTED: + sb.append("connected"); + if (readShutdown) + sb.append(" ishut"); + if (writeShutdown) + sb.append(" oshut"); + break; + } + if (localAddress != null) { + sb.append(" local="); + sb.append(localAddress.toString()); + } + if (remoteAddress != null) { + sb.append(" remote="); + sb.append(remoteAddress.toString()); + } + } + } + sb.append(']'); + return sb.toString(); + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/Cancellable.java b/jdk/src/share/classes/sun/nio/ch/Cancellable.java new file mode 100644 index 00000000000..ae08ed9eb89 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/Cancellable.java @@ -0,0 +1,39 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +/** + * Implemented by asynchronous channels that require notification when an I/O + * operation is cancelled. + */ + +interface Cancellable { + /** + * Invoked to notify channel that cancel has been invoked while holding + * the Future's lock. + */ + void onCancel(PendingFuture task); +} diff --git a/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java b/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java new file mode 100644 index 00000000000..221b9f8f5f7 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java @@ -0,0 +1,113 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.AsynchronousChannel; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ExecutionException; +import java.io.IOException; + +/** + * A Future representing the result of an I/O operation that has already + * completed. + */ + +final class CompletedFuture + extends AbstractFuture +{ + private final V result; + private final Throwable exc; + + private CompletedFuture(AsynchronousChannel channel, + V result, + Throwable exc, + A attachment) + { + super(channel, attachment); + this.result = result; + this.exc = exc; + } + + @SuppressWarnings("unchecked") + static CompletedFuture withResult(AsynchronousChannel channel, + V result, + A attachment) + { + return new CompletedFuture(channel, result, null, attachment); + } + + @SuppressWarnings("unchecked") + static CompletedFuture withFailure(AsynchronousChannel channel, + Throwable exc, + A attachment) + { + // exception must be IOException or SecurityException + if (!(exc instanceof IOException) && !(exc instanceof SecurityException)) + exc = new IOException(exc); + return new CompletedFuture(channel, null, exc, attachment); + } + + @Override + public V get() throws ExecutionException { + if (exc != null) + throw new ExecutionException(exc); + return result; + } + + @Override + public V get(long timeout, TimeUnit unit) throws ExecutionException { + if (unit == null) + throw new NullPointerException(); + if (exc != null) + throw new ExecutionException(exc); + return result; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return true; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + Throwable exception() { + return exc; + } + + @Override + V value() { + return result; + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 54cbfba16c3..e5ec5e0632d 100644 --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,8 +111,12 @@ class DatagramChannelImpl public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family) { super(sp); if ((family != StandardProtocolFamily.INET) && - (family != StandardProtocolFamily.INET6)) { - throw new UnsupportedOperationException("Protocol family not supported"); + (family != StandardProtocolFamily.INET6)) + { + if (family == null) + throw new NullPointerException("'family' is null"); + else + throw new UnsupportedOperationException("Protocol family not supported"); } if (family == StandardProtocolFamily.INET6) { if (!Net.isIPv6Available()) { @@ -149,28 +153,28 @@ class DatagramChannelImpl public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) - return null; + throw new ClosedChannelException(); return localAddress; } } @Override - public SocketAddress getConnectedAddress() throws IOException { + public SocketAddress getRemoteAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) - return null; + throw new ClosedChannelException(); return remoteAddress; } } @Override - public DatagramChannel setOption(SocketOption name, Object value) + public DatagramChannel setOption(SocketOption name, T value) throws IOException { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("Invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { ensureOpen(); @@ -224,8 +228,8 @@ class DatagramChannelImpl { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("Invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { ensureOpen(); @@ -273,7 +277,7 @@ class DatagramChannelImpl } } - private static class LazyInitialization { + private static class DefaultOptionsHolder { static final Set> defaultOptions = defaultOptions(); private static Set> defaultOptions() { @@ -291,8 +295,8 @@ class DatagramChannelImpl } @Override - public final Set> options() { - return LazyInitialization.defaultOptions; + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; } private void ensureOpen() throws ClosedChannelException { @@ -864,23 +868,26 @@ class DatagramChannelImpl } // package-private - void drop(MembershipKeyImpl key) - throws IOException - { - assert key.getChannel() == this; + void drop(MembershipKeyImpl key) { + assert key.channel() == this; synchronized (stateLock) { if (!key.isValid()) return; - if (family == StandardProtocolFamily.INET6) { - MembershipKeyImpl.Type6 key6 = - (MembershipKeyImpl.Type6)key; - Net.drop6(fd, key6.group(), key6.index(), key6.source()); - } else { - MembershipKeyImpl.Type4 key4 = - (MembershipKeyImpl.Type4)key; - Net.drop4(fd, key4.group(), key4.interfaceAddress(), key4.source()); + try { + if (family == StandardProtocolFamily.INET6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); + } else { + MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; + Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), + key4.source()); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); } key.invalidate(); @@ -895,8 +902,8 @@ class DatagramChannelImpl void block(MembershipKeyImpl key, InetAddress source) throws IOException { - assert key.getChannel() == this; - assert key.getSourceAddress() == null; + assert key.channel() == this; + assert key.sourceAddress() == null; synchronized (stateLock) { if (!key.isValid()) @@ -905,19 +912,19 @@ class DatagramChannelImpl throw new IllegalArgumentException("Source address is a wildcard address"); if (source.isMulticastAddress()) throw new IllegalArgumentException("Source address is multicast address"); - if (source.getClass() != key.getGroup().getClass()) + if (source.getClass() != key.group().getClass()) throw new IllegalArgumentException("Source address is different type to group"); int n; if (family == StandardProtocolFamily.INET6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6)key; - n = Net.block6(fd, key6.group(), key6.index(), + n = Net.block6(fd, key6.groupAddress(), key6.index(), Net.inet6AsByteArray(source)); } else { MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; - n = Net.block4(fd, key4.group(), key4.interfaceAddress(), + n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), Net.inet4AsInt(source)); } if (n == IOStatus.UNAVAILABLE) { @@ -930,26 +937,29 @@ class DatagramChannelImpl /** * Unblock given source. */ - void unblock(MembershipKeyImpl key, InetAddress source) - throws IOException - { - assert key.getChannel() == this; - assert key.getSourceAddress() == null; + void unblock(MembershipKeyImpl key, InetAddress source) { + assert key.channel() == this; + assert key.sourceAddress() == null; synchronized (stateLock) { if (!key.isValid()) throw new IllegalStateException("key is no longer valid"); - if (family == StandardProtocolFamily.INET6) { - MembershipKeyImpl.Type6 key6 = - (MembershipKeyImpl.Type6)key; - Net.unblock6(fd, key6.group(), key6.index(), - Net.inet6AsByteArray(source)); - } else { - MembershipKeyImpl.Type4 key4 = - (MembershipKeyImpl.Type4)key; - Net.unblock4(fd, key4.group(), key4.interfaceAddress(), - Net.inet4AsInt(source)); + try { + if (family == StandardProtocolFamily.INET6) { + MembershipKeyImpl.Type6 key6 = + (MembershipKeyImpl.Type6)key; + Net.unblock6(fd, key6.groupAddress(), key6.index(), + Net.inet6AsByteArray(source)); + } else { + MembershipKeyImpl.Type4 key4 = + (MembershipKeyImpl.Type4)key; + Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), + Net.inet4AsInt(source)); + } + } catch (IOException ioe) { + // should not happen + throw new AssertionError(ioe); } } } diff --git a/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java b/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java index 86e787ef805..d695fd2a4f5 100644 --- a/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java +++ b/jdk/src/share/classes/sun/nio/ch/ExtendedSocketOption.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java index 894c489cd85..1e622e1f4ae 100644 --- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,27 +26,18 @@ package sun.nio.ch; import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.RandomAccessFile; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.BufferPoolMXBean; import java.nio.channels.*; -import java.nio.channels.spi.*; import java.util.ArrayList; import java.util.List; import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.lang.ref.WeakReference; -import java.lang.ref.ReferenceQueue; import java.lang.reflect.Field; import java.security.AccessController; -import java.security.PrivilegedAction; import javax.management.ObjectName; import javax.management.MalformedObjectNameException; - import sun.misc.Cleaner; import sun.security.action.GetPropertyAction; @@ -55,14 +46,11 @@ public class FileChannelImpl { // Used to make native read and write calls - private static final NativeDispatcher nd; + private static final FileDispatcher nd; // Memory allocation size for mapping buffers private static final long allocationGranularity; - // Cached field for MappedByteBuffer.isAMappedBuffer - private static final Field isAMappedBufferField; - // File descriptor private final FileDescriptor fd; @@ -107,20 +95,19 @@ public class FileChannelImpl // -- Standard channel operations -- protected void implCloseChannel() throws IOException { - - nd.preClose(fd); - threads.signal(); - // Invalidate and release any locks that we still hold if (fileLockTable != null) { fileLockTable.removeAll( new FileLockTable.Releaser() { public void release(FileLock fl) throws IOException { ((FileLockImpl)fl).invalidate(); - release0(fd, fl.position(), fl.size()); + nd.release(fd, fl.position(), fl.size()); } }); } + nd.preClose(fd); + threads.signalAndWait(); + if (parent != null) { // Close the fd via the parent stream's close method. The parent @@ -141,12 +128,11 @@ public class FileChannelImpl throw new NonReadableChannelException(); synchronized (positionLock) { int n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return 0; - ti = threads.add(); do { n = IOUtil.read(fd, dst, -1, nd, positionLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -165,12 +151,11 @@ public class FileChannelImpl throw new NonReadableChannelException(); synchronized (positionLock) { long n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return 0; - ti = threads.add(); do { n = IOUtil.read(fd, dsts, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -198,12 +183,11 @@ public class FileChannelImpl throw new NonWritableChannelException(); synchronized (positionLock) { int n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return 0; - ti = threads.add(); do { n = IOUtil.write(fd, src, -1, nd, positionLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -222,12 +206,11 @@ public class FileChannelImpl throw new NonWritableChannelException(); synchronized (positionLock) { long n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return 0; - ti = threads.add(); do { n = IOUtil.write(fd, srcs, nd); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -256,12 +239,11 @@ public class FileChannelImpl ensureOpen(); synchronized (positionLock) { long p = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return 0; - ti = threads.add(); do { p = position0(fd, -1); } while ((p == IOStatus.INTERRUPTED) && isOpen()); @@ -280,12 +262,11 @@ public class FileChannelImpl throw new IllegalArgumentException(); synchronized (positionLock) { long p = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return null; - ti = threads.add(); do { p = position0(fd, newPosition); } while ((p == IOStatus.INTERRUPTED) && isOpen()); @@ -302,14 +283,13 @@ public class FileChannelImpl ensureOpen(); synchronized (positionLock) { long s = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return -1; - ti = threads.add(); do { - s = size0(fd); + s = nd.size(fd); } while ((s == IOStatus.INTERRUPTED) && isOpen()); return IOStatus.normalize(s); } finally { @@ -331,12 +311,11 @@ public class FileChannelImpl synchronized (positionLock) { int rv = -1; long p = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return null; - ti = threads.add(); // get current position do { @@ -348,7 +327,7 @@ public class FileChannelImpl // truncate file do { - rv = truncate0(fd, size); + rv = nd.truncate(fd, size); } while ((rv == IOStatus.INTERRUPTED) && isOpen()); if (!isOpen()) return null; @@ -371,14 +350,13 @@ public class FileChannelImpl public void force(boolean metaData) throws IOException { ensureOpen(); int rv = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return; - ti = threads.add(); do { - rv = force0(fd, metaData); + rv = nd.force(fd, metaData); } while ((rv == IOStatus.INTERRUPTED) && isOpen()); } finally { threads.remove(ti); @@ -428,12 +406,11 @@ public class FileChannelImpl return IOStatus.UNSUPPORTED; long n = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return -1; - ti = threads.add(); do { n = transferTo0(thisFDVal, position, icount, targetFDVal); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -635,12 +612,11 @@ public class FileChannelImpl throw new NonReadableChannelException(); ensureOpen(); int n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return -1; - ti = threads.add(); do { n = IOUtil.read(fd, dst, position, nd, positionLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -661,12 +637,11 @@ public class FileChannelImpl throw new NonWritableChannelException(); ensureOpen(); int n = 0; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return -1; - ti = threads.add(); do { n = IOUtil.write(fd, src, position, nd, positionLock); } while ((n == IOStatus.INTERRUPTED) && isOpen()); @@ -756,12 +731,11 @@ public class FileChannelImpl throw new NonReadableChannelException(); long addr = -1; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return null; - ti = threads.add(); if (size() < position + size) { // Extend file size if (!writable) { throw new IOException("Channel not open for writing " + @@ -769,7 +743,7 @@ public class FileChannelImpl } int rv; do { - rv = truncate0(fd, position + size); + rv = nd.truncate(fd, position + size); } while ((rv == IOStatus.INTERRUPTED) && isOpen()); } if (size == 0) { @@ -863,10 +837,7 @@ public class FileChannelImpl // -- Locks -- - public static final int NO_LOCK = -1; // Failed to lock - public static final int LOCKED = 0; // Obtained requested lock - public static final int RET_EX_LOCK = 1; // Obtained exclusive lock - public static final int INTERRUPTED = 2; // Request interrupted + // keeps track of locks on this file private volatile FileLockTable fileLockTable; @@ -896,12 +867,21 @@ public class FileChannelImpl return isSharedFileLockTable; } - private FileLockTable fileLockTable() { + private FileLockTable fileLockTable() throws IOException { if (fileLockTable == null) { synchronized (this) { if (fileLockTable == null) { - fileLockTable = isSharedFileLockTable() ? - new SharedFileLockTable(this) : new SimpleFileLockTable(); + if (isSharedFileLockTable()) { + int ti = threads.add(); + try { + ensureOpen(); + fileLockTable = FileLockTable.newSharedFileLockTable(this, fd); + } finally { + threads.remove(ti); + } + } else { + fileLockTable = new SimpleFileLockTable(); + } } } } @@ -920,21 +900,20 @@ public class FileChannelImpl FileLockTable flt = fileLockTable(); flt.add(fli); boolean i = true; - int ti = -1; + int ti = threads.add(); try { begin(); if (!isOpen()) return null; - ti = threads.add(); - int result = lock0(fd, true, position, size, shared); - if (result == RET_EX_LOCK) { + int result = nd.lock(fd, true, position, size, shared); + if (result == FileDispatcher.RET_EX_LOCK) { assert shared; FileLockImpl fli2 = new FileLockImpl(this, position, size, false); flt.replace(fli, fli2); return fli2; } - if (result == INTERRUPTED || result == NO_LOCK) { + if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) { flt.remove(fli); i = false; } @@ -963,77 +942,54 @@ public class FileChannelImpl FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockTable flt = fileLockTable(); flt.add(fli); - int result = lock0(fd, false, position, size, shared); - if (result == NO_LOCK) { - flt.remove(fli); - return null; + int result; + + int ti = threads.add(); + try { + try { + ensureOpen(); + result = nd.lock(fd, false, position, size, shared); + } catch (IOException e) { + flt.remove(fli); + throw e; + } + if (result == FileDispatcher.NO_LOCK) { + flt.remove(fli); + return null; + } + if (result == FileDispatcher.RET_EX_LOCK) { + assert shared; + FileLockImpl fli2 = new FileLockImpl(this, position, size, + false); + flt.replace(fli, fli2); + return fli2; + } + return fli; + } finally { + threads.remove(ti); } - if (result == RET_EX_LOCK) { - assert shared; - FileLockImpl fli2 = new FileLockImpl(this, position, size, - false); - flt.replace(fli, fli2); - return fli2; - } - return fli; } void release(FileLockImpl fli) throws IOException { ensureOpen(); - release0(fd, fli.position(), fli.size()); + int ti = threads.add(); + try { + ensureOpen(); + nd.release(fd, fli.position(), fli.size()); + } finally { + threads.remove(ti); + } assert fileLockTable != null; fileLockTable.remove(fli); } - - // -- File lock support -- - - /** - * A table of FileLocks. - */ - private interface FileLockTable { - /** - * Adds a file lock to the table. - * - * @throws OverlappingFileLockException if the file lock overlaps - * with an existing file lock in the table - */ - void add(FileLock fl) throws OverlappingFileLockException; - - /** - * Remove an existing file lock from the table. - */ - void remove(FileLock fl); - - /** - * An implementation of this interface releases a given file lock. - * Used with removeAll. - */ - interface Releaser { - void release(FileLock fl) throws IOException; - } - - /** - * Removes all file locks from the table. - *

- * The Releaser#release method is invoked for each file lock before - * it is removed. - * - * @throws IOException if the release method throws IOException - */ - void removeAll(Releaser r) throws IOException; - - /** - * Replaces an existing file lock in the table. - */ - void replace(FileLock fl1, FileLock fl2); - } + // -- File lock support -- /** * A simple file lock table that maintains a list of FileLocks obtained by a * FileChannel. Use to get 1.4/5.0 behaviour. */ - private static class SimpleFileLockTable implements FileLockTable { + private static class SimpleFileLockTable extends FileLockTable { // synchronize on list for access private List lockList = new ArrayList(2); @@ -1083,207 +1039,8 @@ public class FileChannelImpl } } - /** - * A weak reference to a FileLock. - *

- * SharedFileLockTable uses a list of file lock references to avoid keeping the - * FileLock (and FileChannel) alive. - */ - private static class FileLockReference extends WeakReference { - private FileKey fileKey; - - FileLockReference(FileLock referent, - ReferenceQueue queue, - FileKey key) { - super(referent, queue); - this.fileKey = key; - } - - private FileKey fileKey() { - return fileKey; - } - } - - /** - * A file lock table that is over a system-wide map of all file locks. - */ - private static class SharedFileLockTable implements FileLockTable { - // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey. - // The map value is a list of file locks represented by FileLockReferences. - // All access to the list must be synchronized on the list. - private static ConcurrentHashMap> lockMap = - new ConcurrentHashMap>(); - - // reference queue for cleared refs - private static ReferenceQueue queue = new ReferenceQueue(); - - // the enclosing file channel - private FileChannelImpl fci; - - // File key for the file that this channel is connected to - private FileKey fileKey; - - public SharedFileLockTable(FileChannelImpl fci) { - this.fci = fci; - this.fileKey = FileKey.create(fci.fd); - } - - public void add(FileLock fl) throws OverlappingFileLockException { - ArrayList list = lockMap.get(fileKey); - - for (;;) { - - // The key isn't in the map so we try to create it atomically - if (list == null) { - list = new ArrayList(2); - ArrayList prev; - synchronized (list) { - prev = lockMap.putIfAbsent(fileKey, list); - if (prev == null) { - // we successfully created the key so we add the file lock - list.add(new FileLockReference(fl, queue, fileKey)); - break; - } - } - // someone else got there first - list = prev; - } - - // There is already a key. It is possible that some other thread - // is removing it so we re-fetch the value from the map. If it - // hasn't changed then we check the list for overlapping locks - // and add the new lock to the list. - synchronized (list) { - ArrayList current = lockMap.get(fileKey); - if (list == current) { - checkList(list, fl.position(), fl.size()); - list.add(new FileLockReference(fl, queue, fileKey)); - break; - } - list = current; - } - - } - - // process any stale entries pending in the reference queue - removeStaleEntries(); - } - - private void removeKeyIfEmpty(FileKey fk, ArrayList list) { - assert Thread.holdsLock(list); - assert lockMap.get(fk) == list; - if (list.isEmpty()) { - lockMap.remove(fk); - } - } - - public void remove(FileLock fl) { - assert fl != null; - - // the lock must exist so the list of locks must be present - ArrayList list = lockMap.get(fileKey); - assert list != null; - - synchronized (list) { - int index = 0; - while (index < list.size()) { - FileLockReference ref = list.get(index); - FileLock lock = ref.get(); - if (lock == fl) { - assert (lock != null) && (lock.channel() == fci); - ref.clear(); - list.remove(index); - break; - } - index++; - } - } - } - - public void removeAll(Releaser releaser) throws IOException { - ArrayList list = lockMap.get(fileKey); - if (list != null) { - synchronized (list) { - int index = 0; - while (index < list.size()) { - FileLockReference ref = list.get(index); - FileLock lock = ref.get(); - - // remove locks obtained by this channel - if (lock != null && lock.channel() == fci) { - // invoke the releaser to invalidate/release the lock - releaser.release(lock); - - // remove the lock from the list - ref.clear(); - list.remove(index); - } else { - index++; - } - } - - // once the lock list is empty we remove it from the map - removeKeyIfEmpty(fileKey, list); - } - } - } - - public void replace(FileLock fromLock, FileLock toLock) { - // the lock must exist so there must be a list - ArrayList list = lockMap.get(fileKey); - assert list != null; - - synchronized (list) { - for (int index=0; index list, long position, long size) - throws OverlappingFileLockException - { - assert Thread.holdsLock(list); - for (FileLockReference ref: list) { - FileLock fl = ref.get(); - if (fl != null && fl.overlaps(position, size)) - throw new OverlappingFileLockException(); - } - } - - // Process the reference queue - private void removeStaleEntries() { - FileLockReference ref; - while ((ref = (FileLockReference)queue.poll()) != null) { - FileKey fk = ref.fileKey(); - ArrayList list = lockMap.get(fk); - if (list != null) { - synchronized (list) { - list.remove(ref); - removeKeyIfEmpty(fk, list); - } - } - } - } - } - // -- Native methods -- - // Grabs a file lock - native int lock0(FileDescriptor fd, boolean blocking, long pos, long size, - boolean shared) throws IOException; - - // Releases a file lock - native void release0(FileDescriptor fd, long pos, long size) - throws IOException; - // Creates a new mapping private native long map0(int prot, long position, long length) throws IOException; @@ -1291,12 +1048,6 @@ public class FileChannelImpl // Removes an existing mapping private static native int unmap0(long address, long length); - // Forces output to device - private native int force0(FileDescriptor fd, boolean metaData); - - // Truncates a file - private native int truncate0(FileDescriptor fd, long size); - // Transfers from src to dst, or returns -2 if kernel can't do that private native long transferTo0(int src, long position, long count, int dst); @@ -1305,18 +1056,13 @@ public class FileChannelImpl // otherwise the position is set to offset private native long position0(FileDescriptor fd, long offset); - // Reports this file's size - private native long size0(FileDescriptor fd); - // Caches fieldIDs private static native long initIDs(); static { Util.load(); allocationGranularity = initIDs(); - nd = new FileDispatcher(); - isAMappedBufferField = Reflect.lookupField("java.nio.MappedByteBuffer", - "isAMappedBuffer"); + nd = new FileDispatcherImpl(); } } diff --git a/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java b/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java new file mode 100644 index 00000000000..9f8a0f79e4f --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/FileDispatcher.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.io.*; + +abstract class FileDispatcher extends NativeDispatcher { + + public static final int NO_LOCK = -1; // Failed to lock + public static final int LOCKED = 0; // Obtained requested lock + public static final int RET_EX_LOCK = 1; // Obtained exclusive lock + public static final int INTERRUPTED = 2; // Request interrupted + + abstract int force(FileDescriptor fd, boolean metaData) throws IOException; + + abstract int truncate(FileDescriptor fd, long size) throws IOException; + + abstract long size(FileDescriptor fd) throws IOException; + + abstract int lock(FileDescriptor fd, boolean blocking, long pos, long size, + boolean shared) throws IOException; + + abstract void release(FileDescriptor fd, long pos, long size) + throws IOException; +} diff --git a/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java b/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java index 721faf1a0fa..9efd1532b50 100644 --- a/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/FileLockImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,7 @@ package sun.nio.ch; import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.FileLock; -import java.nio.channels.FileChannel; +import java.nio.channels.*; public class FileLockImpl extends FileLock @@ -41,6 +39,12 @@ public class FileLockImpl this.valid = true; } + FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared) + { + super(channel, position, size, shared); + this.valid = true; + } + public synchronized boolean isValid() { return valid; } @@ -50,10 +54,15 @@ public class FileLockImpl } public synchronized void release() throws IOException { - if (!channel().isOpen()) + Channel ch = acquiredBy(); + if (!ch.isOpen()) throw new ClosedChannelException(); if (valid) { - ((FileChannelImpl)channel()).release(this); + if (ch instanceof FileChannelImpl) + ((FileChannelImpl)ch).release(this); + else if (ch instanceof AsynchronousFileChannelImpl) + ((AsynchronousFileChannelImpl)ch).release(this); + else throw new AssertionError(); valid = false; } } diff --git a/jdk/src/share/classes/sun/nio/ch/FileLockTable.java b/jdk/src/share/classes/sun/nio/ch/FileLockTable.java new file mode 100644 index 00000000000..137ab88872b --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/FileLockTable.java @@ -0,0 +1,282 @@ +/* + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.lang.ref.*; +import java.io.FileDescriptor; +import java.io.IOException; + +abstract class FileLockTable { + protected FileLockTable() { + } + + /** + * Creates and returns a file lock table for a channel that is connected to + * the a system-wide map of all file locks for the Java virtual machine. + */ + public static FileLockTable newSharedFileLockTable(Channel channel, + FileDescriptor fd) + throws IOException + { + return new SharedFileLockTable(channel, fd); + } + + /** + * Adds a file lock to the table. + * + * @throws OverlappingFileLockException if the file lock overlaps + * with an existing file lock in the table + */ + public abstract void add(FileLock fl) throws OverlappingFileLockException; + + /** + * Remove an existing file lock from the table. + */ + public abstract void remove(FileLock fl); + + /** + * An implementation of this interface releases a given file lock. + * Used with removeAll. + */ + public abstract interface Releaser { + void release(FileLock fl) throws IOException; + } + + /** + * Removes all file locks from the table. + *

+ * The Releaser#release method is invoked for each file lock before + * it is removed. + * + * @throws IOException if the release method throws IOException + */ + public abstract void removeAll(Releaser r) throws IOException; + + /** + * Replaces an existing file lock in the table. + */ + public abstract void replace(FileLock fl1, FileLock fl2); +} + + +/** + * A file lock table that is over a system-wide map of all file locks. + */ +class SharedFileLockTable extends FileLockTable { + + /** + * A weak reference to a FileLock. + *

+ * SharedFileLockTable uses a list of file lock references to avoid keeping the + * FileLock (and FileChannel) alive. + */ + private static class FileLockReference extends WeakReference { + private FileKey fileKey; + + FileLockReference(FileLock referent, + ReferenceQueue queue, + FileKey key) { + super(referent, queue); + this.fileKey = key; + } + + FileKey fileKey() { + return fileKey; + } + } + + // The system-wide map is a ConcurrentHashMap that is keyed on the FileKey. + // The map value is a list of file locks represented by FileLockReferences. + // All access to the list must be synchronized on the list. + private static ConcurrentHashMap> lockMap = + new ConcurrentHashMap>(); + + // reference queue for cleared refs + private static ReferenceQueue queue = new ReferenceQueue(); + + // The connection to which this table is connected + private final Channel channel; + + // File key for the file that this channel is connected to + private final FileKey fileKey; + + SharedFileLockTable(Channel channel, FileDescriptor fd) throws IOException { + this.channel = channel; + this.fileKey = FileKey.create(fd); + } + + @Override + public void add(FileLock fl) throws OverlappingFileLockException { + List list = lockMap.get(fileKey); + + for (;;) { + + // The key isn't in the map so we try to create it atomically + if (list == null) { + list = new ArrayList(2); + List prev; + synchronized (list) { + prev = lockMap.putIfAbsent(fileKey, list); + if (prev == null) { + // we successfully created the key so we add the file lock + list.add(new FileLockReference(fl, queue, fileKey)); + break; + } + } + // someone else got there first + list = prev; + } + + // There is already a key. It is possible that some other thread + // is removing it so we re-fetch the value from the map. If it + // hasn't changed then we check the list for overlapping locks + // and add the new lock to the list. + synchronized (list) { + List current = lockMap.get(fileKey); + if (list == current) { + checkList(list, fl.position(), fl.size()); + list.add(new FileLockReference(fl, queue, fileKey)); + break; + } + list = current; + } + + } + + // process any stale entries pending in the reference queue + removeStaleEntries(); + } + + private void removeKeyIfEmpty(FileKey fk, List list) { + assert Thread.holdsLock(list); + assert lockMap.get(fk) == list; + if (list.isEmpty()) { + lockMap.remove(fk); + } + } + + @Override + public void remove(FileLock fl) { + assert fl != null; + + // the lock must exist so the list of locks must be present + List list = lockMap.get(fileKey); + if (list == null) return; + + synchronized (list) { + int index = 0; + while (index < list.size()) { + FileLockReference ref = list.get(index); + FileLock lock = ref.get(); + if (lock == fl) { + assert (lock != null) && (lock.channel() == channel); + ref.clear(); + list.remove(index); + break; + } + index++; + } + } + } + + @Override + public void removeAll(Releaser releaser) throws IOException { + List list = lockMap.get(fileKey); + if (list != null) { + synchronized (list) { + int index = 0; + while (index < list.size()) { + FileLockReference ref = list.get(index); + FileLock lock = ref.get(); + + // remove locks obtained by this channel + if (lock != null && lock.channel() == channel) { + // invoke the releaser to invalidate/release the lock + releaser.release(lock); + + // remove the lock from the list + ref.clear(); + list.remove(index); + } else { + index++; + } + } + + // once the lock list is empty we remove it from the map + removeKeyIfEmpty(fileKey, list); + } + } + } + + @Override + public void replace(FileLock fromLock, FileLock toLock) { + // the lock must exist so there must be a list + List list = lockMap.get(fileKey); + assert list != null; + + synchronized (list) { + for (int index=0; index list, long position, long size) + throws OverlappingFileLockException + { + assert Thread.holdsLock(list); + for (FileLockReference ref: list) { + FileLock fl = ref.get(); + if (fl != null && fl.overlaps(position, size)) + throw new OverlappingFileLockException(); + } + } + + // Process the reference queue + private void removeStaleEntries() { + FileLockReference ref; + while ((ref = (FileLockReference)queue.poll()) != null) { + FileKey fk = ref.fileKey(); + List list = lockMap.get(fk); + if (list != null) { + synchronized (list) { + list.remove(ref); + removeKeyIfEmpty(fk, list); + } + } + } + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/Groupable.java b/jdk/src/share/classes/sun/nio/ch/Groupable.java new file mode 100644 index 00000000000..b1760152b37 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/Groupable.java @@ -0,0 +1,35 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +/** + * Implemented by asynchronous channels that can be associated with an + * asynchronous channel group. + */ + +interface Groupable { + AsynchronousChannelGroupImpl group(); +} diff --git a/jdk/src/share/classes/sun/nio/ch/IOUtil.java b/jdk/src/share/classes/sun/nio/ch/IOUtil.java index f57b724b562..8d5bb13a2ee 100644 --- a/jdk/src/share/classes/sun/nio/ch/IOUtil.java +++ b/jdk/src/share/classes/sun/nio/ch/IOUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,7 @@ package sun.nio.ch; import java.io.FileDescriptor; import java.io.IOException; -import java.net.*; import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.nio.channels.spi.*; /** @@ -47,7 +44,6 @@ class IOUtil { */ private static int remaining(ByteBuffer[] bufs) { int numBufs = bufs.length; - boolean remaining = false; for (int i=0; i= len) { - bytesWritten -= len; - int newPosition = pos + len; - nextBuffer.position(newPosition); - } else { // Buffers not completely filled - if (bytesWritten > 0) { - assert(pos + bytesWritten < (long)Integer.MAX_VALUE); - int newPosition = (int)(pos + bytesWritten); - nextBuffer.position(newPosition); + ByteBuffer bb = Util.getTemporaryDirectBuffer(rem); + shadow[i] = bb; + // Leave slow buffer position untouched; it will be updated + // after we see how many bytes were really written out + bb.put(bufs[i]); + bufs[i].position(pos); + bb.flip(); + } else { + shadow[i] = bufs[i]; + } + } + + IOVecWrapper vec = null; + long bytesWritten = 0; + try { + // Create a native iovec array + vec= new IOVecWrapper(numBufs); + + // Fill in the iovec array with appropriate data + for (int i=0; i= len) { + bytesWritten -= len; + int newPosition = pos + len; + nextBuffer.position(newPosition); + } else { // Buffers not completely filled + if (bytesWritten > 0) { + assert(pos + bytesWritten < (long)Integer.MAX_VALUE); + int newPosition = (int)(pos + bytesWritten); + nextBuffer.position(newPosition); + } + break; + } + } + return returnVal; + } finally { + // return any substituted buffers to cache + for (int i=0; i= len) { - bytesRead -= len; - int newPosition = pos + len; - nextBuffer.position(newPosition); - } else { // Buffers not completely filled - if (bytesRead > 0) { - assert(pos + bytesRead < (long)Integer.MAX_VALUE); - int newPosition = (int)(pos + bytesRead); + // Note: should this have been cached from above? + int pos = nextBuffer.position(); + int len = nextBuffer.remaining(); + if (bytesRead >= len) { + bytesRead -= len; + int newPosition = pos + len; nextBuffer.position(newPosition); + } else { // Buffers not completely filled + if (bytesRead > 0) { + assert(pos + bytesRead < (long)Integer.MAX_VALUE); + int newPosition = (int)(pos + bytesRead); + nextBuffer.position(newPosition); + } + break; + } + } + + // Put results from shadow into the slow buffers + if (usingSlowBuffers) { + for (int i=0; i myGroupAndInvokeCount = + new ThreadLocal() { + @Override protected GroupAndInvokeCount initialValue() { + return null; + } + }; + + /** + * Binds this thread to the given group + */ + static void bindToGroup(AsynchronousChannelGroupImpl group) { + myGroupAndInvokeCount.set(new GroupAndInvokeCount(group)); + } + + /** + * Returns the GroupAndInvokeCount object for this thread. + */ + static GroupAndInvokeCount getGroupAndInvokeCount() { + return myGroupAndInvokeCount.get(); + } + + /** + * Returns true if the current thread is in a channel group's thread pool + */ + static boolean isBoundToAnyGroup() { + return myGroupAndInvokeCount.get() != null; + } + + /** + * Returns true if the current thread is in the given channel's thread + * pool and we haven't exceeded the maximum number of handler frames on + * the stack. + */ + static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, + AsynchronousChannelGroupImpl group) + { + if ((myGroupAndInvokeCount != null) && + (myGroupAndInvokeCount.group() == group) && + (myGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount)) + { + return true; + } + return false; + } + + /** + * Invoke handler without checking the thread identity or number of handlers + * on the thread stack. + */ + @SuppressWarnings("unchecked") + static void invokeUnchecked(CompletionHandler handler, + AbstractFuture result) + { + if (handler != null && !result.isCancelled()) { + Throwable exc = result.exception(); + if (exc == null) { + handler.completed(result.value(), result.attachment()); + } else { + handler.failed(exc, result.attachment()); + } + + // clear interrupt + Thread.interrupted(); + } + } + + + /** + * Invoke handler after incrementing the invoke count. + */ + static void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, + CompletionHandler handler, + AbstractFuture result) + { + myGroupAndInvokeCount.incrementInvokeCount(); + invokeUnchecked(handler, result); + } + + /** + * Invokes the handler. If the current thread is in the channel group's + * thread pool then the handler is invoked directly, otherwise it is + * invoked indirectly. + */ + static void invoke(CompletionHandler handler, + AbstractFuture result) + { + if (handler != null) { + boolean invokeDirect = false; + boolean identityOkay = false; + GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); + if (thisGroupAndInvokeCount != null) { + AsynchronousChannel channel = result.channel(); + if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group())) + identityOkay = true; + if (identityOkay && + (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount)) + { + // group match + invokeDirect = true; + } + } + if (invokeDirect) { + thisGroupAndInvokeCount.incrementInvokeCount(); + invokeUnchecked(handler, result); + } else { + try { + invokeIndirectly(handler, result); + } catch (RejectedExecutionException ree) { + // channel group shutdown; fallback to invoking directly + // if the current thread has the right identity. + if (identityOkay) { + invokeUnchecked(handler, result); + } else { + throw new ShutdownChannelGroupException(); + } + } + } + } + } + + /** + * Invokes the handler "indirectly" in the channel group's thread pool. + */ + static void invokeIndirectly(final CompletionHandler handler, + final AbstractFuture result) + { + if (handler != null) { + AsynchronousChannel channel = result.channel(); + try { + ((Groupable)channel).group().executeOnPooledThread(new Runnable() { + public void run() { + GroupAndInvokeCount thisGroupAndInvokeCount = + myGroupAndInvokeCount.get(); + if (thisGroupAndInvokeCount != null) + thisGroupAndInvokeCount.setInvokeCount(1); + invokeUnchecked(handler, result); + } + }); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + } + } + + /** + * Invokes the handler "indirectly" in the given Executor + */ + static void invokeIndirectly(final CompletionHandler handler, + final AbstractFuture result, + Executor executor) + { + if (handler != null) { + try { + executor.execute(new Runnable() { + public void run() { + invokeUnchecked(handler, result); + } + }); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + } + } + + /** + * Invokes the given task on the thread pool associated with the given + * channel. If the current thread is in the thread pool then the task is + * invoked directly. + */ + static void invokeOnThreadInThreadPool(Groupable channel, + Runnable task) + { + boolean invokeDirect; + GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); + AsynchronousChannelGroupImpl targetGroup = channel.group(); + if (thisGroupAndInvokeCount == null) { + invokeDirect = false; + } else { + invokeDirect = (thisGroupAndInvokeCount.group == targetGroup); + } + try { + if (invokeDirect) { + task.run(); + } else { + targetGroup.executeOnPooledThread(task); + } + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java b/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java index 687f79c0095..0089ffd4440 100644 --- a/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/MembershipKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,7 @@ class MembershipKeyImpl this.sourceAddress = sourceAddress; } - int group() { + int groupAddress() { return groupAddress; } @@ -120,7 +120,7 @@ class MembershipKeyImpl this.sourceAddress = sourceAddress; } - byte[] group() { + byte[] groupAddress() { return groupAddress; } @@ -142,28 +142,28 @@ class MembershipKeyImpl valid = false; } - public void drop() throws IOException { + public void drop() { // delegate to channel ((DatagramChannelImpl)ch).drop(this); } @Override - public MulticastChannel getChannel() { + public MulticastChannel channel() { return ch; } @Override - public InetAddress getGroup() { + public InetAddress group() { return group; } @Override - public NetworkInterface getNetworkInterface() { + public NetworkInterface networkInterface() { return interf; } @Override - public InetAddress getSourceAddress() { + public InetAddress sourceAddress() { return source; } @@ -191,9 +191,7 @@ class MembershipKeyImpl } @Override - public MembershipKey unblock(InetAddress toUnblock) - throws IOException - { + public MembershipKey unblock(InetAddress toUnblock) { synchronized (stateLock) { if ((blockedSet == null) || !blockedSet.contains(toUnblock)) throw new IllegalStateException("not blocked"); diff --git a/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java b/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java index 5a2a8ef7447..fc90be39d16 100644 --- a/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java +++ b/jdk/src/share/classes/sun/nio/ch/MembershipRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,20 +55,20 @@ class MembershipRegistry { List keys = groups.get(group); if (keys != null) { for (MembershipKeyImpl key: keys) { - if (key.getNetworkInterface().equals(interf)) { + if (key.networkInterface().equals(interf)) { // already a member to receive all packets so return // existing key or detect conflict if (source == null) { - if (key.getSourceAddress() == null) + if (key.sourceAddress() == null) return key; throw new IllegalStateException("Already a member to receive all packets"); } // already have source-specific membership so return key // or detect conflict - if (key.getSourceAddress() == null) + if (key.sourceAddress() == null) throw new IllegalStateException("Already have source-specific membership"); - if (source.equals(key.getSourceAddress())) + if (source.equals(key.sourceAddress())) return key; } } @@ -81,7 +81,7 @@ class MembershipRegistry { * Add membership to the registry, returning a new membership key. */ void add(MembershipKeyImpl key) { - InetAddress group = key.getGroup(); + InetAddress group = key.group(); List keys; if (groups == null) { groups = new HashMap>(); @@ -100,7 +100,7 @@ class MembershipRegistry { * Remove a key from the registry */ void remove(MembershipKeyImpl key) { - InetAddress group = key.getGroup(); + InetAddress group = key.group(); List keys = groups.get(group); if (keys != null) { Iterator i = keys.iterator(); @@ -120,9 +120,11 @@ class MembershipRegistry { * Invalidate all keys in the registry */ void invalidateAll() { - for (InetAddress group: groups.keySet()) { - for (MembershipKeyImpl key: groups.get(group)) { - key.invalidate(); + if (groups != null) { + for (InetAddress group: groups.keySet()) { + for (MembershipKeyImpl key: groups.get(group)) { + key.invalidate(); + } } } } diff --git a/jdk/src/share/classes/sun/nio/ch/NativeThreadSet.java b/jdk/src/share/classes/sun/nio/ch/NativeThreadSet.java index 612befcbbd0..a009541d97c 100644 --- a/jdk/src/share/classes/sun/nio/ch/NativeThreadSet.java +++ b/jdk/src/share/classes/sun/nio/ch/NativeThreadSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ class NativeThreadSet { private long[] elts; private int used = 0; + private boolean waitingToEmpty; NativeThreadSet(int n) { elts = new long[n]; @@ -75,12 +76,14 @@ class NativeThreadSet { synchronized (this) { elts[i] = 0; used--; + if (used == 0 && waitingToEmpty) + notifyAll(); } } // Signals all threads in this set. // - void signal() { + void signalAndWait() { synchronized (this) { int u = used; int n = elts.length; @@ -92,7 +95,12 @@ class NativeThreadSet { if (--u == 0) break; } + waitingToEmpty = true; + while (used > 0) { + try { + wait(); + } catch (InterruptedException ignore) { } + } } } - } diff --git a/jdk/src/share/classes/sun/nio/ch/Net.java b/jdk/src/share/classes/sun/nio/ch/Net.java index ba0ba0bdcde..f910c5db05e 100644 --- a/jdk/src/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/share/classes/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,7 +207,7 @@ class Net { // package-private // -- Socket options static void setSocketOption(FileDescriptor fd, ProtocolFamily family, - SocketOption name, Object value) + SocketOption name, Object value) throws IOException { if (value == null) @@ -262,7 +262,7 @@ class Net { // package-private } static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, - SocketOption name) + SocketOption name) throws IOException { Class type = name.type(); diff --git a/jdk/src/share/classes/sun/nio/ch/OptionKey.java b/jdk/src/share/classes/sun/nio/ch/OptionKey.java index 70ba8a6fa71..88474533587 100644 --- a/jdk/src/share/classes/sun/nio/ch/OptionKey.java +++ b/jdk/src/share/classes/sun/nio/ch/OptionKey.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/jdk/src/share/classes/sun/nio/ch/PendingFuture.java b/jdk/src/share/classes/sun/nio/ch/PendingFuture.java new file mode 100644 index 00000000000..d88cf233a82 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/PendingFuture.java @@ -0,0 +1,257 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.*; +import java.io.IOException; + +/** + * A Future for a pending I/O operation. A PendingFuture allows for the + * attachment of an additional arbitrary context object and a timer task. + */ + +final class PendingFuture + extends AbstractFuture +{ + private static final CancellationException CANCELLED = + new CancellationException(); + + private final CompletionHandler handler; + + // true if result (or exception) is available + private volatile boolean haveResult; + private volatile V result; + private volatile Throwable exc; + + // latch for waiting (created lazily if needed) + private CountDownLatch latch; + + // optional timer task that is cancelled when result becomes available + private Future timeoutTask; + + // optional context object + private volatile Object context; + + + PendingFuture(AsynchronousChannel channel, + CompletionHandler handler, + A attachment, + Object context) + { + super(channel, attachment); + this.handler = handler; + this.context = context; + } + + PendingFuture(AsynchronousChannel channel, + CompletionHandler handler, + A attachment) + { + super(channel, attachment); + this.handler = handler; + } + + CompletionHandler handler() { + return handler; + } + + void setContext(Object context) { + this.context = context; + } + + Object getContext() { + return context; + } + + void setTimeoutTask(Future task) { + synchronized (this) { + if (haveResult) { + task.cancel(false); + } else { + this.timeoutTask = task; + } + } + } + + // creates latch if required; return true if caller needs to wait + private boolean prepareForWait() { + synchronized (this) { + if (haveResult) { + return false; + } else { + if (latch == null) + latch = new CountDownLatch(1); + return true; + } + } + } + + /** + * Sets the result, or a no-op if the result or exception is already set. + */ + boolean setResult(V res) { + synchronized (this) { + if (haveResult) + return false; + result = res; + haveResult = true; + if (timeoutTask != null) + timeoutTask.cancel(false); + if (latch != null) + latch.countDown(); + return true; + } + } + + /** + * Sets the result, or a no-op if the result or exception is already set. + */ + boolean setFailure(Throwable x) { + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + synchronized (this) { + if (haveResult) + return false; + exc = x; + haveResult = true; + if (timeoutTask != null) + timeoutTask.cancel(false); + if (latch != null) + latch.countDown(); + return true; + } + } + + @Override + public V get() throws ExecutionException, InterruptedException { + if (!haveResult) { + boolean needToWait = prepareForWait(); + if (needToWait) + latch.await(); + } + if (exc != null) { + if (exc == CANCELLED) + throw new CancellationException(); + throw new ExecutionException(exc); + } + return result; + } + + @Override + public V get(long timeout, TimeUnit unit) + throws ExecutionException, InterruptedException, TimeoutException + { + if (!haveResult) { + boolean needToWait = prepareForWait(); + if (needToWait) + if (!latch.await(timeout, unit)) throw new TimeoutException(); + } + if (exc != null) { + if (exc == CANCELLED) + throw new CancellationException(); + throw new ExecutionException(exc); + } + return result; + } + + @Override + Throwable exception() { + return (exc != CANCELLED) ? exc : null; + } + + @Override + V value() { + return result; + } + + @Override + public boolean isCancelled() { + return (exc == CANCELLED); + } + + @Override + public boolean isDone() { + return haveResult; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + synchronized (this) { + if (haveResult) + return false; // already completed + + // A shutdown of the channel group will close all channels and + // shutdown the executor. To ensure that the completion handler + // is executed we queue the task while holding the lock. + if (handler != null) { + prepareForWait(); + Runnable cancelTask = new Runnable() { + public void run() { + while (!haveResult) { + try { + latch.await(); + } catch (InterruptedException ignore) { } + } + handler.cancelled(attachment()); + } + }; + AsynchronousChannel ch = channel(); + if (ch instanceof Groupable) { + ((Groupable)ch).group().executeOnPooledThread(cancelTask); + } else { + if (ch instanceof AsynchronousFileChannelImpl) { + ((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask); + } else { + throw new AssertionError("Should not get here"); + } + } + } + + // notify channel + if (channel() instanceof Cancellable) + ((Cancellable)channel()).onCancel(this); + + // set result and cancel timer + exc = CANCELLED; + haveResult = true; + if (timeoutTask != null) + timeoutTask.cancel(false); + } + + // close channel if forceful cancel + if (mayInterruptIfRunning) { + try { + channel().close(); + } catch (IOException ignore) { } + } + + // release waiters (this also releases the invoker) + if (latch != null) + latch.countDown(); + return true; + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/Reflect.java b/jdk/src/share/classes/sun/nio/ch/Reflect.java index 913357fcd9e..cc4716eb1ad 100644 --- a/jdk/src/share/classes/sun/nio/ch/Reflect.java +++ b/jdk/src/share/classes/sun/nio/ch/Reflect.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ class Reflect { // package-private { try { Class cl = Class.forName(className); - Constructor c = cl.getDeclaredConstructor(paramTypes); + Constructor c = cl.getDeclaredConstructor(paramTypes); setAccessible(c); return c; } catch (ClassNotFoundException x) { @@ -79,7 +79,7 @@ class Reflect { // package-private static Method lookupMethod(String className, String methodName, - Class[] paramTypes) + Class... paramTypes) { try { Class cl = Class.forName(className); diff --git a/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index fd532980b0b..d509198aee2 100644 --- a/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,9 @@ package sun.nio.ch; import java.io.FileDescriptor; import java.io.IOException; -import java.lang.reflect.*; import java.net.*; import java.nio.channels.*; import java.nio.channels.spi.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.*; @@ -111,19 +108,19 @@ class ServerSocketChannelImpl public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) - return null; + throw new ClosedChannelException(); return localAddress; } } @Override - public ServerSocketChannel setOption(SocketOption name, Object value) + public ServerSocketChannel setOption(SocketOption name, T value) throws IOException { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { if (!isOpen()) @@ -142,8 +139,8 @@ class ServerSocketChannelImpl { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { if (!isOpen()) @@ -154,7 +151,7 @@ class ServerSocketChannelImpl } } - private static class LazyInitialization { + private static class DefaultOptionsHolder { static final Set> defaultOptions = defaultOptions(); private static Set> defaultOptions() { @@ -166,8 +163,8 @@ class ServerSocketChannelImpl } @Override - public final Set> options() { - return LazyInitialization.defaultOptions; + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; } public boolean isBound() { diff --git a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java new file mode 100644 index 00000000000..47c3b2abd29 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java @@ -0,0 +1,612 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +/** + * A prototype implementation of AsynchronousDatagramChannel, used to aid + * test and spec development. + */ + +class SimpleAsynchronousDatagramChannelImpl + extends AsynchronousDatagramChannel implements Groupable, Cancellable +{ + private final DatagramChannel dc; + private final AsynchronousChannelGroupImpl group; + private final Object attachKey; + private boolean closed; + + // used to coordinate timed and blocking reads + private final Object readLock = new Object(); + + // channel blocking mode (requires readLock) + private boolean isBlocking = true; + + // number of blocking readers (requires readLock) + private int blockingReaderCount; + + // true if timed read attempted while blocking read in progress (requires readLock) + private boolean transitionToNonBlocking; + + // true if a blocking read is cancelled (requires readLock) + private boolean blockingReadKilledByCancel; + + // temporary Selectors used by timed reads (requires readLock) + private Selector firstReader; + private Set otherReaders; + + SimpleAsynchronousDatagramChannelImpl(ProtocolFamily family, + AsynchronousChannelGroupImpl group) + throws IOException + { + super(group.provider()); + this.dc = (family == null) ? + DatagramChannel.open() : DatagramChannel.open(family); + this.group = group; + + // attach this channel to the group as foreign channel + boolean registered = false; + try { + if (!(dc instanceof DatagramChannelImpl)) + throw new UnsupportedOperationException(); + attachKey = group + .attachForeignChannel(this, ((DatagramChannelImpl)dc).getFD()); + registered = true; + } finally { + if (!registered) + dc.close(); + } + } + + // throws RuntimeException if blocking read has been cancelled + private void ensureBlockingReadNotKilled() { + assert Thread.holdsLock(readLock); + if (blockingReadKilledByCancel) + throw new RuntimeException("Reading not allowed due to cancellation"); + } + + // invoke prior to non-timed read/receive + private void beginNoTimeoutRead() { + synchronized (readLock) { + ensureBlockingReadNotKilled(); + if (isBlocking) + blockingReaderCount++; + } + } + + // invoke after non-timed read/receive has completed + private void endNoTimeoutRead() { + synchronized (readLock) { + if (isBlocking) { + if (--blockingReaderCount == 0 && transitionToNonBlocking) { + // notify any threads waiting to make channel non-blocking + readLock.notifyAll(); + } + } + } + } + + // invoke prior to timed read + // returns the timeout remaining + private long prepareForTimedRead(PendingFuture result, long timeout) + throws IOException + { + synchronized (readLock) { + ensureBlockingReadNotKilled(); + if (isBlocking) { + transitionToNonBlocking = true; + while (blockingReaderCount > 0 && + timeout > 0L && + !result.isCancelled()) + { + long st = System.currentTimeMillis(); + try { + readLock.wait(timeout); + } catch (InterruptedException e) { } + timeout -= System.currentTimeMillis() - st; + } + if (blockingReaderCount == 0) { + // re-check that blocked read wasn't cancelled + ensureBlockingReadNotKilled(); + // no blocking reads so change channel to non-blocking + dc.configureBlocking(false); + isBlocking = false; + } + } + return timeout; + } + } + + // returns a temporary Selector + private Selector getSelector() throws IOException { + Selector sel = Util.getTemporarySelector(dc); + synchronized (readLock) { + if (firstReader == null) { + firstReader = sel; + } else { + if (otherReaders == null) + otherReaders = new HashSet(); + otherReaders.add(sel); + } + } + return sel; + } + + // releases a temporary Selector + private void releaseSelector(Selector sel) throws IOException { + synchronized (readLock) { + if (firstReader == sel) { + firstReader = null; + } else { + otherReaders.remove(sel); + } + } + Util.releaseTemporarySelector(sel); + } + + // wakeup all Selectors currently in use + private void wakeupSelectors() { + synchronized (readLock) { + if (firstReader != null) + firstReader.wakeup(); + if (otherReaders != null) { + for (Selector sel: otherReaders) { + sel.wakeup(); + } + } + } + } + + @Override + public AsynchronousChannelGroupImpl group() { + return group; + } + + @Override + public boolean isOpen() { + return dc.isOpen(); + } + + @Override + public void onCancel(PendingFuture task) { + synchronized (readLock) { + if (blockingReaderCount > 0) { + blockingReadKilledByCancel = true; + readLock.notifyAll(); + return; + } + } + wakeupSelectors(); + } + + @Override + public void close() throws IOException { + synchronized (dc) { + if (closed) + return; + closed = true; + } + // detach from group and close underlying channel + group.detachForeignChannel(attachKey); + dc.close(); + + // wakeup any threads blocked in timed read/receives + wakeupSelectors(); + } + + @Override + public AsynchronousDatagramChannel connect(SocketAddress remote) + throws IOException + { + dc.connect(remote); + return this; + } + + @Override + public AsynchronousDatagramChannel disconnect() throws IOException { + dc.disconnect(); + return this; + } + + private static class WrappedMembershipKey extends MembershipKey { + private final MulticastChannel channel; + private final MembershipKey key; + + WrappedMembershipKey(MulticastChannel channel, MembershipKey key) { + this.channel = channel; + this.key = key; + } + + @Override + public boolean isValid() { + return key.isValid(); + } + + @Override + public void drop() { + key.drop(); + } + + @Override + public MulticastChannel channel() { + return channel; + } + + @Override + public InetAddress group() { + return key.group(); + } + + @Override + public NetworkInterface networkInterface() { + return key.networkInterface(); + } + + @Override + public InetAddress sourceAddress() { + return key.sourceAddress(); + } + + @Override + public MembershipKey block(InetAddress toBlock) throws IOException { + key.block(toBlock); + return this; + } + + @Override + public MembershipKey unblock(InetAddress toUnblock) { + key.unblock(toUnblock); + return this; + } + + @Override + public String toString() { + return key.toString(); + } + } + + @Override + public MembershipKey join(InetAddress group, + NetworkInterface interf) + throws IOException + { + MembershipKey key = ((MulticastChannel)dc).join(group, interf); + return new WrappedMembershipKey(this, key); + } + + @Override + public MembershipKey join(InetAddress group, + NetworkInterface interf, + InetAddress source) + throws IOException + { + MembershipKey key = ((MulticastChannel)dc).join(group, interf, source); + return new WrappedMembershipKey(this, key); + } + + @Override + public Future send(ByteBuffer src, + SocketAddress target, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + if (unit == null) + throw new NullPointerException(); + + CompletedFuture result; + try { + int n = dc.send(src, target); + result = CompletedFuture.withResult(this, n, attachment); + } catch (IOException ioe) { + result = CompletedFuture.withFailure(this, ioe, attachment); + } + Invoker.invoke(handler, result); + return result; + } + + @Override + public Future write(ByteBuffer src, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + if (unit == null) + throw new NullPointerException(); + + CompletedFuture result; + try { + int n = dc.write(src); + result = CompletedFuture.withResult(this, n, attachment); + } catch (IOException ioe) { + result = CompletedFuture.withFailure(this, ioe, attachment); + } + Invoker.invoke(handler, result); + return result; + } + + /** + * Receive into the given buffer with privileges enabled and restricted by + * the given AccessControlContext (can be null). + */ + private SocketAddress doRestrictedReceive(final ByteBuffer dst, + AccessControlContext acc) + throws IOException + { + if (acc == null) { + return dc.receive(dst); + } else { + try { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public SocketAddress run() throws IOException { + return dc.receive(dst); + }}, acc); + } catch (PrivilegedActionException pae) { + Exception cause = pae.getException(); + if (cause instanceof SecurityException) + throw (SecurityException)cause; + throw (IOException)cause; + } + } + } + + @Override + public Future receive(final ByteBuffer dst, + final long timeout, + final TimeUnit unit, + A attachment, + final CompletionHandler handler) + { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + if (unit == null) + throw new NullPointerException(); + + // complete immediately if channel closed + if (!isOpen()) { + CompletedFuture result = CompletedFuture.withFailure(this, + new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + final AccessControlContext acc = (System.getSecurityManager() == null) ? + null : AccessController.getContext(); + final PendingFuture result = + new PendingFuture(this, handler, attachment); + Runnable task = new Runnable() { + public void run() { + try { + SocketAddress remote = null; + long to; + if (timeout == 0L) { + beginNoTimeoutRead(); + try { + remote = doRestrictedReceive(dst, acc); + } finally { + endNoTimeoutRead(); + } + to = 0L; + } else { + to = prepareForTimedRead(result, unit.toMillis(timeout)); + if (to <= 0L) + throw new InterruptedByTimeoutException(); + remote = doRestrictedReceive(dst, acc); + } + if (remote == null) { + Selector sel = getSelector(); + SelectionKey sk = null; + try { + sk = dc.register(sel, SelectionKey.OP_READ); + for (;;) { + if (!dc.isOpen()) + throw new AsynchronousCloseException(); + if (result.isCancelled()) + break; + long st = System.currentTimeMillis(); + int ns = sel.select(to); + if (ns > 0) { + remote = doRestrictedReceive(dst, acc); + if (remote != null) + break; + } + sel.selectedKeys().remove(sk); + if (timeout != 0L) { + to -= System.currentTimeMillis() - st; + if (to <= 0) + throw new InterruptedByTimeoutException(); + } + } + } finally { + if (sk != null) + sk.cancel(); + releaseSelector(sel); + } + } + result.setResult(remote); + } catch (Throwable x) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result.setFailure(x); + } + Invoker.invokeUnchecked(handler, result); + } + }; + try { + group.executeOnPooledThread(task); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + return result; + } + + @Override + public Future read(final ByteBuffer dst, + final long timeout, + final TimeUnit unit, + A attachment, + final CompletionHandler handler) + { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (timeout < 0L) + throw new IllegalArgumentException("Negative timeout"); + if (unit == null) + throw new NullPointerException(); + // another thread may disconnect before read is initiated + if (!dc.isConnected()) + throw new NotYetConnectedException(); + + // complete immediately if channel closed + if (!isOpen()) { + CompletedFuture result = CompletedFuture.withFailure(this, + new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + final PendingFuture result = + new PendingFuture(this, handler, attachment); + Runnable task = new Runnable() { + public void run() { + try { + int n = 0; + long to; + if (timeout == 0L) { + beginNoTimeoutRead(); + try { + n = dc.read(dst); + } finally { + endNoTimeoutRead(); + } + to = 0L; + } else { + to = prepareForTimedRead(result, unit.toMillis(timeout)); + if (to <= 0L) + throw new InterruptedByTimeoutException(); + n = dc.read(dst); + } + if (n == 0) { + Selector sel = getSelector(); + SelectionKey sk = null; + try { + sk = dc.register(sel, SelectionKey.OP_READ); + for (;;) { + if (!dc.isOpen()) + throw new AsynchronousCloseException(); + if (result.isCancelled()) + break; + long st = System.currentTimeMillis(); + int ns = sel.select(to); + if (ns > 0) { + if ((n = dc.read(dst)) != 0) + break; + } + sel.selectedKeys().remove(sk); + if (timeout != 0L) { + to -= System.currentTimeMillis() - st; + if (to <= 0) + throw new InterruptedByTimeoutException(); + } + } + } finally { + if (sk != null) + sk.cancel(); + releaseSelector(sel); + } + } + result.setResult(n); + } catch (Throwable x) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result.setFailure(x); + } + Invoker.invokeUnchecked(handler, result); + } + }; + try { + group.executeOnPooledThread(task); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + return result; + } + + @Override + public AsynchronousDatagramChannel bind(SocketAddress local) + throws IOException + { + dc.bind(local); + return this; + } + + @Override + public SocketAddress getLocalAddress() throws IOException { + return dc.getLocalAddress(); + } + + @Override + public AsynchronousDatagramChannel setOption(SocketOption name, T value) + throws IOException + { + dc.setOption(name, value); + return this; + } + + @Override + public T getOption(SocketOption name) throws IOException { + return dc.getOption(name); + } + + @Override + public Set> supportedOptions() { + return dc.supportedOptions(); + } + + @Override + public SocketAddress getRemoteAddress() throws IOException { + return dc.getRemoteAddress(); + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java new file mode 100644 index 00000000000..52fe5a2802f --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java @@ -0,0 +1,426 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * "Portable" implementation of AsynchronousFileChannel for use on operating + * systems that don't support asynchronous file I/O. + */ + +public class SimpleAsynchronousFileChannelImpl + extends AsynchronousFileChannelImpl +{ + // lazy initialization of default thread pool for file I/O + private static class DefaultExecutorHolder { + static final ExecutorService defaultExecutor = + ThreadPool.createDefault().executor(); + } + + // Used to make native read and write calls + private static final FileDispatcher nd = new FileDispatcherImpl(); + + // indicates if the associated thread pool is the default thread pool + private final boolean isDefaultExecutor; + + // Thread-safe set of IDs of native threads, for signalling + private final NativeThreadSet threads = new NativeThreadSet(2); + + + SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj, + boolean reading, + boolean writing, + ExecutorService executor, + boolean isDefaultexecutor) + { + super(fdObj, reading, writing, executor); + this.isDefaultExecutor = isDefaultexecutor; + } + + public static AsynchronousFileChannel open(FileDescriptor fdo, + boolean reading, + boolean writing, + ThreadPool pool) + { + // Executor is either default or based on pool parameters + ExecutorService executor; + boolean isDefaultexecutor; + if (pool == null) { + executor = DefaultExecutorHolder.defaultExecutor; + isDefaultexecutor = true; + } else { + executor = pool.executor(); + isDefaultexecutor = false; + } + return new SimpleAsynchronousFileChannelImpl(fdo, + reading, writing, executor, isDefaultexecutor); + } + + @Override + public void close() throws IOException { + // mark channel as closed + synchronized (fdObj) { + if (closed) + return; // already closed + closed = true; + // from this point on, if another thread invokes the begin() method + // then it will throw ClosedChannelException + } + + // signal any threads blocked on this channel + nd.preClose(fdObj); + threads.signalAndWait(); + + // wait until all async I/O operations have completely gracefully + closeLock.writeLock().lock(); + try { + // do nothing + } finally { + closeLock.writeLock().unlock(); + } + + // Invalidate and release any locks that we still hold + invalidateAllLocks(); + + // close file + nd.close(fdObj); + + // shutdown executor if specific to this channel + if (!isDefaultExecutor) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + executor.shutdown(); + return null; + } + }); + } + } + + @Override + public long size() throws IOException { + int ti = threads.add(); + try { + long n = 0L; + try { + begin(); + do { + n = nd.size(fdObj); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + return n; + } finally { + end(n >= 0L); + } + } finally { + threads.remove(ti); + } + } + + @Override + public AsynchronousFileChannel truncate(long size) throws IOException { + if (size < 0L) + throw new IllegalArgumentException("Negative size"); + if (!writing) + throw new NonWritableChannelException(); + int ti = threads.add(); + try { + long n = 0L; + try { + begin(); + do { + n = nd.size(fdObj); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + + // truncate file if 'size' less than current size + if (size < n && isOpen()) { + do { + n = nd.truncate(fdObj, size); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + } + return this; + } finally { + end(n > 0); + } + } finally { + threads.remove(ti); + } + } + + @Override + public void force(boolean metaData) throws IOException { + int ti = threads.add(); + try { + int n = 0; + try { + begin(); + do { + n = nd.force(fdObj, metaData); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + } finally { + end(n >= 0); + } + } finally { + threads.remove(ti); + } + } + + @Override + public Future lock(final long position, + final long size, + final boolean shared, + A attachment, + final CompletionHandler handler) + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + final FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invokeIndirectly(handler, result, executor); + return result; + } + + final PendingFuture result = + new PendingFuture(this, handler, attachment); + Runnable task = new Runnable() { + public void run() { + int ti = threads.add(); + try { + int n; + try { + begin(); + do { + n = nd.lock(fdObj, true, position, size, shared); + } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); + if (n == FileDispatcher.LOCKED) { + result.setResult(fli); + } else { + if (n != FileDispatcher.INTERRUPTED) + throw new AssertionError(); + throw new AsynchronousCloseException(); + } + } catch (IOException x) { + removeFromFileLockTable(fli); + if (!isOpen()) + x = new AsynchronousCloseException(); + result.setFailure(x); + } finally { + end(); + } + } finally { + threads.remove(ti); + } + Invoker.invokeUnchecked(handler, result); + } + }; + try { + executor.execute(task); + } catch (RejectedExecutionException ree) { + // rollback + removeFromFileLockTable(fli); + throw new ShutdownChannelGroupException(); + } + return result; + } + + @Override + public FileLock tryLock(long position, long size, boolean shared) + throws IOException + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) + throw new ClosedChannelException(); + + int ti = threads.add(); + boolean gotLock = false; + try { + begin(); + int n; + do { + n = nd.lock(fdObj, false, position, size, shared); + } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); + if (n != FileDispatcher.LOCKED) { + if (n == FileDispatcher.NO_LOCK) + return null; // locked by someone else + if (n == FileDispatcher.INTERRUPTED) + throw new AsynchronousCloseException(); + // should not get here + throw new AssertionError(); + } + gotLock = true; + return fli; + } finally { + if (!gotLock) + removeFromFileLockTable(fli); + end(); + threads.remove(ti); + } + } + + @Override + void release(FileLockImpl fli) throws IOException { + try { + begin(); + nd.release(fdObj, fli.position(), fli.size()); + removeFromFileLockTable(fli); + } finally { + end(); + } + } + + @Override + public Future read(final ByteBuffer dst, + final long position, + A attachment, + final CompletionHandler handler) + { + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (!reading) + throw new NonReadableChannelException(); + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + + // complete immediately if channel closed or no space remaining + if (!isOpen() || (dst.remaining() == 0)) { + CompletedFuture result; + if (isOpen()) { + result = CompletedFuture.withResult(this, 0, attachment); + } else { + result = CompletedFuture.withFailure(this, + new ClosedChannelException(), attachment); + } + Invoker.invokeIndirectly(handler, result, executor); + return result; + } + + final PendingFuture result = + new PendingFuture(this, handler, attachment); + Runnable task = new Runnable() { + public void run() { + int ti = threads.add(); + try { + begin(); + int n; + do { + n = IOUtil.read(fdObj, dst, position, nd, null); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + if (n < 0 && !isOpen()) + throw new AsynchronousCloseException(); + result.setResult(n); + } catch (IOException x) { + if (!isOpen()) + x = new AsynchronousCloseException(); + result.setFailure(x); + } finally { + end(); + threads.remove(ti); + } + Invoker.invokeUnchecked(handler, result); + } + }; + try { + executor.execute(task); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + return result; + } + + @Override + public Future write(final ByteBuffer src, + final long position, + A attachment, + final CompletionHandler handler) + { + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (!writing) + throw new NonWritableChannelException(); + + // complete immediately if channel is closed or no bytes remaining + if (!isOpen() || (src.remaining() == 0)) { + CompletedFuture result; + if (isOpen()) { + result = CompletedFuture.withResult(this, 0, attachment); + } else { + result = CompletedFuture.withFailure(this, + new ClosedChannelException(), attachment); + } + Invoker.invokeIndirectly(handler, result, executor); + return result; + } + + final PendingFuture result = + new PendingFuture(this, handler, attachment); + Runnable task = new Runnable() { + public void run() { + int ti = threads.add(); + try { + begin(); + int n; + do { + n = IOUtil.write(fdObj, src, position, nd, null); + } while ((n == IOStatus.INTERRUPTED) && isOpen()); + if (n < 0 && !isOpen()) + throw new AsynchronousCloseException(); + result.setResult(n); + } catch (IOException x) { + if (!isOpen()) + x = new AsynchronousCloseException(); + result.setFailure(x); + } finally { + end(); + threads.remove(ti); + } + Invoker.invokeUnchecked(handler, result); + } + }; + try { + executor.execute(task); + } catch (RejectedExecutionException ree) { + throw new ShutdownChannelGroupException(); + } + return result; + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 11567ba2ab7..20944774d4e 100644 --- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,28 +128,28 @@ class SocketChannelImpl public SocketAddress getLocalAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) - return null; + throw new ClosedChannelException(); return localAddress; } } @Override - public SocketAddress getConnectedAddress() throws IOException { + public SocketAddress getRemoteAddress() throws IOException { synchronized (stateLock) { if (!isOpen()) - return null; + throw new ClosedChannelException(); return remoteAddress; } } @Override - public SocketChannel setOption(SocketOption name, Object value) + public SocketChannel setOption(SocketOption name, T value) throws IOException { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("Invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { if (!isOpen()) @@ -175,8 +175,8 @@ class SocketChannelImpl { if (name == null) throw new NullPointerException(); - if (!options().contains(name)) - throw new IllegalArgumentException("Invalid option name"); + if (!supportedOptions().contains(name)) + throw new UnsupportedOperationException("'" + name + "' not supported"); synchronized (stateLock) { if (!isOpen()) @@ -193,7 +193,7 @@ class SocketChannelImpl } } - private static class LazyInitialization { + private static class DefaultOptionsHolder { static final Set> defaultOptions = defaultOptions(); private static Set> defaultOptions() { @@ -212,8 +212,8 @@ class SocketChannelImpl } @Override - public final Set> options() { - return LazyInitialization.defaultOptions; + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; } private boolean ensureReadOpen() throws ClosedChannelException { diff --git a/jdk/src/share/classes/sun/nio/ch/ThreadPool.java b/jdk/src/share/classes/sun/nio/ch/ThreadPool.java new file mode 100644 index 00000000000..37e6a80a0ba --- /dev/null +++ b/jdk/src/share/classes/sun/nio/ch/ThreadPool.java @@ -0,0 +1,176 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.util.concurrent.*; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; +import sun.security.action.GetIntegerAction; + +/** + * Encapsulates a thread pool associated with a channel group. + */ + +public class ThreadPool { + private static final String DEFAULT_THREAD_POOL_THREAD_FACTORY = + "java.nio.channels.DefaultThreadPool.threadFactory"; + private static final String DEFAULT_THREAD_POOL_INITIAL_SIZE = + "java.nio.channels.DefaultThreadPool.initialSize"; + private static final ThreadFactory defaultThreadFactory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + } + }; + + private final ExecutorService executor; + + // indicates if thread pool is fixed size + private final boolean isFixed; + + // indicates the pool size (for a fixed thread pool configuratin this is + // the maximum pool size; for other thread pools it is the initial size) + private final int poolSize; + + private ThreadPool(ExecutorService executor, + boolean isFixed, + int poolSize) + { + this.executor = executor; + this.isFixed = isFixed; + this.poolSize = poolSize; + } + + ExecutorService executor() { + return executor; + } + + boolean isFixedThreadPool() { + return isFixed; + } + + int poolSize() { + return poolSize; + } + + static ThreadFactory defaultThreadFactory() { + return defaultThreadFactory; + } + + private static class DefaultThreadPoolHolder { + final static ThreadPool defaultThreadPool = createDefault(); + } + + // return the default (system-wide) thread pool + static ThreadPool getDefault() { + return DefaultThreadPoolHolder.defaultThreadPool; + } + + // create thread using default settings (configured by system properties) + static ThreadPool createDefault() { + // default the number of fixed threads to the hardware core count + int initialSize = getDefaultThreadPoolInitialSize(); + if (initialSize < 0) + initialSize = Runtime.getRuntime().availableProcessors(); + // default to thread factory that creates daemon threads + ThreadFactory threadFactory = getDefaultThreadPoolThreadFactory(); + if (threadFactory == null) + threadFactory = defaultThreadFactory; + // create thread pool + ExecutorService executor = + new ThreadPoolExecutor(0, Integer.MAX_VALUE, + Long.MAX_VALUE, TimeUnit.MILLISECONDS, + new SynchronousQueue(), + threadFactory); + return new ThreadPool(executor, false, initialSize); + } + + // create using given parameters + static ThreadPool create(int nThreads, ThreadFactory factory) { + if (nThreads <= 0) + throw new IllegalArgumentException("'nThreads' must be > 0"); + ExecutorService executor = Executors.newFixedThreadPool(nThreads, factory); + return new ThreadPool(executor, true, nThreads); + } + + // wrap a user-supplied executor + public static ThreadPool wrap(ExecutorService executor, int initialSize) { + if (executor == null) + throw new NullPointerException("'executor' is null"); + // attempt to check if cached thread pool + if (executor instanceof ThreadPoolExecutor) { + int max = ((ThreadPoolExecutor)executor).getMaximumPoolSize(); + if (max == Integer.MAX_VALUE) { + if (initialSize < 0) { + initialSize = Runtime.getRuntime().availableProcessors(); + } else { + // not a cached thread pool so ignore initial size + initialSize = 0; + } + } + } else { + // some other type of thread pool + if (initialSize < 0) + initialSize = 0; + } + return new ThreadPool(executor, false, initialSize); + } + + private static int getDefaultThreadPoolInitialSize() { + String propValue = AccessController.doPrivileged(new + GetPropertyAction(DEFAULT_THREAD_POOL_INITIAL_SIZE)); + if (propValue != null) { + try { + return Integer.parseInt(propValue); + } catch (NumberFormatException x) { + throw new Error("Value of property '" + DEFAULT_THREAD_POOL_INITIAL_SIZE + + "' is invalid: " + x); + } + } + return -1; + } + + private static ThreadFactory getDefaultThreadPoolThreadFactory() { + String propValue = AccessController.doPrivileged(new + GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); + if (propValue != null) { + try { + Class c = Class + .forName(propValue, true, ClassLoader.getSystemClassLoader()); + return ((ThreadFactory)c.newInstance()); + } catch (ClassNotFoundException x) { + throw new Error(x); + } catch (InstantiationException x) { + throw new Error(x); + } catch (IllegalAccessException x) { + throw new Error(x); + } + } + return null; + } +} diff --git a/jdk/src/share/classes/sun/nio/ch/Util.java b/jdk/src/share/classes/sun/nio/ch/Util.java index 534548ff778..efdce4a4b9a 100644 --- a/jdk/src/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/share/classes/sun/nio/ch/Util.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.*; -import java.nio.channels.spi.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; @@ -100,6 +99,9 @@ class Util { return; } } + + // release memory + ((DirectBuffer)buf).cleaner().clean(); } private static class SelectorWrapper { diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java new file mode 100644 index 00000000000..053e3dcfbb0 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java @@ -0,0 +1,110 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Base implementation of AclFileAttributeView + */ + +abstract class AbstractAclFileAttributeView + implements AclFileAttributeView +{ + private static final String OWNER_NAME = "owner"; + private static final String ACL_NAME = "acl"; + + @Override + public final String name() { + return "acl"; + } + + @Override + public final Object getAttribute(String attribute) throws IOException { + if (attribute.equals(OWNER_NAME)) + return getOwner(); + if (attribute.equals(ACL_NAME)) + return getAcl(); + return null; + } + + @Override + @SuppressWarnings("unchecked") + public final void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(OWNER_NAME)) { + setOwner((UserPrincipal)value); + return; + } + if (attribute.equals(ACL_NAME)) { + setAcl((List)value); + return; + } + throw new UnsupportedOperationException(); + } + + @Override + public final Map readAttributes(String first, String[] rest) + throws IOException + { + boolean acl = false; + boolean owner = false; + + if (first.equals(ACL_NAME)) acl = true; + else if (first.equals(OWNER_NAME)) owner = true; + else if (first.equals("*")) { + owner = true; + acl = true; + } + + if (!acl || !owner) { + for (String attribute: rest) { + if (attribute.equals("*")) { + owner = true; + acl = true; + break; + } + if (attribute.equals(ACL_NAME)) { + acl = true; + continue; + } + if (attribute.equals(OWNER_NAME)) { + owner = true; + continue; + } + } + } + Map result = new HashMap(2); + if (acl) + result.put(ACL_NAME, getAcl()); + if (owner) + result.put(OWNER_NAME, getOwner()); + return Collections.unmodifiableMap(result); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java new file mode 100644 index 00000000000..18cf00d501c --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java @@ -0,0 +1,208 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Base implementation of BasicFileAttributeView + */ + +abstract class AbstractBasicFileAttributeView + implements BasicFileAttributeView +{ + private static final String SIZE_NAME = "size"; + private static final String CREATION_TIME_NAME = "creationTime"; + private static final String LAST_ACCESS_TIME_NAME = "lastAccessTime"; + private static final String LAST_MODIFIED_TIME_NAME = "lastModifiedTime"; + private static final String RESOLUTION_NAME = "resolution"; + private static final String FILE_KEY_NAME = "fileKey"; + private static final String LINK_COUNT_NAME = "linkCount"; + private static final String IS_DIRECTORY_NAME = "isDirectory"; + private static final String IS_REGULAR_FILE_NAME = "isRegularFile"; + private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink"; + private static final String IS_OTHER_NAME = "isOther"; + + protected AbstractBasicFileAttributeView() { } + + @Override + public String name() { + return "basic"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + BasicFileAttributes attrs = readAttributes(); + if (attribute.equals(SIZE_NAME)) + return attrs.size(); + if (attribute.equals(CREATION_TIME_NAME)) + return attrs.creationTime(); + if (attribute.equals(LAST_ACCESS_TIME_NAME)) + return attrs.lastAccessTime(); + if (attribute.equals(LAST_MODIFIED_TIME_NAME)) + return attrs.lastModifiedTime(); + if (attribute.equals(RESOLUTION_NAME)) + return attrs.resolution(); + if (attribute.equals(FILE_KEY_NAME)) + return attrs.fileKey(); + if (attribute.equals(LINK_COUNT_NAME)) + return attrs.linkCount(); + if (attribute.equals(IS_DIRECTORY_NAME)) + return attrs.isDirectory(); + if (attribute.equals(IS_REGULAR_FILE_NAME)) + return attrs.isRegularFile(); + if (attribute.equals(IS_SYMBOLIC_LINK_NAME)) + return attrs.isSymbolicLink(); + if (attribute.equals(IS_OTHER_NAME)) + return attrs.isOther(); + return null; + } + + private Long toTimeValue(Object value) { + if (value == null) + throw new NullPointerException(); + Long time = (Long)value; + if (time < 0L && time != -1L) + throw new IllegalArgumentException("time value cannot be negative"); + return time; + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(LAST_MODIFIED_TIME_NAME)) { + setTimes(toTimeValue(value), null, null, TimeUnit.MILLISECONDS); + return; + } + if (attribute.equals(LAST_ACCESS_TIME_NAME)) { + setTimes(null, toTimeValue(value), null, TimeUnit.MILLISECONDS); + return; + } + if (attribute.equals(CREATION_TIME_NAME)) { + setTimes(null, null, toTimeValue(value), TimeUnit.MILLISECONDS); + return; + } + throw new UnsupportedOperationException("'" + attribute + + "' is unknown or read-only attribute"); + } + + /** + * + */ + static class AttributesBuilder { + private Set set = new HashSet(); + private Map map = new HashMap(); + private boolean copyAll; + + private AttributesBuilder(String first, String[] rest) { + if (first.equals("*")) { + copyAll = true; + } else { + set.add(first); + // copy names into the given Set bailing out if "*" is found + for (String attribute: rest) { + if (attribute.equals("*")) { + copyAll = true; + break; + } + set.add(attribute); + } + } + } + + /** + * Creates builder to build up a map of the matching attributes + */ + static AttributesBuilder create(String first, String[] rest) { + return new AttributesBuilder(first, rest); + } + + /** + * Returns true if the attribute should be returned in the map + */ + boolean match(String attribute) { + if (copyAll) + return true; + return set.contains(attribute); + } + + void add(String attribute, Object value) { + map.put(attribute, value); + } + + /** + * Returns the map. Discard all references to the AttributesBuilder + * after invoking this method. + */ + Map unmodifiableMap() { + return Collections.unmodifiableMap(map); + } + } + + /** + * Invoked by readAttributes or sub-classes to add all matching basic + * attributes to the builder + */ + final void addBasicAttributesToBuilder(BasicFileAttributes attrs, + AttributesBuilder builder) + { + if (builder.match(SIZE_NAME)) + builder.add(SIZE_NAME, attrs.size()); + if (builder.match(CREATION_TIME_NAME)) + builder.add(CREATION_TIME_NAME, attrs.creationTime()); + if (builder.match(LAST_ACCESS_TIME_NAME)) + builder.add(LAST_ACCESS_TIME_NAME, attrs.lastAccessTime()); + if (builder.match(LAST_MODIFIED_TIME_NAME)) + builder.add(LAST_MODIFIED_TIME_NAME, attrs.lastModifiedTime()); + if (builder.match(RESOLUTION_NAME)) + builder.add(RESOLUTION_NAME, attrs.resolution()); + if (builder.match(FILE_KEY_NAME)) + builder.add(FILE_KEY_NAME, attrs.fileKey()); + if (builder.match(LINK_COUNT_NAME)) + builder.add(LINK_COUNT_NAME, attrs.linkCount()); + if (builder.match(IS_DIRECTORY_NAME)) + builder.add(IS_DIRECTORY_NAME, attrs.isDirectory()); + if (builder.match(IS_REGULAR_FILE_NAME)) + builder.add(IS_REGULAR_FILE_NAME, attrs.isRegularFile()); + if (builder.match(IS_SYMBOLIC_LINK_NAME)) + builder.add(IS_SYMBOLIC_LINK_NAME, attrs.isSymbolicLink()); + if (builder.match(IS_OTHER_NAME)) + builder.add(IS_OTHER_NAME, attrs.isOther()); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + addBasicAttributesToBuilder(readAttributes(), builder); + return builder.unmodifiableMap(); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java new file mode 100644 index 00000000000..73c8c2a0db1 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileStoreSpaceAttributeView.java @@ -0,0 +1,119 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Base implementation of FileStoreSpaceAttributeView + */ + +abstract class AbstractFileStoreSpaceAttributeView + implements FileStoreSpaceAttributeView +{ + private static final String TOTAL_SPACE_NAME = "totalSpace"; + private static final String USABLE_SPACE_NAME = "usableSpace"; + private static final String UNALLOCATED_SPACE_NAME = "unallocatedSpace"; + + @Override + public final String name() { + return "space"; + } + + @Override + public final Object getAttribute(String attribute) throws IOException { + FileStoreSpaceAttributes attrs = readAttributes(); + if (attribute.equals(TOTAL_SPACE_NAME)) + return attrs.totalSpace(); + if (attribute.equals(USABLE_SPACE_NAME)) + return attrs.usableSpace(); + if (attribute.equals(UNALLOCATED_SPACE_NAME)) + return attrs.unallocatedSpace(); + return null; + } + + @Override + public final void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute == null || value == null) + throw new NullPointerException(); + throw new UnsupportedOperationException(); + } + + @Override + public final Map readAttributes(String first, String[] rest) + throws IOException + { + boolean total = false; + boolean usable = false; + boolean unallocated = false; + + if (first.equals(TOTAL_SPACE_NAME)) total = true; + else if (first.equals(USABLE_SPACE_NAME)) usable = true; + else if (first.equals(UNALLOCATED_SPACE_NAME)) unallocated = true; + else if (first.equals("*")) { + total = true; + usable = true; + unallocated = true; + } + + if (!total || !usable || !unallocated) { + for (String attribute: rest) { + if (attribute.equals("*")) { + total = true; + usable = true; + unallocated = true; + break; + } + if (attribute.equals(TOTAL_SPACE_NAME)) { + total = true; + continue; + } + if (attribute.equals(USABLE_SPACE_NAME)) { + usable = true; + continue; + } + if (attribute.equals(UNALLOCATED_SPACE_NAME)) { + unallocated = true; + continue; + } + } + } + + FileStoreSpaceAttributes attrs = readAttributes(); + Map result = new HashMap(2); + if (total) + result.put(TOTAL_SPACE_NAME, attrs.totalSpace()); + if (usable) + result.put(USABLE_SPACE_NAME, attrs.usableSpace()); + if (unallocated) + result.put(UNALLOCATED_SPACE_NAME, attrs.unallocatedSpace()); + return Collections.unmodifiableMap(result); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java new file mode 100644 index 00000000000..d8a391b8081 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.FileRef; +import java.nio.file.spi.FileTypeDetector; +import java.io.IOException; +import sun.nio.fs.MimeType; + +/** + * Base implementation of FileTypeDetector + */ + +public abstract class AbstractFileTypeDetector + extends FileTypeDetector +{ + protected AbstractFileTypeDetector() { + super(); + } + + /** + * Invokes the implProbeContentType method to guess the file's content type, + * and this validates that the content type's syntax is valid. + */ + @Override + public final String probeContentType(FileRef file) throws IOException { + if (file == null) + throw new NullPointerException("'file' is null"); + String result = implProbeContentType(file); + if (result != null) { + // check the content type + try { + MimeType.parse(result); + } catch (IllegalArgumentException ignore) { + result = null; + } + } + return result; + } + + /** + * Probes the given file to guess its content type. + */ + protected abstract String implProbeContentType(FileRef file) + throws IOException; +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java b/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java new file mode 100644 index 00000000000..3ab8af8e13b --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java @@ -0,0 +1,290 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.io.IOException; +import java.util.*; + +/** + * Base implementation of background poller thread used in watch service + * implementations. A poller thread waits on events from the file system and + * also services "requests" from clients to register for new events or cancel + * existing registrations. + */ + +abstract class AbstractPoller implements Runnable { + + // list of requests pending to the poller thread + private final LinkedList requestList; + + // set to true when shutdown + private boolean shutdown; + + protected AbstractPoller() { + this.requestList = new LinkedList(); + this.shutdown = false; + } + + /** + * Starts the poller thread + */ + public void start() { + final Runnable thisRunnable = this; + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + Thread thr = new Thread(thisRunnable); + thr.setDaemon(true); + thr.start(); + return null; + } + }); + } + + /** + * Wakeup poller thread so that it can service pending requests + */ + abstract void wakeup() throws IOException; + + /** + * Executed by poller thread to register directory for changes + */ + abstract Object implRegister(Path path, + Set> events, + WatchEvent.Modifier... modifiers); + + /** + * Executed by poller thread to cancel key + */ + abstract void implCancelKey(WatchKey key); + + /** + * Executed by poller thread to shutdown and cancel all keys + */ + abstract void implCloseAll(); + + /** + * Requests, and waits on, poller thread to register given file. + */ + final WatchKey register(FileRef dir, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + // validate arguments before request to poller + if (dir == null) + throw new NullPointerException(); + if (events.length == 0) + throw new IllegalArgumentException("No events to register"); + Set> eventSet = new HashSet>(events.length); + for (WatchEvent.Kind event: events) { + // standard events + if (event == StandardWatchEventKind.ENTRY_CREATE || + event == StandardWatchEventKind.ENTRY_MODIFY || + event == StandardWatchEventKind.ENTRY_DELETE) + { + eventSet.add(event); + continue; + } + + // OVERFLOW is ignored + if (event == StandardWatchEventKind.OVERFLOW) { + if (events.length == 1) + throw new IllegalArgumentException("No events to register"); + continue; + } + + // null/unsupported + if (event == null) + throw new NullPointerException("An element in event set is 'null'"); + throw new UnsupportedOperationException(event.name()); + } + return (WatchKey)invoke(RequestType.REGISTER, dir, eventSet, modifiers); + } + + /** + * Cancels, and waits on, poller thread to cancel given key. + */ + final void cancel(WatchKey key) { + try { + invoke(RequestType.CANCEL, key); + } catch (IOException x) { + // should not happen + throw new AssertionError(x.getMessage()); + } + } + + /** + * Shutdown poller thread + */ + final void close() throws IOException { + invoke(RequestType.CLOSE); + } + + /** + * Types of request that the poller thread must handle + */ + private static enum RequestType { + REGISTER, + CANCEL, + CLOSE; + } + + /** + * Encapsulates a request (command) to the poller thread. + */ + private static class Request { + private final RequestType type; + private final Object[] params; + + private boolean completed = false; + private Object result = null; + + Request(RequestType type, Object... params) { + this.type = type; + this.params = params; + } + + RequestType type() { + return type; + } + + Object[] parameters() { + return params; + } + + void release(Object result) { + synchronized (this) { + this.completed = true; + this.result = result; + notifyAll(); + } + } + + /** + * Await completion of the request. The return value is the result of + * the request. + */ + Object awaitResult() { + synchronized (this) { + while (!completed) { + try { + wait(); + } catch (InterruptedException x) { + // ignore + } + } + return result; + } + } + } + + /** + * Enqueues request to poller thread and waits for result + */ + private Object invoke(RequestType type, Object... params) throws IOException { + // submit request + Request req = new Request(type, params); + synchronized (requestList) { + if (shutdown) { + throw new ClosedWatchServiceException(); + } + requestList.add(req); + } + + // wakeup thread + wakeup(); + + // wait for result + Object result = req.awaitResult(); + + if (result instanceof RuntimeException) + throw (RuntimeException)result; + if (result instanceof IOException ) + throw (IOException)result; + return result; + } + + /** + * Invoked by poller thread to process all pending requests + * + * @return true if poller thread should shutdown + */ + @SuppressWarnings("unchecked") + boolean processRequests() { + synchronized (requestList) { + Request req; + while ((req = requestList.poll()) != null) { + // if in process of shutdown then reject request + if (shutdown) { + req.release(new ClosedWatchServiceException()); + } + + switch (req.type()) { + /** + * Register directory + */ + case REGISTER: { + Object[] params = req.parameters(); + Path path = (Path)params[0]; + Set> events = + (Set>)params[1]; + WatchEvent.Modifier[] modifiers = + (WatchEvent.Modifier[])params[2]; + req.release(implRegister(path, events, modifiers)); + break; + } + /** + * Cancel existing key + */ + case CANCEL : { + Object[] params = req.parameters(); + WatchKey key = (WatchKey)params[0]; + implCancelKey(key); + req.release(null); + break; + } + /** + * Close watch service + */ + case CLOSE: { + implCloseAll(); + req.release(null); + shutdown = true; + break; + } + + default: + req.release(new IOException("request not recognized")); + } + } + } + return shutdown; + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java new file mode 100644 index 00000000000..3ac9b507fc0 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java @@ -0,0 +1,124 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.ByteBuffer; +import java.nio.file.attribute.UserDefinedFileAttributeView; +import java.io.IOException; +import java.util.*; + +/** + * Base implementation of NamedAttributeView + */ + +abstract class AbstractUserDefinedFileAttributeView + implements UserDefinedFileAttributeView +{ + protected AbstractUserDefinedFileAttributeView() { } + + protected void checkAccess(String file, + boolean checkRead, + boolean checkWrite) + { + assert checkRead || checkWrite; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (checkRead) + sm.checkRead(file); + if (checkWrite) + sm.checkWrite(file); + sm.checkPermission(new RuntimePermission("accessUserDefinedAttributes")); + } + } + + @Override + public final String name() { + return "xattr"; + } + + @Override + public final Object getAttribute(String attribute) throws IOException { + int size; + try { + size = size(attribute); + } catch (IOException e) { + // not found or some other I/O error + if (list().contains(attribute)) + throw e; + return null; + } + byte[] buf = new byte[size]; + int n = read(attribute, ByteBuffer.wrap(buf)); + return (n == size) ? buf : Arrays.copyOf(buf, n); + } + + @Override + public final void setAttribute(String attribute, Object value) + throws IOException + { + ByteBuffer bb; + if (value instanceof byte[]) { + bb = ByteBuffer.wrap((byte[])value); + } else { + bb = (ByteBuffer)value; + } + write(attribute, bb); + } + + @Override + public final Map readAttributes(String first, String... rest) + throws IOException + { + // names of attributes to return + List names = new ArrayList(); + + boolean readAll = false; + if (first.equals("*")) { + readAll = true; + } else { + names.add(first); + } + for (String name: rest) { + if (name.equals("*")) { + readAll = true; + } else { + names.add(name); + } + } + if (readAll) + names = list(); + + // read each value and return in map + Map result = new HashMap(); + for (String name: names) { + Object value = getAttribute(name); + if (value != null) + result.put(name, value); + } + + return result; + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java new file mode 100644 index 00000000000..8e33f81ed84 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java @@ -0,0 +1,180 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.util.*; + +/** + * Base implementation class for watch keys. + */ + +abstract class AbstractWatchKey extends WatchKey { + + /** + * Maximum size of event list (in the future this may be tunable) + */ + static final int MAX_EVENT_LIST_SIZE = 512; + + /** + * Special event to signal overflow + */ + static final Event OVERFLOW_EVENT = + new Event(StandardWatchEventKind.OVERFLOW, null); + + /** + * Possible key states + */ + private static enum State { READY, SIGNALLED }; + + // reference to watcher + private final AbstractWatchService watcher; + + // key state + private State state; + + // pending events + private List> events; + + protected AbstractWatchKey(AbstractWatchService watcher) { + this.watcher = watcher; + this.state = State.READY; + this.events = new ArrayList>(); + } + + final AbstractWatchService watcher() { + return watcher; + } + + /** + * Enqueues this key to the watch service + */ + final void signal() { + synchronized (this) { + if (state == State.READY) { + state = State.SIGNALLED; + watcher.enqueueKey(this); + } + } + } + + /** + * Adds the event to this key and signals it. + */ + @SuppressWarnings("unchecked") + final void signalEvent(WatchEvent.Kind kind, Object context) { + synchronized (this) { + int size = events.size(); + if (size > 1) { + // don't let list get too big + if (size >= MAX_EVENT_LIST_SIZE) { + kind = StandardWatchEventKind.OVERFLOW; + context = null; + } + + // repeated event + WatchEvent prev = events.get(size-1); + if (kind == prev.kind()) { + boolean isRepeat; + if (context == null) { + isRepeat = (prev.context() == null); + } else { + isRepeat = context.equals(prev.context()); + } + if (isRepeat) { + ((Event)prev).increment(); + return; + } + } + } + + // non-repeated event + events.add(new Event((WatchEvent.Kind)kind, context)); + signal(); + } + } + + @Override + public final List> pollEvents() { + synchronized (this) { + List> result = events; + events = new ArrayList>(); + return result; + } + } + + @Override + public final boolean reset() { + synchronized (this) { + if (state == State.SIGNALLED && isValid()) { + if (events.isEmpty()) { + state = State.READY; + } else { + // pending events so re-queue key + watcher.enqueueKey(this); + } + } + return isValid(); + } + } + + /** + * WatchEvent implementation + */ + private static class Event extends WatchEvent { + private final WatchEvent.Kind kind; + private final T context; + + // synchronize on watch key to access/increment count + private int count; + + Event(WatchEvent.Kind type, T context) { + this.kind = type; + this.context = context; + this.count = 1; + } + + @Override + public WatchEvent.Kind kind() { + return kind; + } + + @Override + public T context() { + return context; + } + + @Override + public int count() { + return count; + } + + // for repeated events + void increment() { + count++; + } + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java new file mode 100644 index 00000000000..c29d78b59d2 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.util.concurrent.*; +import java.io.IOException; + +/** + * Base implementation class for watch services. + */ + +abstract class AbstractWatchService extends WatchService { + + // signaled keys waiting to be dequeued + private final LinkedBlockingDeque pendingKeys = + new LinkedBlockingDeque(); + + // special key to indicate that watch service is closed + private final WatchKey CLOSE_KEY = + new AbstractWatchKey(null) { + @Override + public boolean isValid() { + return true; + } + + @Override + public void cancel() { + } + }; + + // used when closing watch service + private volatile boolean closed; + private Object closeLock = new Object(); + + protected AbstractWatchService() { + } + + /** + * Register the given object with this watch service + */ + abstract WatchKey register(Path path, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifers) + throws IOException; + + // used by AbstractWatchKey to enqueue key + final void enqueueKey(WatchKey key) { + pendingKeys.offer(key); + } + + /** + * Throws ClosedWatchServiceException if watch service is closed + */ + private void checkOpen() { + if (closed) + throw new ClosedWatchServiceException(); + } + + /** + * Checks the key isn't the special CLOSE_KEY used to unblock threads when + * the watch service is closed. + */ + private void checkKey(WatchKey key) { + if (key == CLOSE_KEY) { + // re-queue in case there are other threads blocked in take/poll + enqueueKey(key); + } + checkOpen(); + } + + @Override + public final WatchKey poll() { + checkOpen(); + WatchKey key = pendingKeys.poll(); + checkKey(key); + return key; + } + + @Override + public final WatchKey poll(long timeout, TimeUnit unit) + throws InterruptedException + { + checkOpen(); + WatchKey key = pendingKeys.poll(timeout, unit); + checkKey(key); + return key; + } + + @Override + public final WatchKey take() + throws InterruptedException + { + checkOpen(); + WatchKey key = pendingKeys.take(); + checkKey(key); + return key; + } + + /** + * Tells whether or not this watch service is open. + */ + final boolean isOpen() { + return !closed; + } + + /** + * Retrieves the object upon which the close method synchronizes. + */ + final Object closeLock() { + return closeLock; + } + + /** + * Closes this watch service. This method is invoked by the close + * method to perform the actual work of closing the watch service. + */ + abstract void implClose() throws IOException; + + @Override + public final void close() + throws IOException + { + synchronized (closeLock) { + // nothing to do if already closed + if (closed) + return; + closed = true; + + implClose(); + + // clear pending keys and queue special key to ensure that any + // threads blocked in take/poll wakeup + pendingKeys.clear(); + pendingKeys.offer(CLOSE_KEY); + } + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/BasicFileAttributesHolder.java b/jdk/src/share/classes/sun/nio/fs/BasicFileAttributesHolder.java new file mode 100644 index 00000000000..28f8691ec73 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/BasicFileAttributesHolder.java @@ -0,0 +1,46 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.BasicFileAttributes; + +/** + * Implemented by objects that may hold or cache the attributes of a file. + */ + +public interface BasicFileAttributesHolder { + /** + * Returns cached attributes (may be null). If file is a symbolic link then + * the attributes are the link attributes and not the final target of the + * file. + */ + BasicFileAttributes get(); + + /** + * Invalidates cached attributes + */ + void invalidate(); +} diff --git a/jdk/src/share/classes/sun/nio/fs/Cancellable.java b/jdk/src/share/classes/sun/nio/fs/Cancellable.java new file mode 100644 index 00000000000..3b40ddd1017 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/Cancellable.java @@ -0,0 +1,137 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import sun.misc.Unsafe; +import java.util.concurrent.ExecutionException; + +/** + * Base implementation of a task (typically native) that polls a memory location + * during execution so that it may be aborted/cancelled before completion. The + * task is executed by invoking the {@link runInterruptibly} method defined + * here and cancelled by invoking Thread.interrupt. + */ + +abstract class Cancellable implements Runnable { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private final long pollingAddress; + private final Object lock = new Object(); + + // the following require lock when examining or changing + private boolean completed; + private Throwable exception; + + protected Cancellable() { + pollingAddress = unsafe.allocateMemory(4); + unsafe.putIntVolatile(null, pollingAddress, 0); + } + + /** + * Returns the memory address of a 4-byte int that should be polled to + * detect cancellation. + */ + protected long addressToPollForCancel() { + return pollingAddress; + } + + /** + * The value to write to the polled memory location to indicate that the + * task has been cancelled. If this method is not overridden then it + * defaults to MAX_VALUE. + */ + protected int cancelValue() { + return Integer.MAX_VALUE; + } + + /** + * "cancels" the task by writing bits into memory location that it polled + * by the task. + */ + final void cancel() { + synchronized (lock) { + if (!completed) { + unsafe.putIntVolatile(null, pollingAddress, cancelValue()); + } + } + } + + /** + * Returns the exception thrown by the task or null if the task completed + * successfully. + */ + private Throwable exception() { + synchronized (lock) { + return exception; + } + } + + @Override + public final void run() { + try { + implRun(); + } catch (Throwable t) { + synchronized (lock) { + exception = t; + } + } finally { + synchronized (lock) { + completed = true; + unsafe.freeMemory(pollingAddress); + } + } + } + + /** + * The task body. This should periodically poll the memory location + * to check for cancellation. + */ + abstract void implRun() throws Throwable; + + /** + * Invokes the given task in its own thread. If this (meaning the current) + * thread is interrupted then an attempt is make to cancel the background + * thread by writing into the memory location that it polls cooperatively. + */ + static void runInterruptibly(Cancellable task) throws ExecutionException { + Thread t = new Thread(task); + t.start(); + boolean cancelledByInterrupt = false; + while (t.isAlive()) { + try { + t.join(); + } catch (InterruptedException e) { + cancelledByInterrupt = true; + task.cancel(); + } + } + if (cancelledByInterrupt) + Thread.currentThread().interrupt(); + Throwable exc = task.exception(); + if (exc != null) + throw new ExecutionException(exc); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java new file mode 100644 index 00000000000..f40c2a79740 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java @@ -0,0 +1,111 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; + +/** + * An implementation of FileOwnerAttributeView that delegates to a given + * PosixFileAttributeView or AclFileAttributeView object. + */ + +final class FileOwnerAttributeViewImpl implements FileOwnerAttributeView { + private static final String OWNER_NAME = "owner"; + + private final FileAttributeView view; + private final boolean isPosixView; + + FileOwnerAttributeViewImpl(PosixFileAttributeView view) { + this.view = view; + this.isPosixView = true; + } + + FileOwnerAttributeViewImpl(AclFileAttributeView view) { + this.view = view; + this.isPosixView = false; + } + + @Override + public String name() { + return "owner"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(OWNER_NAME)) + return getOwner(); + return null; + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(OWNER_NAME)) { + setOwner((UserPrincipal)value); + return; + } + throw new UnsupportedOperationException(); + } + + @Override + public Map readAttributes(String first, String[] rest) throws IOException { + Map result = new HashMap(); + if (first.equals("*") || first.equals(OWNER_NAME)) { + result.put(OWNER_NAME, getOwner()); + } else { + for (String attribute: rest) { + if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { + result.put(OWNER_NAME, getOwner()); + break; + } + } + } + return result; + } + + @Override + public UserPrincipal getOwner() throws IOException { + if (isPosixView) { + return ((PosixFileAttributeView)view).readAttributes().owner(); + } else { + return ((AclFileAttributeView)view).getOwner(); + } + } + + @Override + public void setOwner(UserPrincipal owner) + throws IOException + { + if (isPosixView) { + ((PosixFileAttributeView)view).setOwner(owner); + } else { + ((AclFileAttributeView)view).setOwner(owner); + } + } + } diff --git a/jdk/src/share/classes/sun/nio/fs/Globs.java b/jdk/src/share/classes/sun/nio/fs/Globs.java new file mode 100644 index 00000000000..33857ea0cdf --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/Globs.java @@ -0,0 +1,217 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.util.regex.PatternSyntaxException; + +public class Globs { + private Globs() { } + + private static final String regexMetaChars = ".^$+{[]|()"; + private static final String globMetaChars = "\\*?[{"; + + private static boolean isRegexMeta(char c) { + return regexMetaChars.indexOf(c) != -1; + } + + private static boolean isGlobMeta(char c) { + return globMetaChars.indexOf(c) != -1; + } + private static char EOL = 0; //TBD + + private static char next(String glob, int i) { + if (i < glob.length()) { + return glob.charAt(i); + } + return EOL; + } + + /** + * Creates a regex pattern from the given glob expression. + * + * @throws PatternSyntaxException + */ + private static String toRegexPattern(String globPattern, boolean isDos) { + boolean inGroup = false; + StringBuilder regex = new StringBuilder("^"); + + int i = 0; + while (i < globPattern.length()) { + char c = globPattern.charAt(i++); + switch (c) { + case '\\': + // escape special characters + if (i == globPattern.length()) { + throw new PatternSyntaxException("No character to escape", + globPattern, i - 1); + } + char next = globPattern.charAt(i++); + if (isGlobMeta(next) || isRegexMeta(next)) { + regex.append('\\'); + } + regex.append(next); + break; + case '/': + if (isDos) { + regex.append("\\\\"); + } else { + regex.append(c); + } + break; + case '[': + // don't match name separator in class + if (isDos) { + regex.append("[[^\\\\]&&["); + } else { + regex.append("[[^/]&&["); + } + if (next(globPattern, i) == '^') { + // escape the regex negation char if it appears + regex.append("\\^"); + i++; + } else { + // negation + if (next(globPattern, i) == '!') { + regex.append('^'); + i++; + } + // hyphen allowed at start + if (next(globPattern, i) == '-') { + regex.append('-'); + i++; + } + } + boolean hasRangeStart = false; + char last = 0; + while (i < globPattern.length()) { + c = globPattern.charAt(i++); + if (c == ']') { + break; + } + if (c == '/' || (isDos && c == '\\')) { + throw new PatternSyntaxException("Explicit 'name separator' in class", + globPattern, i - 1); + } + // TBD: how to specify ']' in a class? + if (c == '\\' || c == '[' || + c == '&' && next(globPattern, i) == '&') { + // escape '\', '[' or "&&" for regex class + regex.append('\\'); + } + regex.append(c); + + if (c == '-') { + if (!hasRangeStart) { + throw new PatternSyntaxException("Invalid range", + globPattern, i - 1); + } + if ((c = next(globPattern, i++)) == EOL || c == ']') { + break; + } + if (c < last) { + throw new PatternSyntaxException("Invalid range", + globPattern, i - 3); + } + regex.append(c); + hasRangeStart = false; + } else { + hasRangeStart = true; + last = c; + } + } + if (c != ']') { + throw new PatternSyntaxException("Missing ']", globPattern, i - 1); + } + regex.append("]]"); + break; + case '{': + if (inGroup) { + throw new PatternSyntaxException("Cannot nest groups", + globPattern, i - 1); + } + regex.append("(?:(?:"); + inGroup = true; + break; + case '}': + if (inGroup) { + regex.append("))"); + inGroup = false; + } else { + regex.append('}'); + } + break; + case ',': + if (inGroup) { + regex.append(")|(?:"); + } else { + regex.append(','); + } + break; + case '*': + if (next(globPattern, i) == '*') { + // crosses directory boundaries + regex.append(".*"); + i++; + } else { + // within directory boundary + if (isDos) { + regex.append("[^\\\\]*"); + } else { + regex.append("[^/]*"); + } + } + break; + case '?': + if (isDos) { + regex.append("[^\\\\]"); + } else { + regex.append("[^/]"); + } + break; + + default: + if (isRegexMeta(c)) { + regex.append('\\'); + } + regex.append(c); + } + } + + if (inGroup) { + throw new PatternSyntaxException("Missing '}", globPattern, i - 1); + } + + return regex.append('$').toString(); + } + + static String toUnixRegexPattern(String globPattern) { + return toRegexPattern(globPattern, false); + } + + static String toWindowsRegexPattern(String globPattern) { + return toRegexPattern(globPattern, true); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/MimeType.java b/jdk/src/share/classes/sun/nio/fs/MimeType.java new file mode 100644 index 00000000000..053ea44c205 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/MimeType.java @@ -0,0 +1,73 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Represents a MIME type for the purposes of validation and matching. For + * now this class is implemented using the javax.activation.MimeType class but + * this dependency can easily be eliminated when required. + */ + +public class MimeType { + private final javax.activation.MimeType type; + + private MimeType(javax.activation.MimeType type) { + this.type = type; + } + + /** + * Parses the given string as a MIME type. + * + * @throws IllegalArgumentException + * If the string is not a valid MIME type + */ + public static MimeType parse(String type) { + try { + return new MimeType(new javax.activation.MimeType(type)); + } catch (javax.activation.MimeTypeParseException x) { + throw new IllegalArgumentException(x); + } + } + + /** + * Returns {@code true} if this MIME type has parameters. + */ + public boolean hasParameters() { + return !type.getParameters().isEmpty(); + } + + /** + * Matches this MIME type against a given MIME type. This method returns + * true if the given string is a MIME type and it matches this type. + */ + public boolean match(String other) { + try { + return type.match(other); + } catch (javax.activation.MimeTypeParseException x) { + return false; + } + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java new file mode 100644 index 00000000000..975c1c20b2c --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/NativeBuffer.java @@ -0,0 +1,87 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import sun.misc.Unsafe; +import sun.misc.Cleaner; + +/** + * A light-weight buffer in native memory. + */ + +class NativeBuffer { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private final long address; + private final int size; + private final Cleaner cleaner; + + // optional "owner" to avoid copying + // (only safe for use by thread-local caches) + private Object owner; + + private static class Deallocator implements Runnable { + private final long address; + Deallocator(long address) { + this.address = address; + } + public void run() { + unsafe.freeMemory(address); + } + } + + NativeBuffer(int size) { + this.address = unsafe.allocateMemory(size); + this.size = size; + this.cleaner = Cleaner.create(this, new Deallocator(address)); + } + + void release() { + NativeBuffers.releaseNativeBuffer(this); + } + + long address() { + return address; + } + + int size() { + return size; + } + + Cleaner cleaner() { + return cleaner; + } + + // not synchronized; only safe for use by thread-local caches + void setOwner(Object owner) { + this.owner = owner; + } + + // not synchronized; only safe for use by thread-local caches + Object owner() { + return owner; + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java b/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java new file mode 100644 index 00000000000..fa247a6acc0 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/NativeBuffers.java @@ -0,0 +1,140 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import sun.misc.Unsafe; + +/** + * Factory for native buffers. + */ + +class NativeBuffers { + private NativeBuffers() { } + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private static final int TEMP_BUF_POOL_SIZE = 3; + private static ThreadLocal threadLocal = + new ThreadLocal(); + + /** + * Allocates a native buffer, of at least the given size, from the heap. + */ + static NativeBuffer allocNativeBuffer(int size) { + // Make a new one of at least 2k + if (size < 2048) size = 2048; + return new NativeBuffer(size); + } + + /** + * Returns a native buffer, of at least the given size, from the thread + * local cache. + */ + static NativeBuffer getNativeBufferFromCache(int size) { + // return from cache if possible + NativeBuffer[] buffers = threadLocal.get(); + if (buffers != null) { + for (int i=0; i= size) { + buffers[i] = null; + return buffer; + } + } + } + return null; + } + + /** + * Returns a native buffer, of at least the given size. The native buffer + * is taken from the thread local cache if possible; otherwise it is + * allocated from the heap. + */ + static NativeBuffer getNativeBuffer(int size) { + NativeBuffer buffer = getNativeBufferFromCache(size); + if (buffer != null) { + buffer.setOwner(null); + return buffer; + } else { + return allocNativeBuffer(size); + } + } + + /** + * Releases the given buffer. If there is space in the thread local cache + * then the buffer goes into the cache; otherwise the memory is deallocated. + */ + static void releaseNativeBuffer(NativeBuffer buffer) { + // create cache if it doesn't exist + NativeBuffer[] buffers = threadLocal.get(); + if (buffers == null) { + buffers = new NativeBuffer[TEMP_BUF_POOL_SIZE]; + buffers[0] = buffer; + threadLocal.set(buffers); + return; + } + // Put it in an empty slot if such exists + for (int i=0; i= (len + 1); + unsafe.copyMemory(cstr, offset, null, buffer.address(), len); + unsafe.putByte(buffer.address() + len, (byte)0); + } + + /** + * Copies a byte array and zero terminator into a native buffer, returning + * the buffer. + */ + static NativeBuffer asNativeBuffer(byte[] cstr) { + NativeBuffer buffer = getNativeBuffer(cstr.length+1); + copyCStringToNativeBuffer(cstr, buffer); + return buffer; + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java new file mode 100644 index 00000000000..73a89c27136 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java @@ -0,0 +1,429 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import com.sun.nio.file.SensitivityWatchEventModifier; + +/** + * Simple WatchService implementation that uses periodic tasks to poll + * registered directories for changes. This implementation is for use on + * operating systems that do not have native file change notification support. + */ + +class PollingWatchService + extends AbstractWatchService +{ + // map of registrations + private final Map map = + new HashMap(); + + // used to execute the periodic tasks that poll for changes + private final ScheduledExecutorService scheduledExecutor; + + PollingWatchService() { + // TBD: Make the number of threads configurable + scheduledExecutor = Executors + .newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + }}); + } + + /** + * Register the given file with this watch service + */ + @Override + WatchKey register(final Path path, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + // check events - CCE will be thrown if there are invalid elements + if (events.length == 0) + throw new IllegalArgumentException("No events to register"); + final Set> eventSet = + new HashSet>(events.length); + for (WatchEvent.Kind event: events) { + // standard events + if (event == StandardWatchEventKind.ENTRY_CREATE || + event == StandardWatchEventKind.ENTRY_MODIFY || + event == StandardWatchEventKind.ENTRY_DELETE) + { + eventSet.add(event); + continue; + } + + // OVERFLOW is ignored + if (event == StandardWatchEventKind.OVERFLOW) { + if (events.length == 1) + throw new IllegalArgumentException("No events to register"); + continue; + } + + // null/unsupported + if (event == null) + throw new NullPointerException("An element in event set is 'null'"); + throw new UnsupportedOperationException(event.name()); + } + + // A modifier may be used to specify the sensitivity level + SensitivityWatchEventModifier sensivity = SensitivityWatchEventModifier.MEDIUM; + if (modifiers.length > 0) { + for (WatchEvent.Modifier modifier: modifiers) { + if (modifier == null) + throw new NullPointerException(); + if (modifier instanceof SensitivityWatchEventModifier) { + sensivity = (SensitivityWatchEventModifier)modifier; + continue; + } + throw new UnsupportedOperationException("Modifier not supported"); + } + } + + // check if watch service is closed + if (!isOpen()) + throw new ClosedWatchServiceException(); + + // registration is done in privileged block as it requires the + // attributes of the entries in the directory. + try { + final SensitivityWatchEventModifier s = sensivity; + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + @Override + public PollingWatchKey run() throws IOException { + return doPrivilegedRegister(path, eventSet, s); + } + }); + } catch (PrivilegedActionException pae) { + Throwable cause = pae.getCause(); + if (cause != null && cause instanceof IOException) + throw (IOException)cause; + throw new AssertionError(pae); + } + } + + // registers directory returning a new key if not already registered or + // existing key if already registered + private PollingWatchKey doPrivilegedRegister(Path path, + Set> events, + SensitivityWatchEventModifier sensivity) + throws IOException + { + // check file is a directory and get its file key if possible + BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path); + if (!attrs.isDirectory()) { + throw new NotDirectoryException(path.toString()); + } + Object fileKey = attrs.fileKey(); + if (fileKey == null) + throw new AssertionError("File keys must be supported"); + + // grab close lock to ensure that watch service cannot be closed + synchronized (closeLock()) { + if (!isOpen()) + throw new ClosedWatchServiceException(); + + PollingWatchKey watchKey; + synchronized (map) { + watchKey = map.get(fileKey); + if (watchKey == null) { + // new registration + watchKey = new PollingWatchKey(this, path, fileKey); + map.put(fileKey, watchKey); + } else { + // update to existing registration + watchKey.disable(); + } + } + watchKey.enable(events, sensivity.sensitivityValueInSeconds()); + return watchKey; + } + + } + + @Override + void implClose() throws IOException { + synchronized (map) { + for (Map.Entry entry: map.entrySet()) { + PollingWatchKey watchKey = entry.getValue(); + watchKey.disable(); + watchKey.invalidate(); + } + map.clear(); + } + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + scheduledExecutor.shutdown(); + return null; + } + }); + } + + /** + * Entry in directory cache to record file last-modified-time and tick-count + */ + private static class CacheEntry { + private long lastModified; + private int lastTickCount; + + CacheEntry(long lastModified, int lastTickCount) { + this.lastModified = lastModified; + this.lastTickCount = lastTickCount; + } + + int lastTickCount() { + return lastTickCount; + } + + long lastModified() { + return lastModified; + } + + void update(long lastModified, int tickCount) { + this.lastModified = lastModified; + this.lastTickCount = tickCount; + } + } + + /** + * WatchKey implementation that encapsulates a map of the entries of the + * entries in the directory. Polling the key causes it to re-scan the + * directory and queue keys when entries are added, modified, or deleted. + */ + private class PollingWatchKey extends AbstractWatchKey { + private final Path dir; + private final Object fileKey; + + // current event set + private Set> events; + + // the result of the periodic task that causes this key to be polled + private ScheduledFuture poller; + + // indicates if the key is valid + private volatile boolean valid; + + // used to detect files that have been deleted + private int tickCount; + + // map of entries in directory + private Map entries; + + PollingWatchKey(PollingWatchService watcher, + Path dir, + Object fileKey) + throws IOException + { + super(watcher); + this.dir = dir; + this.fileKey = fileKey; + this.valid = true; + this.tickCount = 0; + this.entries = new HashMap(); + + // get the initial entries in the directory + DirectoryStream stream = dir.newDirectoryStream(); + try { + for (Path entry: stream) { + // don't follow links + long lastModified = Attributes + .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) + .lastModifiedTime(); + entries.put(entry.getName(), + new CacheEntry(lastModified, tickCount)); + } + } catch (ConcurrentModificationException cme) { + // thrown if directory iteration fails + Throwable cause = cme.getCause(); + if (cause != null && cause instanceof IOException) + throw (IOException)cause; + throw new AssertionError(cme); + } finally { + stream.close(); + } + } + + FileRef directory() { + return dir; + } + + Object fileKey() { + return fileKey; + } + + @Override + public boolean isValid() { + return valid; + } + + void invalidate() { + valid = false; + } + + // enables periodic polling + void enable(Set> events, long period) { + synchronized (this) { + // update the events + this.events = events; + + // create the periodic task + Runnable thunk = new Runnable() { public void run() { poll(); }}; + this.poller = scheduledExecutor + .scheduleAtFixedRate(thunk, period, period, TimeUnit.SECONDS); + } + } + + // disables periodic polling + void disable() { + synchronized (this) { + if (poller != null) + poller.cancel(false); + } + } + + @Override + public void cancel() { + valid = false; + synchronized (map) { + map.remove(fileKey()); + } + disable(); + } + + /** + * Polls the directory to detect for new files, modified files, or + * deleted files. + */ + synchronized void poll() { + if (!valid) { + return; + } + + // update tick + tickCount++; + + // open directory + DirectoryStream stream = null; + try { + stream = dir.newDirectoryStream(); + } catch (IOException x) { + // directory is no longer accessible so cancel key + cancel(); + signal(); + return; + } + + // iterate over all entries in directory + try { + for (Path entry: stream) { + long lastModified = 0L; + try { + lastModified = Attributes + .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) + .lastModifiedTime(); + } catch (IOException x) { + // unable to get attributes of entry. If file has just + // been deleted then we'll report it as deleted on the + // next poll + continue; + } + + // lookup cache + CacheEntry e = entries.get(entry.getName()); + if (e == null) { + // new file found + entries.put(entry.getName(), + new CacheEntry(lastModified, tickCount)); + + // queue ENTRY_CREATE if event enabled + if (events.contains(StandardWatchEventKind.ENTRY_CREATE)) { + signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getName()); + continue; + } else { + // if ENTRY_CREATE is not enabled and ENTRY_MODIFY is + // enabled then queue event to avoid missing out on + // modifications to the file immediately after it is + // created. + if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) { + signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName()); + } + } + continue; + } + + // check if file has changed + if (e.lastModified != lastModified) { + if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) { + signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName()); + } + } + // entry in cache so update poll time + e.update(lastModified, tickCount); + + } + } catch (ConcurrentModificationException x) { + // FIXME - should handle this + } finally { + + // close directory stream + try { + stream.close(); + } catch (IOException x) { + // ignore + } + } + + // iterate over cache to detect entries that have been deleted + Iterator> i = entries.entrySet().iterator(); + while (i.hasNext()) { + Map.Entry mapEntry = i.next(); + CacheEntry entry = mapEntry.getValue(); + if (entry.lastTickCount() != tickCount) { + Path name = mapEntry.getKey(); + // remove from map and queue delete event (if enabled) + i.remove(); + if (events.contains(StandardWatchEventKind.ENTRY_DELETE)) { + signalEvent(StandardWatchEventKind.ENTRY_DELETE, name); + } + } + } + } + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/Reflect.java b/jdk/src/share/classes/sun/nio/fs/Reflect.java new file mode 100644 index 00000000000..d425ef2498a --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/Reflect.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Utility class for reflection. + */ + +class Reflect { + private Reflect() {} + + private static void setAccessible(final AccessibleObject ao) { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + ao.setAccessible(true); + return null; + }}); + } + + /** + * Lookup the field of a given class. + */ + static Field lookupField(String className, String fieldName) { + try { + Class cl = Class.forName(className); + Field f = cl.getDeclaredField(fieldName); + setAccessible(f); + return f; + } catch (ClassNotFoundException x) { + throw new AssertionError(x); + } catch (NoSuchFieldException x) { + throw new AssertionError(x); + } + } +} diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index 2a16b983f33..07c78e2959a 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Enumeration; -import java.util.List; import java.util.StringTokenizer; import java.net.InetAddress; import java.net.UnknownHostException; @@ -74,7 +73,7 @@ public class Config { private String defaultRealm; // default kdc realm. // used for native interface - private static native String getWindowsDirectory(); + private static native String getWindowsDirectory(boolean isSystem); /** @@ -156,11 +155,7 @@ public class Config { configFile = loadConfigFile(); stanzaTable = parseStanzaTable(configFile); } catch (IOException ioe) { - KrbException ke = new KrbException("Could not load " + - "configuration file " + - ioe.getMessage()); - ke.initCause(ioe); - throw(ke); + // No krb5.conf, no problem. We'll use DNS etc. } } } @@ -661,38 +656,37 @@ public class Config { } /** - * Gets the default configuration file name. The file will be searched - * in a list of possible loations in the following order: - * 1. the location and file name defined by system property - * "java.security.krb5.conf", - * 2. at Java home lib\security directory with "krb5.conf" name, - * 3. "krb5.ini" at Java home, - * 4. at windows directory with the name of "krb5.ini" for Windows, - * /etc/krb5/krb5.conf for Solaris, /etc/krb5.conf for Linux. + * Gets the default configuration file name. This method will never + * return null. + * + * If the system property "java.security.krb5.conf" is defined, we'll + * use its value, no matter if the file exists or not. Otherwise, + * the file will be searched in a list of possible loations in the + * following order: + * + * 1. at Java home lib\security directory with "krb5.conf" name, + * 2. at windows directory with the name of "krb5.ini" for Windows, + * /etc/krb5/krb5.conf for Solaris, /etc/krb5.conf otherwise. + * + * Note: When the Terminal Service is started in Windows (from 2003), + * there are two kinds of Windows directories: A system one (say, + * C:\Windows), and a user-private one (say, C:\Users\Me\Windows). + * We will first look for krb5.ini in the user-private one. If not + * found, try the system one instead. */ private String getFileName() { String name = java.security.AccessController.doPrivileged( new sun.security.action. GetPropertyAction("java.security.krb5.conf")); - if (name != null) { - boolean temp = - java.security.AccessController.doPrivileged( - new FileExistsAction(name)); - if (temp) - return name; - } else { + if (name == null) { name = java.security.AccessController.doPrivileged( new sun.security.action. GetPropertyAction("java.home")) + File.separator + "lib" + File.separator + "security" + File.separator + "krb5.conf"; - boolean temp = - java.security.AccessController.doPrivileged( - new FileExistsAction(name)); - if (temp) { - return name; - } else { + if (!fileExists(name)) { + name = null; String osname = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("os.name")); @@ -703,19 +697,35 @@ public class Config { // ignore exceptions } if (Credentials.alreadyLoaded) { - if ((name = getWindowsDirectory()) == null) { - name = "c:\\winnt\\krb5.ini"; - } else if (name.endsWith("\\")) { - name += "krb5.ini"; - } else { - name += "\\krb5.ini"; + String path = getWindowsDirectory(false); + if (path != null) { + if (path.endsWith("\\")) { + path = path + "krb5.ini"; + } else { + path = path + "\\krb5.ini"; + } + if (fileExists(path)) { + name = path; + } } - } else { + if (name == null) { + path = getWindowsDirectory(true); + if (path != null) { + if (path.endsWith("\\")) { + path = path + "krb5.ini"; + } else { + path = path + "\\krb5.ini"; + } + name = path; + } + } + } + if (name == null) { name = "c:\\winnt\\krb5.ini"; } } else if (osname.startsWith("SunOS")) { name = "/etc/krb5/krb5.conf"; - } else if (osname.startsWith("Linux")) { + } else { name = "/etc/krb5.conf"; } } @@ -1042,7 +1052,12 @@ public class Config { public boolean useDNS(String name) { String value = getDefault(name, "libdefaults"); if (value == null) { - return getDefaultBooleanValue("dns_fallback", "libdefaults"); + value = getDefault("dns_fallback", "libdefaults"); + if ("false".equalsIgnoreCase(value)) { + return false; + } else { + return true; + } } else { return value.equalsIgnoreCase("true"); } @@ -1064,12 +1079,39 @@ public class Config { /** * Gets default realm. + * @throws KrbException where no realm can be located + * @return the default realm, always non null */ public String getDefaultRealm() throws KrbException { + Exception cause = null; String realm = getDefault("default_realm", "libdefaults"); if ((realm == null) && useDNS_Realm()) { // use DNS to locate Kerberos realm - realm = getRealmFromDNS(); + try { + realm = getRealmFromDNS(); + } catch (KrbException ke) { + cause = ke; + } + } + if (realm == null) { + realm = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + @Override + public String run() { + String osname = System.getProperty("os.name"); + if (osname.startsWith("Windows")) { + return System.getenv("USERDNSDOMAIN"); + } + return null; + } + }); + } + if (realm == null) { + KrbException ke = new KrbException("Cannot locate default realm"); + if (cause != null) { + ke.initCause(cause); + } + throw ke; } return realm; } @@ -1077,17 +1119,48 @@ public class Config { /** * Returns a list of KDC's with each KDC separated by a space * - * @param realm the realm for which the master KDC is desired - * @return the list of KDCs + * @param realm the realm for which the KDC list is desired + * @throws KrbException if there's no way to find KDC for the realm + * @return the list of KDCs separated by a space, always non null */ public String getKDCList(String realm) throws KrbException { if (realm == null) { realm = getDefaultRealm(); } + Exception cause = null; String kdcs = getDefault("kdc", realm); if ((kdcs == null) && useDNS_KDC()) { // use DNS to locate KDC - kdcs = getKDCFromDNS(realm); + try { + kdcs = getKDCFromDNS(realm); + } catch (KrbException ke) { + cause = ke; + } + } + if (kdcs == null) { + kdcs = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + @Override + public String run() { + String osname = System.getProperty("os.name"); + if (osname.startsWith("Windows")) { + String logonServer = System.getenv("LOGONSERVER"); + if (logonServer != null + && logonServer.startsWith("\\\\")) { + logonServer = logonServer.substring(2); + } + return logonServer; + } + return null; + } + }); + } + if (kdcs == null) { + KrbException ke = new KrbException("Cannot locate KDC"); + if (cause != null) { + ke.initCause(cause); + } + throw ke; } return kdcs; } @@ -1102,7 +1175,7 @@ public class Config { String realm = null; String hostName = null; try { - hostName = InetAddress.getLocalHost().getHostName(); + hostName = InetAddress.getLocalHost().getCanonicalHostName(); } catch (UnknownHostException e) { KrbException ke = new KrbException(Krb5.KRB_ERR_GENERIC, "Unable to locate Kerberos realm: " + e.getMessage()); @@ -1171,6 +1244,11 @@ public class Config { return kdcs; } + private boolean fileExists(String name) { + return java.security.AccessController.doPrivileged( + new FileExistsAction(name)); + } + static class FileExistsAction implements java.security.PrivilegedAction { diff --git a/jdk/src/share/classes/sun/security/krb5/KrbServiceLocator.java b/jdk/src/share/classes/sun/security/krb5/KrbServiceLocator.java index 0efe37d1aa4..fefcdbde054 100644 --- a/jdk/src/share/classes/sun/security/krb5/KrbServiceLocator.java +++ b/jdk/src/share/classes/sun/security/krb5/KrbServiceLocator.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,7 +133,7 @@ class KrbServiceLocator { */ static String[] getKerberosService(String realmName, String protocol) { - String dnsUrl = "dns:///_kerberos." + protocol + realmName; + String dnsUrl = "dns:///_kerberos." + protocol + "." + realmName; String[] hostports = null; try { diff --git a/jdk/src/share/classes/sun/security/krb5/Realm.java b/jdk/src/share/classes/sun/security/krb5/Realm.java index 1dbffe26445..a34745d8770 100644 --- a/jdk/src/share/classes/sun/security/krb5/Realm.java +++ b/jdk/src/share/classes/sun/security/krb5/Realm.java @@ -39,7 +39,6 @@ import sun.security.krb5.RealmException; import sun.security.krb5.internal.Krb5; import sun.security.util.*; import java.io.IOException; -import java.io.OutputStream; import java.util.StringTokenizer; import java.util.Vector; import java.util.Stack; @@ -364,7 +363,6 @@ public class Realm implements Cloneable { } String tempTarget = null, tempRealm = null; - StringTokenizer strTok = null; Stack iStack = new Stack (); /* @@ -382,7 +380,7 @@ public class Realm implements Cloneable { tempTarget = sRealm; } - do { + out: do { if (DEBUG) { count++; System.out.println(">>> Realm parseCapaths: loop " + @@ -400,15 +398,21 @@ public class Realm implements Cloneable { /* * We have one or more space-separated intermediary realms. - * Stack them. + * Stack them. A null is always added between intermedies of + * different targets. When this null is popped, it means none + * of the intermedies for this target is useful (because of + * infinite loop), the target is then removed from the partial + * tempList, and the next possible intermediary is tried. */ - strTok = new StringTokenizer(intermediaries, " "); - while (strTok.hasMoreTokens()) + iStack.push(null); + String[] ints = intermediaries.split("\\s+"); + for (int i = ints.length-1; i>=0; i--) { - tempRealm = strTok.nextToken(); - if (!tempRealm.equals(PrincipalName. - REALM_COMPONENT_SEPARATOR_STR) && - !iStack.contains(tempRealm)) { + tempRealm = ints[i]; + if (tempRealm.equals(PrincipalName.REALM_COMPONENT_SEPARATOR_STR)) { + break out; + } + if (!tempList.contains(tempRealm)) { iStack.push(tempRealm); if (DEBUG) { System.out.println(">>> Realm parseCapaths: loop " + @@ -418,16 +422,18 @@ public class Realm implements Cloneable { } } else if (DEBUG) { System.out.println(">>> Realm parseCapaths: loop " + - count + ": ignoring realm: [" + tempRealm + "]"); } } - } else if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + - count + - ": no intermediaries"); + } else { + if (DEBUG) { + System.out.println(">>> Realm parseCapaths: loop " + + count + + ": no intermediaries"); + } + break; } /* @@ -435,7 +441,12 @@ public class Realm implements Cloneable { */ try { - tempTarget = iStack.pop(); + while ((tempTarget = iStack.pop()) == null) { + tempList.removeElementAt(tempList.size()-1); + if (DEBUG) { + System.out.println(">>> Realm parseCapaths: backtrack, remove tail"); + } + } } catch (EmptyStackException exc) { tempTarget = null; } diff --git a/jdk/src/share/classes/sun/security/provider/X509Factory.java b/jdk/src/share/classes/sun/security/provider/X509Factory.java index 8fc755cc83d..ce0d120ae8d 100644 --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -638,10 +638,15 @@ is) // First read all of the data that is found between // the "-----BEGIN" and "-----END" boundaries into a buffer. String temp; - if ((temp=readLine(br))==null || !temp.startsWith("-----BEGIN")) { - throw new IOException("Unsupported encoding"); - } else { + while (true) { + temp=readLine(br); + if (temp == null) { + throw new IOException("Unsupported encoding"); + } len += temp.length(); + if (temp.startsWith("-----BEGIN")) { + break; + } } StringBuffer strBuf = new StringBuffer(); while ((temp=readLine(br))!=null && !temp.startsWith("-----END")) { @@ -683,22 +688,11 @@ is) * Determines if input is binary or Base64 encoded. */ private boolean isBase64(InputStream is) throws IOException { - if (is.available() >= 10) { - is.mark(10); + if (is.available() >= 1) { + is.mark(1); int c1 = is.read(); - int c2 = is.read(); - int c3 = is.read(); - int c4 = is.read(); - int c5 = is.read(); - int c6 = is.read(); - int c7 = is.read(); - int c8 = is.read(); - int c9 = is.read(); - int c10 = is.read(); is.reset(); - if (c1 == '-' && c2 == '-' && c3 == '-' && c4 == '-' - && c5 == '-' && c6 == 'B' && c7 == 'E' && c8 == 'G' - && c9 == 'I' && c10 == 'N') { + if (c1 != DerValue.tag_Sequence) { return true; } else { return false; diff --git a/jdk/src/share/classes/sun/security/ssl/AppInputStream.java b/jdk/src/share/classes/sun/security/ssl/AppInputStream.java index d638b8f46e9..2ca889593c0 100644 --- a/jdk/src/share/classes/sun/security/ssl/AppInputStream.java +++ b/jdk/src/share/classes/sun/security/ssl/AppInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,14 @@ class AppInputStream extends InputStream { */ public synchronized 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; + } + if (c.checkEOF()) { return -1; } diff --git a/jdk/src/share/classes/sun/security/ssl/AppOutputStream.java b/jdk/src/share/classes/sun/security/ssl/AppOutputStream.java index d039cacb8b2..d8c78a8eb50 100644 --- a/jdk/src/share/classes/sun/security/ssl/AppOutputStream.java +++ b/jdk/src/share/classes/sun/security/ssl/AppOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,18 +58,25 @@ class AppOutputStream extends OutputStream { */ synchronized public void write(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; + } + // check if the Socket is invalid (error or closed) c.checkWrite(); - // + // Always flush at the end of each application level record. // This lets application synchronize read and write streams // however they like; if we buffered here, they couldn't. - // - // NOTE: *must* call c.writeRecord() even for len == 0 try { do { int howmuch = Math.min(len, r.availableDataBytes()); + // NOTE: *must* call c.writeRecord() even for howmuch == 0 if (howmuch > 0) { r.write(b, off, howmuch); off += howmuch; diff --git a/jdk/src/share/classes/sun/security/ssl/ByteBufferInputStream.java b/jdk/src/share/classes/sun/security/ssl/ByteBufferInputStream.java index 9c484d87ed3..d69e2bfdc54 100644 --- a/jdk/src/share/classes/sun/security/ssl/ByteBufferInputStream.java +++ b/jdk/src/share/classes/sun/security/ssl/ByteBufferInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,7 @@ class ByteBufferInputStream extends InputStream { if (b == null) { throw new NullPointerException(); - } else if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { + } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java index c98f1cc2c26..3aeef2d8eee 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,88 +41,112 @@ import javax.net.ssl.SSLSessionBindingEvent; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; -import sun.misc.Cache; +import sun.security.util.Cache; -final class SSLSessionContextImpl implements SSLSessionContext -{ - private Cache sessionCache = new Cache(); - private Cache sessionHostPortCache = new Cache(); - private int cacheLimit; - private long timeoutMillis; +final class SSLSessionContextImpl implements SSLSessionContext { + private Cache sessionCache; // session cache, session id as key + private Cache sessionHostPortCache; // session cache, "host:port" as key + private int cacheLimit; // the max cache size + private int timeout; // timeout in seconds + private static final Debug debug = Debug.getInstance("ssl"); - // file private - SSLSessionContextImpl() - { - cacheLimit = getCacheLimit(); - timeoutMillis = 86400000; // default, 24 hours + // package private + SSLSessionContextImpl() { + cacheLimit = getDefaultCacheLimit(); // default cache size + timeout = 86400; // default, 24 hours + + // use soft reference + sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout); + sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout); } /** - * Returns the SSL session object associated with the - * specific session ID passed. + * Returns the SSLSession bound to the specified session id. */ - public SSLSession getSession(byte[] id) - { - SSLSession sess = (SSLSession) sessionCache.get( - new SessionId(id)); - return checkTimeValidity(sess); + public SSLSession getSession(byte[] sessionId) { + if (sessionId == null) { + throw new NullPointerException("session id cannot be null"); + } + + SSLSessionImpl sess = + (SSLSessionImpl)sessionCache.get(new SessionId(sessionId)); + if (!isTimedout(sess)) { + return sess; + } + + return null; } /** * Returns an enumeration of the active SSL sessions. */ public Enumeration getIds() { - Vector v = new Vector(sessionCache.size()); - SessionId sessId; + SessionCacheVisitor scVisitor = new SessionCacheVisitor(); + sessionCache.accept(scVisitor); - for (Enumeration e = sessionCache.keys(); e.hasMoreElements(); ) { - sessId = (SessionId) e.nextElement(); - if (!isTimedout((SSLSession)sessionCache.get(sessId))) - v.addElement(sessId.getId()); - } - return v.elements(); + return scVisitor.getSessionIds(); } + /** + * Sets the timeout limit for cached SSLSession objects + * + * Note that after reset the timeout, the cached session before + * should be timed within the shorter one of the old timeout and the + * new timeout. + */ public void setSessionTimeout(int seconds) throws IllegalArgumentException { - if (seconds < 0) + if (seconds < 0) { throw new IllegalArgumentException(); - timeoutMillis = seconds * 1000L; + } + + if (timeout != seconds) { + sessionCache.setTimeout(seconds); + sessionHostPortCache.setTimeout(seconds); + timeout = seconds; + } } + /** + * Gets the timeout limit for cached SSLSession objects + */ public int getSessionTimeout() { - return (int) (timeoutMillis / 1000); + return timeout; } + /** + * Sets the size of the cache used for storing + * SSLSession objects. + */ public void setSessionCacheSize(int size) throws IllegalArgumentException { if (size < 0) throw new IllegalArgumentException(); - cacheLimit = size; - /** - * If cache size limit is reduced, when the cache is full to its - * previous limit, trim the cache before its contents - * are used. - */ - if ((cacheLimit != 0) && (sessionCache.size() > cacheLimit)) - adjustCacheSizeTo(cacheLimit); + if (cacheLimit != size) { + sessionCache.setCapacity(size); + sessionHostPortCache.setCapacity(size); + cacheLimit = size; + } } + /** + * Gets the size of the cache used for storing + * SSLSession objects. + */ public int getSessionCacheSize() { return cacheLimit; } + + // package-private method, used ONLY by ServerHandshaker SSLSessionImpl get(byte[] id) { - return (SSLSessionImpl) getSession(id); + return (SSLSessionImpl)getSession(id); } - /** - * Returns the SSL session object associated with the - * specific host name and port number passed. - */ + // package-private method, used ONLY by ClientHandshaker SSLSessionImpl get(String hostname, int port) { /* * If no session caching info is available, we won't @@ -131,96 +155,51 @@ final class SSLSessionContextImpl implements SSLSessionContext if (hostname == null && port == -1) { return null; } - SSLSession sess = (SSLSessionImpl) sessionHostPortCache - .get(getKey(hostname, port)); - return (SSLSessionImpl) checkTimeValidity(sess); + + SSLSessionImpl sess = + (SSLSessionImpl)sessionHostPortCache.get(getKey(hostname, port)); + if (!isTimedout(sess)) { + return sess; + } + + return null; } private String getKey(String hostname, int port) { - return (hostname + ":" + String.valueOf(port)) - .toLowerCase(); + return (hostname + ":" + String.valueOf(port)).toLowerCase(); } + // cache a SSLSession + // + // In SunJSSE implementation, a session is created while getting a + // client hello or a server hello message, and cached while the + // handshaking finished. + // Here we time the session from the time it cached instead of the + // time it created, which is a little longer than the expected. So + // please do check isTimedout() while getting entry from the cache. void put(SSLSessionImpl s) { - // make space for the new session to be added - if ((cacheLimit != 0) && (sessionCache.size() >= cacheLimit)) - adjustCacheSizeTo(cacheLimit - 1); - - /* - * Can always add the session id. - */ sessionCache.put(s.getSessionId(), s); - /* - * If no hostname/port info is available, don't add this one. - */ + // If no hostname/port info is available, don't add this one. if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) { sessionHostPortCache.put( getKey(s.getPeerHost(), s.getPeerPort()), s); } + s.setContext(this); } - private void adjustCacheSizeTo(int targetSize) { - - int cacheSize = sessionCache.size(); - - if (targetSize < 0) - return; - - while (cacheSize > targetSize) { - SSLSessionImpl lru = null; - SSLSessionImpl s = null; - Enumeration e; - - if (debug != null && Debug.isOn("sessioncache")) { - System.out.println("exceeded cache limit of " + cacheLimit); - } - - /* - * Count the number of elements in the cache. The size() method - * does not reflect the cache entries that are no longer available, - * i.e entries that are garbage collected (the cache entries are - * held using soft references and are garbage collected when not - * in use). - */ - int count; - for (count = 0, e = sessionCache.elements(); - e.hasMoreElements(); count++) { - try { - s = (SSLSessionImpl)e.nextElement(); - } catch (NoSuchElementException nsee) { - break; - } - if (isTimedout(s)) { - lru = s; - break; - } else if ((lru == null) || (s.getLastAccessedTime() - < lru.getLastAccessedTime())) { - lru = s; - } - } - if ((lru != null) && (count > targetSize)) { - if (debug != null && Debug.isOn("sessioncache")) { - System.out.println("uncaching " + lru); - } - lru.invalidate(); - count--; // element removed from the cache - } - cacheSize = count; + // package-private method, remove a cached SSLSession + void remove(SessionId key) { + SSLSessionImpl s = (SSLSessionImpl)sessionCache.get(key); + if (s != null) { + sessionCache.remove(key); + sessionHostPortCache.remove( + getKey(s.getPeerHost(), s.getPeerPort())); } } - // file private - void remove(SessionId key) - { - SSLSessionImpl s = (SSLSessionImpl) sessionCache.get(key); - sessionCache.remove(key); - sessionHostPortCache.remove(getKey(s.getPeerHost(), - s.getPeerPort())); - } - - private int getCacheLimit() { + private int getDefaultCacheLimit() { int cacheLimit = 0; try { String s = java.security.AccessController.doPrivileged( @@ -237,21 +216,40 @@ final class SSLSessionContextImpl implements SSLSessionContext return (cacheLimit > 0) ? cacheLimit : 0; } - SSLSession checkTimeValidity(SSLSession sess) { - if (isTimedout(sess)) { - sess.invalidate(); - return null; - } else - return sess; - } - boolean isTimedout(SSLSession sess) { - if (timeoutMillis == 0) + if (timeout == 0) { return false; - if ((sess != null) && - ((sess.getCreationTime() + timeoutMillis) - <= (System.currentTimeMillis()))) + } + + if ((sess != null) && ((sess.getCreationTime() + timeout * 1000L) + <= (System.currentTimeMillis()))) { + sess.invalidate(); return true; + } + return false; } + + final class SessionCacheVisitor + implements sun.security.util.Cache.CacheVisitor { + Vector ids = null; + + // public void visit(java.util.Map map) {} + public void visit(java.util.Map map) { + ids = new Vector(map.size()); + + for (Object key : map.keySet()) { + SSLSessionImpl value = (SSLSessionImpl)map.get(key); + if (!isTimedout(value)) { + ids.addElement(((SessionId)key).getId()); + } + } + } + + public Enumeration getSessionIds() { + return ids != null ? ids.elements() : + new Vector().elements(); + } + } + } diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java index 7974f1b13b4..820954f9613 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -368,7 +368,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { super(); this.host = host; init(context, false); - SocketAddress socketAddress = new InetSocketAddress(host, port); + SocketAddress socketAddress = + host != null ? new InetSocketAddress(host, port) : + new InetSocketAddress(InetAddress.getByName(null), port); connect(socketAddress, 0); } @@ -409,7 +411,9 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { this.host = host; init(context, false); bind(new InetSocketAddress(localAddr, localPort)); - SocketAddress socketAddress = new InetSocketAddress(host, port); + SocketAddress socketAddress = + host != null ? new InetSocketAddress(host, port) : + new InetSocketAddress(InetAddress.getByName(null), port); connect(socketAddress, 0); } @@ -1829,7 +1833,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { } synchronized String getHost() { - if (host == null) { + // Note that the host may be null or empty for localhost. + if (host == null || host.length() == 0) { host = getInetAddress().getHostName(); } return host; diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 220dbd033b1..e99c40d9d8c 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,10 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import sun.misc.BASE64Decoder; +import sun.security.pkcs.PKCS10Attribute; +import sun.security.pkcs.PKCS9Attribute; +import sun.security.util.DerValue; import sun.security.x509.*; import static java.security.KeyStore.*; @@ -85,7 +89,6 @@ import static java.security.KeyStore.*; * * @since 1.2 */ - public final class KeyTool { private boolean debug = false; @@ -100,6 +103,8 @@ public final class KeyTool { private String dname = null; private String dest = null; private String filename = null; + private String infilename = null; + private String outfilename = null; private String srcksfname = null; // User-specified providers are added before any command is called. @@ -117,7 +122,6 @@ public final class KeyTool { private char[] storePassNew = null; private char[] keyPass = null; private char[] keyPassNew = null; - private char[] oldPass = null; private char[] newPass = null; private char[] destKeyPass = null; private char[] srckeyPass = null; @@ -140,6 +144,8 @@ public final class KeyTool { private Set passwords = new HashSet (); private String startDate = null; + private List v3ext = new ArrayList (); + private static final int CERTREQ = 1; private static final int CHANGEALIAS = 2; private static final int DELETE = 3; @@ -156,6 +162,8 @@ public final class KeyTool { private static final int PRINTCERT = 13; private static final int SELFCERT = 14; private static final int STOREPASSWD = 15; + private static final int GENCERT = 16; + private static final int PRINTCERTREQ = 17; private static final Class[] PARAM_STRING = { String.class }; @@ -184,7 +192,9 @@ public final class KeyTool { private void run(String[] args, PrintStream out) throws Exception { try { parseArgs(args); - doCommands(out); + if (command != -1) { + doCommands(out); + } } catch (Exception e) { System.out.println(rb.getString("keytool error: ") + e); if (verbose) { @@ -214,7 +224,10 @@ public final class KeyTool { */ void parseArgs(String[] args) { - if (args.length == 0) usage(); + if (args.length == 0) { + usage(); + return; + } int i=0; @@ -260,6 +273,10 @@ public final class KeyTool { command = IMPORTKEYSTORE; } else if (collator.compare(flags, "-genseckey") == 0) { command = GENSECKEY; + } else if (collator.compare(flags, "-gencert") == 0) { + command = GENCERT; + } else if (collator.compare(flags, "-printcertreq") == 0) { + command = PRINTCERTREQ; } /* @@ -337,9 +354,18 @@ public final class KeyTool { } else if (collator.compare(flags, "-validity") == 0) { if (++i == args.length) errorNeedArgument(flags); validity = Long.parseLong(args[i]); + } else if (collator.compare(flags, "-ext") == 0) { + if (++i == args.length) errorNeedArgument(flags); + v3ext.add(args[i]); } else if (collator.compare(flags, "-file") == 0) { if (++i == args.length) errorNeedArgument(flags); filename = args[i]; + } else if (collator.compare(flags, "-infile") == 0) { + if (++i == args.length) errorNeedArgument(flags); + infilename = args[i]; + } else if (collator.compare(flags, "-outfile") == 0) { + if (++i == args.length) errorNeedArgument(flags); + outfilename = args[i]; } else if (collator.compare(flags, "-sslserver") == 0) { if (++i == args.length) errorNeedArgument(flags); sslserver = args[i]; @@ -364,7 +390,7 @@ public final class KeyTool { } } providers.add( - new Pair(providerClass, providerArg)); + Pair.of(providerClass, providerArg)); } /* @@ -404,6 +430,10 @@ public final class KeyTool { } } + boolean isKeyStoreRelated(int cmd) { + return cmd != PRINTCERT && cmd != PRINTCERTREQ; + } + /** * Execute the commands. */ @@ -568,7 +598,7 @@ public final class KeyTool { // the default, which is located in $HOME/.keystore. // If the command is "genkey", "identitydb", "import", or "printcert", // it is OK not to have a keystore. - if (command != PRINTCERT) { + if (isKeyStoreRelated(command)) { if (ksfname == null) { ksfname = System.getProperty("user.home") + File.separator + ".keystore"; @@ -721,7 +751,7 @@ public final class KeyTool { } } else if (!protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype) - && !(command == PRINTCERT)) { + && isKeyStoreRelated(command)) { // here we have EXPORTCERT and LIST (info valid until STOREPASSWD) System.err.print(rb.getString("Enter keystore password: ")); System.err.flush(); @@ -763,7 +793,7 @@ public final class KeyTool { // Create a certificate factory if (command == PRINTCERT || command == IMPORTCERT - || command == IDENTITYDB) { + || command == IDENTITYDB) { cf = CertificateFactory.getInstance("X509"); } @@ -930,6 +960,41 @@ public final class KeyTool { storePassNew = getNewPasswd("keystore password", storePass); } kssave = true; + } else if (command == GENCERT) { + if (alias == null) { + alias = keyAlias; + } + InputStream inStream = System.in; + if (infilename != null) { + inStream = new FileInputStream(infilename); + } + PrintStream ps = null; + if (outfilename != null) { + ps = new PrintStream(new FileOutputStream(outfilename)); + out = ps; + } + try { + doGenCert(alias, sigAlgName, inStream, out); + } finally { + if (inStream != System.in) { + inStream.close(); + } + if (ps != null) { + ps.close(); + } + } + } else if (command == PRINTCERTREQ) { + InputStream inStream = System.in; + if (filename != null) { + inStream = new FileInputStream(filename); + } + try { + doPrintCertReq(inStream, out); + } finally { + if (inStream != System.in) { + inStream.close(); + } + } } // If we need to save the keystore, do so. @@ -961,6 +1026,91 @@ public final class KeyTool { } } + /** + * Generate a certificate: Read PKCS10 request from in, and print + * certificate to out. Use alias as CA, sigAlgName as the signature + * type. + */ + private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStream out) + throws Exception { + + + Certificate signerCert = keyStore.getCertificate(alias); + byte[] encoded = signerCert.getEncoded(); + X509CertImpl signerCertImpl = new X509CertImpl(encoded); + X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." + + CertificateSubjectName.DN_NAME); + + Date firstDate = getStartDate(startDate); + Date lastDate = new Date(); + lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L); + CertificateValidity interval = new CertificateValidity(firstDate, + lastDate); + + PrivateKey privateKey = (PrivateKey)recoverKey(alias, storePass, keyPass).fst; + if (sigAlgName == null) { + sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm()); + } + Signature signature = Signature.getInstance(sigAlgName); + signature.initSign(privateKey); + + X500Signer signer = new X500Signer(signature, owner); + + X509CertInfo info = new X509CertInfo(); + info.set(X509CertInfo.VALIDITY, interval); + info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber + ((int)(firstDate.getTime()/1000))); + info.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + info.set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(signer.getAlgorithmId())); + info.set(X509CertInfo.ISSUER, + new CertificateIssuerName(signer.getSigner())); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + boolean canRead = false; + StringBuffer sb = new StringBuffer(); + while (true) { + String s = reader.readLine(); + if (s == null) break; + // OpenSSL does not use NEW + //if (s.startsWith("-----BEGIN NEW CERTIFICATE REQUEST-----")) { + if (s.startsWith("-----BEGIN") && s.indexOf("REQUEST") >= 0) { + canRead = true; + //} else if (s.startsWith("-----END NEW CERTIFICATE REQUEST-----")) { + } else if (s.startsWith("-----END") && s.indexOf("REQUEST") >= 0) { + break; + } else if (canRead) { + sb.append(s); + } + } + byte[] rawReq = new BASE64Decoder().decodeBuffer(new String(sb)); + PKCS10 req = new PKCS10(rawReq); + + info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo())); + info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(req.getSubjectName())); + CertificateExtensions reqex = null; + Iterator attrs = req.getAttributes().getAttributes().iterator(); + while (attrs.hasNext()) { + PKCS10Attribute attr = attrs.next(); + if (attr.getAttributeId().equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) { + reqex = (CertificateExtensions)attr.getAttributeValue(); + } + } + CertificateExtensions ext = createV3Extensions( + reqex, + null, + v3ext, + req.getSubjectPublicKeyInfo(), + signerCert.getPublicKey()); + info.set(X509CertInfo.EXTENSIONS, ext); + X509CertImpl cert = new X509CertImpl(info); + cert.sign(privateKey, sigAlgName); + dumpCert(cert, out); + } + /** * Creates a PKCS#10 cert signing request, corresponding to the * keys (and name) associated with a given alias. @@ -972,10 +1122,10 @@ public final class KeyTool { alias = keyAlias; } - Object[] objs = recoverKey(alias, storePass, keyPass); - PrivateKey privKey = (PrivateKey)objs[0]; + Pair objs = recoverKey(alias, storePass, keyPass); + PrivateKey privKey = (PrivateKey)objs.fst; if (keyPass == null) { - keyPass = (char[])objs[1]; + keyPass = objs.snd; } Certificate cert = keyStore.getCertificate(alias); @@ -986,21 +1136,14 @@ public final class KeyTool { throw new Exception(form.format(source)); } PKCS10 request = new PKCS10(cert.getPublicKey()); + CertificateExtensions ext = createV3Extensions(null, null, v3ext, cert.getPublicKey(), null); + // Attribute name is not significant + request.getAttributes().setAttribute(X509CertInfo.EXTENSIONS, + new PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID, ext)); // Construct an X500Signer object, so that we can sign the request if (sigAlgName == null) { - // If no signature algorithm was specified at the command line, - // we choose one that is compatible with the selected private key - String keyAlgName = privKey.getAlgorithm(); - if ("DSA".equalsIgnoreCase(keyAlgName) - || "DSS".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithDSA"; - } else if ("RSA".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithRSA"; - } else { - throw new Exception(rb.getString - ("Cannot derive signature algorithm")); - } + sigAlgName = getCompatibleSigAlgName(privKey.getAlgorithm()); } Signature signature = Signature.getInstance(sigAlgName); @@ -1152,6 +1295,23 @@ public final class KeyTool { keyStore.setKeyEntry(alias, secKey, keyPass, null); } + /** + * If no signature algorithm was specified at the command line, + * we choose one that is compatible with the selected private key + */ + private static String getCompatibleSigAlgName(String keyAlgName) + throws Exception { + if ("DSA".equalsIgnoreCase(keyAlgName)) { + return "SHA1WithDSA"; + } else if ("RSA".equalsIgnoreCase(keyAlgName)) { + return "SHA1WithRSA"; + } else if ("EC".equalsIgnoreCase(keyAlgName)) { + return "SHA1withECDSA"; + } else { + throw new Exception(rb.getString + ("Cannot derive signature algorithm")); + } + } /** * Creates a new key pair and self-signed certificate. */ @@ -1179,16 +1339,7 @@ public final class KeyTool { } if (sigAlgName == null) { - if ("DSA".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithDSA"; - } else if ("RSA".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithRSA"; - } else if ("EC".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1withECDSA"; - } else { - throw new Exception(rb.getString - ("Cannot derive signature algorithm")); - } + sigAlgName = getCompatibleSigAlgName(keyAlgName); } CertAndKeyGen keypair = new CertAndKeyGen(keyAlgName, sigAlgName, providerName); @@ -1225,6 +1376,9 @@ public final class KeyTool { keyPass = promptForKeyPass(alias, null, storePass); } keyStore.setKeyEntry(alias, privKey, keyPass, chain); + + // resign so that -ext are applied. + doSelfCert(alias, null, sigAlgName); } /** @@ -1247,9 +1401,9 @@ public final class KeyTool { throw new Exception(form.format(source)); } - Object[] objs = recoverEntry(keyStore, orig, storePass, keyPass); - Entry entry = (Entry)objs[0]; - keyPass = (char[])objs[1]; + Pair objs = recoverEntry(keyStore, orig, storePass, keyPass); + Entry entry = objs.fst; + keyPass = objs.snd; PasswordProtection pp = null; @@ -1275,10 +1429,10 @@ public final class KeyTool { if (alias == null) { alias = keyAlias; } - Object[] objs = recoverKey(alias, storePass, keyPass); - Key privKey = (Key)objs[0]; + Pair objs = recoverKey(alias, storePass, keyPass); + Key privKey = objs.fst; if (keyPass == null) { - keyPass = (char[])objs[1]; + keyPass = objs.snd; } if (keyPassNew == null) { @@ -1629,8 +1783,8 @@ public final class KeyTool { } } - Object[] objs = recoverEntry(srckeystore, alias, srcstorePass, srckeyPass); - Entry entry = (Entry)objs[0]; + Pair objs = recoverEntry(srckeystore, alias, srcstorePass, srckeyPass); + Entry entry = objs.fst; PasswordProtection pp = null; @@ -1640,8 +1794,8 @@ public final class KeyTool { // so always try to protect with destKeyPass. if (destKeyPass != null) { pp = new PasswordProtection(destKeyPass); - } else if (objs[1] != null) { - pp = new PasswordProtection((char[])objs[1]); + } else if (objs.snd != null) { + pp = new PasswordProtection(objs.snd); } try { @@ -1726,9 +1880,50 @@ public final class KeyTool { } } + private void doPrintCertReq(InputStream in, PrintStream out) + throws Exception { + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + StringBuffer sb = new StringBuffer(); + boolean started = false; + while (true) { + String s = reader.readLine(); + if (s == null) break; + if (!started) { + if (s.startsWith("-----")) { + started = true; + } + } else { + if (s.startsWith("-----")) { + break; + } + sb.append(s); + } + } + PKCS10 req = new PKCS10(new BASE64Decoder().decodeBuffer(new String(sb))); + + PublicKey pkey = req.getSubjectPublicKeyInfo(); + out.printf(rb.getString("PKCS #10 Certificate Request (Version 1.0)\n" + + "Subject: %s\nPublic Key: %s format %s key\n"), + req.getSubjectName(), pkey.getFormat(), pkey.getAlgorithm()); + for (PKCS10Attribute attr: req.getAttributes().getAttributes()) { + ObjectIdentifier oid = attr.getAttributeId(); + if (oid.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) { + CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue(); + printExtensions(rb.getString("Extension Request:"), exts, out); + } else { + out.println(attr.getAttributeId()); + out.println(attr.getAttributeValue()); + } + } + if (debug) { + out.println(req); // Just to see more, say, public key length... + } + } + /** * Reads a certificate (or certificate chain) and prints its contents in - * a human readbable format. + * a human readable format. */ private void printCertFromStream(InputStream in, PrintStream out) throws Exception @@ -1840,7 +2035,18 @@ public final class KeyTool { inStream = new FileInputStream(filename); } try { - printCertFromStream(inStream, out); + // Read the full stream before feeding to X509Factory, + // otherwise, keytool -gencert | keytool -printcert + // might not work properly, since -gencert is slow + // and there's no data in the pipe at the beginning. + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + byte[] b = new byte[4096]; + while (true) { + int len = inStream.read(b); + if (len < 0) break; + bout.write(b, 0, len); + } + printCertFromStream(new ByteArrayInputStream(bout.toByteArray()), out); } finally { if (inStream != System.in) { inStream.close(); @@ -1859,27 +2065,14 @@ public final class KeyTool { alias = keyAlias; } - Object[] objs = recoverKey(alias, storePass, keyPass); - PrivateKey privKey = (PrivateKey)objs[0]; + Pair objs = recoverKey(alias, storePass, keyPass); + PrivateKey privKey = (PrivateKey)objs.fst; if (keyPass == null) - keyPass = (char[])objs[1]; + keyPass = objs.snd; // Determine the signature algorithm if (sigAlgName == null) { - // If no signature algorithm was specified at the command line, - // we choose one that is compatible with the selected private key - String keyAlgName = privKey.getAlgorithm(); - if ("DSA".equalsIgnoreCase(keyAlgName) - || "DSS".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithDSA"; - } else if ("RSA".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1WithRSA"; - } else if ("EC".equalsIgnoreCase(keyAlgName)) { - sigAlgName = "SHA1withECDSA"; - } else { - throw new Exception - (rb.getString("Cannot derive signature algorithm")); - } + sigAlgName = getCompatibleSigAlgName(privKey.getAlgorithm()); } // Get the old certificate @@ -1943,11 +2136,16 @@ public final class KeyTool { certInfo.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, sigAlgid); - // first upgrade to version 3 - certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); + CertificateExtensions ext = createV3Extensions( + null, + (CertificateExtensions)certInfo.get(X509CertInfo.EXTENSIONS), + v3ext, + oldCert.getPublicKey(), + null); + certInfo.set(X509CertInfo.EXTENSIONS, ext); // Sign the new certificate newCert = new X509CertImpl(certInfo); newCert.sign(privKey, sigAlgName); @@ -1985,10 +2183,10 @@ public final class KeyTool { alias = keyAlias; } - Object[] objs = recoverKey(alias, storePass, keyPass); - PrivateKey privKey = (PrivateKey)objs[0]; + Pair objs = recoverKey(alias, storePass, keyPass); + PrivateKey privKey = (PrivateKey)objs.fst; if (keyPass == null) { - keyPass = (char[])objs[1]; + keyPass = objs.snd; } Certificate userCert = keyStore.getCertificate(alias); @@ -2290,36 +2488,40 @@ public final class KeyTool { }; out.println(form.format(source)); - int extnum = 0; if (cert instanceof X509CertImpl) { X509CertImpl impl = (X509CertImpl)cert; - if (cert.getCriticalExtensionOIDs() != null) { - for (String extOID : cert.getCriticalExtensionOIDs()) { - if (extnum == 0) { - out.println(); - out.println(rb.getString("Extensions: ")); - out.println(); - } - out.println("#"+(++extnum)+": "+ - impl.getExtension(new ObjectIdentifier(extOID))); - } - } - if (cert.getNonCriticalExtensionOIDs() != null) { - for (String extOID : cert.getNonCriticalExtensionOIDs()) { - if (extnum == 0) { - out.println(); - out.println(rb.getString("Extensions: ")); - out.println(); - } - Extension ext = impl.getExtension(new ObjectIdentifier(extOID)); - if (ext != null) { - out.println("#"+(++extnum)+": "+ ext); - } else { - out.println("#"+(++extnum)+": "+ - impl.getUnparseableExtension(new ObjectIdentifier(extOID))); - } + X509CertInfo certInfo = (X509CertInfo)impl.get(X509CertImpl.NAME + + "." + + X509CertImpl.INFO); + CertificateExtensions exts = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + printExtensions(rb.getString("Extensions: "), exts, out); + } + } + + private static void printExtensions(String title, CertificateExtensions exts, PrintStream out) + throws Exception { + int extnum = 0; + Iterator i1 = exts.getAllExtensions().iterator(); + Iterator i2 = exts.getUnparseableExtensions().values().iterator(); + while (i1.hasNext() || i2.hasNext()) { + Extension ext = i1.hasNext()?i1.next():i2.next(); + if (extnum == 0) { + out.println(); + out.println(title); + out.println(); + } + out.print("#"+(++extnum)+": "+ ext); + if (ext.getClass() == Extension.class) { + byte[] v = ext.getExtensionValue(); + if (v.length == 0) { + out.println(rb.getString("(Empty value)")); + } else { + new sun.misc.HexDumpEncoder().encode(ext.getExtensionValue(), out); + out.println(); } } + out.println(); } } @@ -2470,7 +2672,7 @@ public final class KeyTool { * recovered private key, and the 2nd element is the password used to * recover it. */ - private Object[] recoverKey(String alias, char[] storePass, + private Pair recoverKey(String alias, char[] storePass, char[] keyPass) throws Exception { @@ -2510,7 +2712,7 @@ public final class KeyTool { key = keyStore.getKey(alias, keyPass); } - return new Object[] {key, keyPass}; + return Pair.of(key, keyPass); } /** @@ -2520,7 +2722,7 @@ public final class KeyTool { * recovered entry, and the 2nd element is the password used to * recover it (null if no password). */ - private Object[] recoverEntry(KeyStore ks, + private Pair recoverEntry(KeyStore ks, String alias, char[] pstore, char[] pkey) throws Exception { @@ -2585,7 +2787,7 @@ public final class KeyTool { } } - return new Object[] {entry, pkey}; + return Pair.of(entry, pkey); } /** * Gets the requested finger print of the certificate. @@ -3026,6 +3228,443 @@ public final class KeyTool { return c.getTime(); } + /** + * Match a command (may be abbreviated) with a command set. + * @param s the command provided + * @param list the legal command set + * @return the position of a single match, or -1 if none matched + * @throws Exception if s is ambiguous + */ + private static int oneOf(String s, String... list) throws Exception { + int[] match = new int[list.length]; + int nmatch = 0; + for (int i = 0; iextstr argument. + * + * @param reqex the requested extensions, can be null, used for -gencert + * @param ext the original extensions, can be null, used for -selfcert + * @param extstrs -ext values, Read keytool doc + * @param pkey the public key for the certificate + * @param akey the public key for the authority (issuer) + * @return the created CertificateExtensions + */ + private CertificateExtensions createV3Extensions( + CertificateExtensions reqex, + CertificateExtensions ext, + List extstrs, + PublicKey pkey, + PublicKey akey) throws Exception { + + if (ext != null && reqex != null) { + // This should not happen + throw new Exception("One of request and original should be null."); + } + if (ext == null) ext = new CertificateExtensions(); + try { + // name{:critical}{=value} + // Honoring requested extensions + if (reqex != null) { + for(String extstr: extstrs) { + if (extstr.toLowerCase().startsWith("honored=")) { + List list = Arrays.asList( + extstr.toLowerCase().substring(8).split(",")); + // First check existence of "all" + if (list.contains("all")) { + ext = reqex; // we know ext was null + } + // one by one for others + for (String item: list) { + if (item.equals("all")) continue; + + // add or remove + boolean add = true; + // -1, unchanged, 0 crtical, 1 non-critical + int action = -1; + String type = null; + if (item.startsWith("-")) { + add = false; + type = item.substring(1); + } else { + int colonpos = item.indexOf(':'); + if (colonpos >= 0) { + type = item.substring(0, colonpos); + action = oneOf(item.substring(colonpos+1), + "critical", "non-critical"); + if (action == -1) { + throw new Exception(rb.getString + ("Illegal value: ") + item); + } + } + } + String n = reqex.getNameByOid(findOidForExtName(type)); + if (add) { + Extension e = (Extension)reqex.get(n); + if (!e.isCritical() && action == 0 + || e.isCritical() && action == 1) { + e = Extension.newExtension( + e.getExtensionId(), + !e.isCritical(), + e.getExtensionValue()); + ext.set(n, e); + } + } else { + ext.delete(n); + } + } + break; + } + } + } + for(String extstr: extstrs) { + String name, value; + boolean isCritical = false; + + int eqpos = extstr.indexOf('='); + if (eqpos >= 0) { + name = extstr.substring(0, eqpos); + value = extstr.substring(eqpos+1); + } else { + name = extstr; + value = null; + } + + int colonpos = name.indexOf(':'); + if (colonpos >= 0) { + if (name.substring(colonpos+1).equalsIgnoreCase("critical")) { + isCritical = true; + } + name = name.substring(0, colonpos); + } + + if (name.equalsIgnoreCase("honored")) { + continue; + } + int exttype = oneOf(name, extSupported); + switch (exttype) { + case 0: // BC + int pathLen = -1; + boolean isCA = false; + if (value == null) { + isCA = true; + } else { + try { // the abbr format + pathLen = Integer.parseInt(value); + isCA = true; + } catch (NumberFormatException ufe) { + // ca:true,pathlen:1 + for (String part: value.split(",")) { + String[] nv = part.split(":"); + if (nv.length != 2) { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } else { + if (nv[0].equalsIgnoreCase("ca")) { + isCA = Boolean.parseBoolean(nv[1]); + } else if (nv[0].equalsIgnoreCase("pathlen")) { + pathLen = Integer.parseInt(nv[1]); + } else { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + } + } + } + } + ext.set(BasicConstraintsExtension.NAME, + new BasicConstraintsExtension(isCritical, isCA, + pathLen)); + break; + case 1: // KU + if(value != null) { + boolean[] ok = new boolean[9]; + for (String s: value.split(",")) { + int p = oneOf(s, + "digitalSignature", // (0), + "nonRepudiation", // (1) + "keyEncipherment", // (2), + "dataEncipherment", // (3), + "keyAgreement", // (4), + "keyCertSign", // (5), + "cRLSign", // (6), + "encipherOnly", // (7), + "decipherOnly", // (8) + "contentCommitment" // also (1) + ); + if (p < 0) { + throw new Exception(rb.getString("Unknown keyUsage type: ") + s); + } + if (p == 9) p = 1; + ok[p] = true; + } + KeyUsageExtension kue = new KeyUsageExtension(ok); + // The above KeyUsageExtension constructor does not + // allow isCritical value, so... + ext.set(KeyUsageExtension.NAME, Extension.newExtension( + kue.getExtensionId(), + isCritical, + kue.getExtensionValue())); + } else { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + break; + case 2: // EKU + if(value != null) { + Vector v = + new Vector (); + for (String s: value.split(",")) { + int p = oneOf(s, + "anyExtendedKeyUsage", + "serverAuth", //1 + "clientAuth", //2 + "codeSigning", //3 + "emailProtection", //4 + "", //5 + "", //6 + "", //7 + "timeStamping", //8 + "OCSPSigning" //9 + ); + if (p < 0) { + try { + v.add(new ObjectIdentifier(s)); + } catch (Exception e) { + throw new Exception(rb.getString( + "Unknown extendedkeyUsage type: ") + s); + } + } else if (p == 0) { + v.add(new ObjectIdentifier("2.5.29.37.0")); + } else { + v.add(new ObjectIdentifier("1.3.6.1.5.5.7.3." + p)); + } + } + ext.set(ExtendedKeyUsageExtension.NAME, + new ExtendedKeyUsageExtension(isCritical, v)); + } else { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + break; + case 3: // SAN + case 4: // IAN + if(value != null) { + String[] ps = value.split(","); + GeneralNames gnames = new GeneralNames(); + for(String item: ps) { + colonpos = item.indexOf(':'); + if (colonpos < 0) { + throw new Exception("Illegal item " + item + " in " + extstr); + } + String t = item.substring(0, colonpos); + String v = item.substring(colonpos+1); + gnames.add(createGeneralName(t, v)); + } + if (exttype == 3) { + ext.set(SubjectAlternativeNameExtension.NAME, + new SubjectAlternativeNameExtension( + isCritical, gnames)); + } else { + ext.set(IssuerAlternativeNameExtension.NAME, + new IssuerAlternativeNameExtension( + isCritical, gnames)); + } + } else { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + break; + case 5: // SIA, always non-critical + case 6: // AIA, always non-critical + if (isCritical) { + throw new Exception(rb.getString( + "This extension cannot be marked as critical. ") + extstr); + } + if(value != null) { + List accessDescriptions = + new ArrayList(); + String[] ps = value.split(","); + for(String item: ps) { + colonpos = item.indexOf(':'); + int colonpos2 = item.indexOf(':', colonpos+1); + if (colonpos < 0 || colonpos2 < 0) { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + String m = item.substring(0, colonpos); + String t = item.substring(colonpos+1, colonpos2); + String v = item.substring(colonpos2+1); + int p = oneOf(m, + "", + "ocsp", //1 + "caIssuers", //2 + "timeStamping", //3 + "", + "caRepository" //5 + ); + ObjectIdentifier oid; + if (p < 0) { + try { + oid = new ObjectIdentifier(m); + } catch (Exception e) { + throw new Exception(rb.getString( + "Unknown AccessDescription type: ") + m); + } + } else { + oid = new ObjectIdentifier("1.3.6.1.5.5.7.48." + p); + } + accessDescriptions.add(new AccessDescription( + oid, createGeneralName(t, v))); + } + if (exttype == 5) { + ext.set(SubjectInfoAccessExtension.NAME, + new SubjectInfoAccessExtension(accessDescriptions)); + } else { + ext.set(AuthorityInfoAccessExtension.NAME, + new AuthorityInfoAccessExtension(accessDescriptions)); + } + } else { + throw new Exception(rb.getString + ("Illegal value: ") + extstr); + } + break; + case -1: + ObjectIdentifier oid = new ObjectIdentifier(name); + byte[] data = null; + if (value != null) { + data = new byte[value.length() / 2 + 1]; + int pos = 0; + for (char c: value.toCharArray()) { + int hex; + if (c >= '0' && c <= '9') { + hex = c - '0' ; + } else if (c >= 'A' && c <= 'F') { + hex = c - 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + hex = c - 'a' + 10; + } else { + continue; + } + if (pos % 2 == 0) { + data[pos/2] = (byte)(hex << 4); + } else { + data[pos/2] += hex; + } + pos++; + } + if (pos % 2 != 0) { + throw new Exception(rb.getString( + "Odd number of hex digits found: ") + extstr); + } + data = Arrays.copyOf(data, pos/2); + } else { + data = new byte[0]; + } + ext.set(oid.toString(), new Extension(oid, isCritical, + new DerValue(DerValue.tag_OctetString, data) + .toByteArray())); + break; + } + } + // always non-critical + ext.set(SubjectKeyIdentifierExtension.NAME, + new SubjectKeyIdentifierExtension( + new KeyIdentifier(pkey).getIdentifier())); + if (akey != null && !pkey.equals(akey)) { + ext.set(AuthorityKeyIdentifierExtension.NAME, + new AuthorityKeyIdentifierExtension( + new KeyIdentifier(akey), null, null)); + } + } catch(IOException e) { + throw new RuntimeException(e); + } + return ext; + } + /** * Prints the usage of this tool. */ @@ -3098,6 +3737,32 @@ public final class KeyTool { ("\t [-sigalg ] [-dname ]")); System.err.println(rb.getString ("\t [-startdate ]")); + System.err.println(rb.getString + ("\t [-ext [:critical][=]]...")); + System.err.println(rb.getString + ("\t [-validity ] [-keypass ]")); + System.err.println(rb.getString + ("\t [-keystore ] [-storepass ]")); + System.err.println(rb.getString + ("\t [-storetype ] [-providername ]")); + System.err.println(rb.getString + ("\t [-providerclass [-providerarg ]] ...")); + System.err.println(rb.getString + ("\t [-providerpath ]")); + System.err.println(); + + System.err.println(rb.getString + ("-gencert [-v] [-rfc] [-protected]")); + System.err.println(rb.getString + ("\t [-infile ] [-outfile ]")); + System.err.println(rb.getString + ("\t [-alias ]")); + System.err.println(rb.getString + ("\t [-sigalg ]")); + System.err.println(rb.getString + ("\t [-startdate ]")); + System.err.println(rb.getString + ("\t [-ext [:critical][=]]...")); System.err.println(rb.getString ("\t [-validity ] [-keypass ]")); System.err.println(rb.getString @@ -3201,6 +3866,10 @@ public final class KeyTool { ("-printcert [-v] [-rfc] [-file | -sslserver ]")); System.err.println(); + System.err.println(rb.getString + ("-printcertreq [-v] [-file ]")); + System.err.println(); + System.err.println(rb.getString ("-storepasswd [-v] [-new ]")); System.err.println(rb.getString @@ -3211,12 +3880,6 @@ public final class KeyTool { ("\t [-providerclass [-providerarg ]] ...")); System.err.println(rb.getString ("\t [-providerpath ]")); - - if (debug) { - throw new RuntimeException("NO ERROR, SORRY"); - } else { - System.exit(1); - } } private void tinyHelp() { @@ -3270,4 +3933,8 @@ class Pair { else if (snd == null) return fst.hashCode() + 2; else return fst.hashCode() * 17 + snd.hashCode(); } + + public static Pair of(A a, B b) { + return new Pair(a,b); + } } diff --git a/jdk/src/share/classes/sun/security/util/Cache.java b/jdk/src/share/classes/sun/security/util/Cache.java index e6eddb6f07d..35d648a5a7f 100644 --- a/jdk/src/share/classes/sun/security/util/Cache.java +++ b/jdk/src/share/classes/sun/security/util/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,6 +100,21 @@ public abstract class Cache { */ public abstract void remove(Object key); + /** + * Set the maximum size. + */ + public abstract void setCapacity(int size); + + /** + * Set the timeout(in seconds). + */ + public abstract void setTimeout(int timeout); + + /** + * accept a visitor + */ + public abstract void accept(CacheVisitor visitor); + /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by SoftReferences. @@ -178,6 +193,10 @@ public abstract class Cache { } } + public interface CacheVisitor { + public void visit(Map map); + } + } class NullCache extends Cache { @@ -208,6 +227,18 @@ class NullCache extends Cache { // empty } + public void setCapacity(int size) { + // empty + } + + public void setTimeout(int timeout) { + // empty + } + + public void accept(CacheVisitor visitor) { + // empty + } + } class MemoryCache extends Cache { @@ -218,8 +249,8 @@ class MemoryCache extends Cache { private final static boolean DEBUG = false; private final Map cacheMap; - private final int maxSize; - private final int lifetime; + private int maxSize; + private long lifetime; private final ReferenceQueue queue; public MemoryCache(boolean soft, int maxSize) { @@ -328,7 +359,7 @@ class MemoryCache extends Cache { oldEntry.invalidate(); return; } - if (cacheMap.size() > maxSize) { + if (maxSize > 0 && cacheMap.size() > maxSize) { expungeExpiredEntries(); if (cacheMap.size() > maxSize) { // still too large? Iterator t = cacheMap.values().iterator(); @@ -368,6 +399,55 @@ class MemoryCache extends Cache { } } + public synchronized void setCapacity(int size) { + expungeExpiredEntries(); + if (size > 0 && cacheMap.size() > size) { + Iterator t = cacheMap.values().iterator(); + for (int i = cacheMap.size() - size; i > 0; i--) { + CacheEntry lruEntry = t.next(); + if (DEBUG) { + System.out.println("** capacity reset removal " + + lruEntry.getKey() + " | " + lruEntry.getValue()); + } + t.remove(); + lruEntry.invalidate(); + } + } + + maxSize = size > 0 ? size : 0; + + if (DEBUG) { + System.out.println("** capacity reset to " + size); + } + } + + public synchronized void setTimeout(int timeout) { + emptyQueue(); + lifetime = timeout > 0 ? timeout * 1000L : 0L; + + if (DEBUG) { + System.out.println("** lifetime reset to " + timeout); + } + } + + // it is a heavyweight method. + public synchronized void accept(CacheVisitor visitor) { + expungeExpiredEntries(); + Map cached = getCachedEntries(); + + visitor.visit(cached); + } + + private Map getCachedEntries() { + Map kvmap = new HashMap(cacheMap.size()); + + for (CacheEntry entry : cacheMap.values()) { + kvmap.put(entry.getKey(), entry.getValue()); + } + + return kvmap; + } + protected CacheEntry newEntry(Object key, Object value, long expirationTime, ReferenceQueue queue) { if (queue != null) { diff --git a/jdk/src/share/classes/sun/security/util/DerValue.java b/jdk/src/share/classes/sun/security/util/DerValue.java index 74e59f609b9..114788beb26 100644 --- a/jdk/src/share/classes/sun/security/util/DerValue.java +++ b/jdk/src/share/classes/sun/security/util/DerValue.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public class DerValue { protected DerInputBuffer buffer; /** - * The DER-encoded data of the value. + * The DER-encoded data of the value, never null */ public final DerInputStream data; @@ -378,8 +378,6 @@ public class DerValue { ("Indefinite length encoding not supported"); length = DerInputStream.getLength(in); } - if (length == 0) - return null; if (fullyBuffered && in.available() != length) throw new IOException("extra data given to DerValue constructor"); @@ -477,6 +475,11 @@ public class DerValue { "DerValue.getOctetString, not an Octet String: " + tag); } bytes = new byte[length]; + // Note: do not tempt to call buffer.read(bytes) at all. There's a + // known bug that it returns -1 instead of 0. + if (length == 0) { + return bytes; + } if (buffer.read(bytes) != length) throw new IOException("short read on DerValue buffer"); if (isConstructed()) { diff --git a/jdk/src/share/classes/sun/security/util/Resources.java b/jdk/src/share/classes/sun/security/util/Resources.java index e89d6cdfc99..c8c5e386de1 100644 --- a/jdk/src/share/classes/sun/security/util/Resources.java +++ b/jdk/src/share/classes/sun/security/util/Resources.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ public class Resources extends java.util.ListResourceBundle { // keytool {"keytool error: ", "keytool error: "}, {"Illegal option: ", "Illegal option: "}, + {"Illegal value: ", "Illegal value: "}, {"Try keytool -help","Try keytool -help"}, {"Command option needs an argument.", "Command option {0} needs an argument."}, {"Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified value.", @@ -281,6 +282,20 @@ public class Resources extends java.util.ListResourceBundle { {"keytool usage:\n", "keytool usage:\n"}, {"Extensions: ", "Extensions: "}, + {"(Empty value)", "(Empty value)"}, + {"Extension Request:", "Extension Request:"}, + {"PKCS #10 Certificate Request (Version 1.0)\n" + + "Subject: %s\nPublic Key: %s format %s key\n", + "PKCS #10 Certificate Request (Version 1.0)\n" + + "Subject: %s\nPublic Key: %s format %s key\n"}, + {"Unknown keyUsage type: ", "Unknown keyUsage type: "}, + {"Unknown extendedkeyUsage type: ", "Unknown extendedkeyUsage type: "}, + {"Unknown AccessDescription type: ", "Unknown AccessDescription type: "}, + {"Unrecognized GeneralName type: ", "Unrecognized GeneralName type: "}, + {"This extension cannot be marked as critical. ", + "This extension cannot be marked as critical. "}, + {"Odd number of hex digits found: ", "Odd number of hex digits found: "}, + {"command {0} is ambiguous:", "command {0} is ambiguous:"}, {"-certreq [-v] [-protected]", "-certreq [-v] [-protected]"}, @@ -322,6 +337,14 @@ public class Resources extends java.util.ListResourceBundle { {"\t [-validity ] [-keypass ]", "\t [-validity ] [-keypass ]"}, /** rest is same as -certreq starting from -keystore **/ + {"-gencert [-v] [-rfc] [-protected]", + "-gencert [-v] [-rfc] [-protected]"}, + {"\t [-infile ] [-outfile ]", + "\t [-infile ] [-outfile ]"}, + {"\t [-sigalg ]", + "\t [-sigalg ]"}, + {"\t [-ext [:critical][=]]...", + "\t [-ext [:critical][=]]..."}, {"-genseckey [-v] [-protected]", "-genseckey [-v] [-protected]"}, @@ -388,6 +411,8 @@ public class Resources extends java.util.ListResourceBundle { {"-printcert [-v] [-rfc] [-file | -sslserver ]", "-printcert [-v] [-rfc] [-file | -sslserver ]"}, + {"-printcertreq [-v] [-file ]", + "-printcertreq [-v] [-file ]"}, {"No certificate from the SSL server", "No certificate from the SSL server"}, diff --git a/jdk/src/share/classes/sun/security/util/SecurityConstants.java b/jdk/src/share/classes/sun/security/util/SecurityConstants.java index 95cd1f57070..43e2cd3d792 100644 --- a/jdk/src/share/classes/sun/security/util/SecurityConstants.java +++ b/jdk/src/share/classes/sun/security/util/SecurityConstants.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ public final class SecurityConstants { public static final String FILE_EXECUTE_ACTION = "execute"; public static final String FILE_READ_ACTION = "read"; public static final String FILE_WRITE_ACTION = "write"; + public static final String FILE_READLINK_ACTION = "readlink"; public static final String SOCKET_RESOLVE_ACTION = "resolve"; public static final String SOCKET_CONNECT_ACTION = "connect"; diff --git a/jdk/src/share/classes/sun/security/x509/AccessDescription.java b/jdk/src/share/classes/sun/security/x509/AccessDescription.java index a9ccbb86824..1544ea953be 100644 --- a/jdk/src/share/classes/sun/security/x509/AccessDescription.java +++ b/jdk/src/share/classes/sun/security/x509/AccessDescription.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,17 @@ public final class AccessDescription { public static final ObjectIdentifier Ad_CAISSUERS_Id = ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 2}); + public static final ObjectIdentifier Ad_TIMESTAMPING_Id = + ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 3}); + + public static final ObjectIdentifier Ad_CAREPOSITORY_Id = + ObjectIdentifier.newInternal(new int[] {1, 3, 6, 1, 5, 5, 7, 48, 5}); + + public AccessDescription(ObjectIdentifier accessMethod, GeneralName accessLocation) { + this.accessMethod = accessMethod; + this.accessLocation = accessLocation; + } + public AccessDescription(DerValue derValue) throws IOException { DerInputStream derIn = derValue.getData(); accessMethod = derIn.getOID(); @@ -90,7 +101,19 @@ public final class AccessDescription { } public String toString() { - return ("accessMethod: " + accessMethod.toString() + - "\n accessLocation: " + accessLocation.toString()); + String method = null; + if (accessMethod.equals(Ad_CAISSUERS_Id)) { + method = "caIssuers"; + } else if (accessMethod.equals(Ad_CAREPOSITORY_Id)) { + method = "caRepository"; + } else if (accessMethod.equals(Ad_TIMESTAMPING_Id)) { + method = "timeStamping"; + } else if (accessMethod.equals(Ad_OCSP_Id)) { + method = "ocsp"; + } else { + method = accessMethod.toString(); + } + return ("accessMethod: " + method + + "\n accessLocation: " + accessLocation.toString() + "\n"); } } diff --git a/jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java b/jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java index 5b0b287fa24..da14007cd16 100644 --- a/jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java +++ b/jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java @@ -43,8 +43,9 @@ import sun.security.util.DerValue; * certificate that identifies the specific OCSP Responder to use when * performing on-line validation of that certificate. *

- * This extension is defined in - * Internet X.509 PKI Certificate and Certificate Revocation List (CRL) Profile. The profile permits + * This extension is defined in + * Internet X.509 PKI Certificate and Certificate Revocation List + * (CRL) Profile. The profile permits * the extension to be included in end-entity or CA certificates, * and it must be marked as non-critical. Its ASN.1 definition is as follows: *

diff --git a/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java b/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java
index f63dca90a79..b14c8436292 100644
--- a/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java
+++ b/jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -198,7 +198,7 @@ implements CertAttrSet {
     public String toString() {
         String s = super.toString() + "AuthorityKeyIdentifier [\n";
         if (id != null) {
-            s += id.toString() + "\n";
+            s += id.toString();     // id already has a newline
         }
         if (names != null) {
             s += names.toString() + "\n";
diff --git a/jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java b/jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java
index 26344ee27f1..c38bb002b08 100644
--- a/jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java
+++ b/jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,18 +70,15 @@ implements CertAttrSet {
 
     // Encode this extension value
     private void encodeThis() throws IOException {
-        if (ca == false && pathLen < 0) {
-            this.extensionValue = null;
-            return;
-        }
         DerOutputStream out = new DerOutputStream();
         DerOutputStream tmp = new DerOutputStream();
 
         if (ca) {
             tmp.putBoolean(ca);
-        }
-        if (pathLen >= 0) {
-            tmp.putInteger(pathLen);
+            // Only encode pathLen when ca == true
+            if (pathLen >= 0) {
+                tmp.putInteger(pathLen);
+            }
         }
         out.write(DerValue.tag_Sequence, tmp);
         this.extensionValue = out.toByteArray();
@@ -134,7 +131,7 @@ implements CertAttrSet {
              throw new IOException("Invalid encoding of BasicConstraints");
          }
 
-         if (val.data == null) {
+         if (val.data == null || val.data.available() == 0) {
              // non-CA cert ("cA" field is FALSE by default), return -1
              return;
          }
diff --git a/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java b/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java
index 0e0800910ea..38ca600927b 100644
--- a/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java
+++ b/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -276,12 +276,6 @@ public final class CertAndKeyGen {
             info.set(X509CertInfo.ISSUER,
                      new CertificateIssuerName(issuer.getSigner()));
 
-            CertificateExtensions ext = new CertificateExtensions();
-                ext.set(SubjectKeyIdentifierExtension.NAME,
-                        new SubjectKeyIdentifierExtension(
-                            new KeyIdentifier(publicKey).getIdentifier()));
-            info.set(X509CertInfo.EXTENSIONS, ext);
-
             cert = new X509CertImpl(info);
             cert.sign(privateKey, this.sigAlg);
 
diff --git a/jdk/src/share/classes/sun/security/x509/CertificateExtensions.java b/jdk/src/share/classes/sun/security/x509/CertificateExtensions.java
index 7049d01e974..cd32e748c74 100644
--- a/jdk/src/share/classes/sun/security/x509/CertificateExtensions.java
+++ b/jdk/src/share/classes/sun/security/x509/CertificateExtensions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -231,6 +231,15 @@ public class CertificateExtensions implements CertAttrSet {
         map.remove(name);
     }
 
+    public String getNameByOid(ObjectIdentifier oid) throws IOException {
+        for (String name: map.keySet()) {
+            if (map.get(name).getExtensionId().equals(oid)) {
+                return name;
+            }
+        }
+        return null;
+    }
+
     /**
      * Return an enumeration of names of attributes existing within this
      * attribute.
diff --git a/jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java b/jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java
index aad153b646a..73f3ecd5c93 100644
--- a/jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java
+++ b/jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,22 @@ extends Extension implements CertAttrSet {
         encodeThis();
     }
 
+    /**
+     * Create a IssuerAlternativeNameExtension with the passed criticality
+     * and GeneralNames.
+     *
+     * @param critical true if the extension is to be treated as critical.
+     * @param names the GeneralNames for the issuer.
+     * @exception IOException on error.
+     */
+    public IssuerAlternativeNameExtension(Boolean critical, GeneralNames names)
+    throws IOException {
+        this.names = names;
+        this.extensionId = PKIXExtensions.IssuerAlternativeName_Id;
+        this.critical = critical.booleanValue();
+        encodeThis();
+    }
+
     /**
      * Create a default IssuerAlternativeNameExtension.
      */
diff --git a/jdk/src/share/classes/sun/security/x509/OIDMap.java b/jdk/src/share/classes/sun/security/x509/OIDMap.java
index ddbb1d6f60a..bb7cffef343 100644
--- a/jdk/src/share/classes/sun/security/x509/OIDMap.java
+++ b/jdk/src/share/classes/sun/security/x509/OIDMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,6 +90,8 @@ public class OIDMap {
 
     private static final String CERT_ISSUER = ROOT + "." +
                                         CertificateIssuerExtension.NAME;
+    private static final String SUBJECT_INFO_ACCESS = ROOT + "." +
+                                          SubjectInfoAccessExtension.NAME;
     private static final String AUTH_INFO_ACCESS = ROOT + "." +
                                           AuthorityInfoAccessExtension.NAME;
     private static final String ISSUING_DIST_POINT = ROOT + "." +
@@ -148,6 +150,8 @@ public class OIDMap {
                     "sun.security.x509.CRLDistributionPointsExtension");
         addInternal(CERT_ISSUER, PKIXExtensions.CertificateIssuer_Id,
                     "sun.security.x509.CertificateIssuerExtension");
+        addInternal(SUBJECT_INFO_ACCESS, PKIXExtensions.SubjectInfoAccess_Id,
+                    "sun.security.x509.SubjectInfoAccessExtension");
         addInternal(AUTH_INFO_ACCESS, PKIXExtensions.AuthInfoAccess_Id,
                     "sun.security.x509.AuthorityInfoAccessExtension");
         addInternal(ISSUING_DIST_POINT,
diff --git a/jdk/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java b/jdk/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java
new file mode 100644
index 00000000000..449f45eb595
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.x509;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.*;
+
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+
+/**
+ * The Subject Information Access Extension (OID = 1.3.6.1.5.5.7.1.11).
+ * 

+ * The subject information access extension indicates how to access + * information and services for the subject of the certificate in which + * the extension appears. When the subject is a CA, information and + * services may include certificate validation services and CA policy + * data. When the subject is an end entity, the information describes + * the type of services offered and how to access them. In this case, + * the contents of this extension are defined in the protocol + * specifications for the supported services. This extension may be + * included in end entity or CA certificates. Conforming CAs MUST mark + * this extension as non-critical. + *

+ * This extension is defined in + * Internet X.509 PKI Certificate and Certificate Revocation List + * (CRL) Profile. The profile permits + * the extension to be included in end-entity or CA certificates, + * and it must be marked as non-critical. Its ASN.1 definition is as follows: + *

+ *   id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 }
+ *
+ *   SubjectInfoAccessSyntax  ::=
+ *          SEQUENCE SIZE (1..MAX) OF AccessDescription
+ *
+ *   AccessDescription  ::=  SEQUENCE {
+ *          accessMethod          OBJECT IDENTIFIER,
+ *          accessLocation        GeneralName  }
+ * 
+ *

+ * @see Extension + * @see CertAttrSet + */ + +public class SubjectInfoAccessExtension extends Extension + implements CertAttrSet { + + /** + * Identifier for this attribute, to be used with the + * get, set, delete methods of Certificate, x509 type. + */ + public static final String IDENT = + "x509.info.extensions.SubjectInfoAccess"; + + /** + * Attribute name. + */ + public static final String NAME = "SubjectInfoAccess"; + public static final String DESCRIPTIONS = "descriptions"; + + /** + * The List of AccessDescription objects. + */ + private List accessDescriptions; + + /** + * Create an SubjectInfoAccessExtension from a List of + * AccessDescription; the criticality is set to false. + * + * @param accessDescriptions the List of AccessDescription + * @throws IOException on error + */ + public SubjectInfoAccessExtension( + List accessDescriptions) throws IOException { + this.extensionId = PKIXExtensions.SubjectInfoAccess_Id; + this.critical = false; + this.accessDescriptions = accessDescriptions; + encodeThis(); + } + + /** + * Create the extension from the passed DER encoded value of the same. + * + * @param critical true if the extension is to be treated as critical. + * @param value Array of DER encoded bytes of the actual value. + * @exception IOException on error. + */ + public SubjectInfoAccessExtension(Boolean critical, Object value) + throws IOException { + this.extensionId = PKIXExtensions.SubjectInfoAccess_Id; + this.critical = critical.booleanValue(); + + if (!(value instanceof byte[])) { + throw new IOException("Illegal argument type"); + } + + extensionValue = (byte[])value; + DerValue val = new DerValue(extensionValue); + if (val.tag != DerValue.tag_Sequence) { + throw new IOException("Invalid encoding for " + + "SubjectInfoAccessExtension."); + } + accessDescriptions = new ArrayList(); + while (val.data.available() != 0) { + DerValue seq = val.data.getDerValue(); + AccessDescription accessDescription = new AccessDescription(seq); + accessDescriptions.add(accessDescription); + } + } + + /** + * Return the list of AccessDescription objects. + */ + public List getAccessDescriptions() { + return accessDescriptions; + } + + /** + * Return the name of this attribute. + */ + public String getName() { + return NAME; + } + + /** + * Write the extension to the DerOutputStream. + * + * @param out the DerOutputStream to write the extension to. + * @exception IOException on encoding errors. + */ + public void encode(OutputStream out) throws IOException { + DerOutputStream tmp = new DerOutputStream(); + if (this.extensionValue == null) { + this.extensionId = PKIXExtensions.SubjectInfoAccess_Id; + this.critical = false; + encodeThis(); + } + super.encode(tmp); + out.write(tmp.toByteArray()); + } + + /** + * Set the attribute value. + */ + public void set(String name, Object obj) throws IOException { + if (name.equalsIgnoreCase(DESCRIPTIONS)) { + if (!(obj instanceof List)) { + throw new IOException("Attribute value should be of type List."); + } + accessDescriptions = (List)obj; + } else { + throw new IOException("Attribute name [" + name + + "] not recognized by " + + "CertAttrSet:SubjectInfoAccessExtension."); + } + encodeThis(); + } + + /** + * Get the attribute value. + */ + public Object get(String name) throws IOException { + if (name.equalsIgnoreCase(DESCRIPTIONS)) { + return accessDescriptions; + } else { + throw new IOException("Attribute name [" + name + + "] not recognized by " + + "CertAttrSet:SubjectInfoAccessExtension."); + } + } + + /** + * Delete the attribute value. + */ + public void delete(String name) throws IOException { + if (name.equalsIgnoreCase(DESCRIPTIONS)) { + accessDescriptions = new ArrayList(); + } else { + throw new IOException("Attribute name [" + name + + "] not recognized by " + + "CertAttrSet:SubjectInfoAccessExtension."); + } + encodeThis(); + } + + /** + * Return an enumeration of names of attributes existing within this + * attribute. + */ + public Enumeration getElements() { + AttributeNameEnumeration elements = new AttributeNameEnumeration(); + elements.addElement(DESCRIPTIONS); + return elements.elements(); + } + + // Encode this extension value + private void encodeThis() throws IOException { + if (accessDescriptions.isEmpty()) { + this.extensionValue = null; + } else { + DerOutputStream ads = new DerOutputStream(); + for (AccessDescription accessDescription : accessDescriptions) { + accessDescription.encode(ads); + } + DerOutputStream seq = new DerOutputStream(); + seq.write(DerValue.tag_Sequence, ads); + this.extensionValue = seq.toByteArray(); + } + } + + /** + * Return the extension as user readable string. + */ + public String toString() { + return super.toString() + "SubjectInfoAccess [\n " + + accessDescriptions + "\n]\n"; + } + +} diff --git a/jdk/src/share/classes/sun/swing/FilePane.java b/jdk/src/share/classes/sun/swing/FilePane.java index 298fd42b146..de5ad7c4831 100644 --- a/jdk/src/share/classes/sun/swing/FilePane.java +++ b/jdk/src/share/classes/sun/swing/FilePane.java @@ -689,7 +689,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { void updateColumnInfo() { File dir = chooser.getCurrentDirectory(); - if (dir != null && fileChooserUIAccessor.usesShellFolder()) { + if (dir != null && usesShellFolder(chooser)) { try { dir = ShellFolder.getShellFolder(dir); } catch (FileNotFoundException e) { @@ -1947,7 +1947,7 @@ public class FilePane extends JPanel implements PropertyChangeListener { if (f instanceof ShellFolder) { return ((ShellFolder) f).isFileSystem(); } else { - if (fileChooserUIAccessor.usesShellFolder()) { + if (usesShellFolder(getFileChooser())) { try { return ShellFolder.getShellFolder(f).isFileSystem(); } catch (FileNotFoundException ex) { @@ -1961,6 +1961,16 @@ public class FilePane extends JPanel implements PropertyChangeListener { } } + /** + * Returns true if specified FileChooser should use ShellFolder + */ + public static boolean usesShellFolder(JFileChooser chooser) { + Boolean prop = (Boolean) chooser.getClientProperty("FileChooser.useShellFolder"); + + return prop == null ? chooser.getFileSystemView().equals(FileSystemView.getFileSystemView()) + : prop.booleanValue(); + } + // This interface is used to access methods in the FileChooserUI // that are not public. public interface FileChooserUIAccessor { @@ -1975,6 +1985,5 @@ public class FilePane extends JPanel implements PropertyChangeListener { public Action getNewFolderAction(); public MouseListener createDoubleClickListener(JList list); public ListSelectionListener createListSelectionListener(); - public boolean usesShellFolder(); } } diff --git a/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java b/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java index 95fac33386a..5ded9d729a4 100644 --- a/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java +++ b/jdk/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java @@ -71,8 +71,6 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { private JToggleButton listViewButton; private JToggleButton detailsViewButton; - private boolean useShellFolder; - private boolean readOnly; private JPanel buttonPanel; @@ -185,10 +183,6 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { public ListSelectionListener createListSelectionListener() { return SynthFileChooserUIImpl.this.createListSelectionListener(getFileChooser()); } - - public boolean usesShellFolder() { - return useShellFolder; - } } protected void installDefaults(JFileChooser fc) { @@ -201,8 +195,6 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { SynthContext context = getContext(fc, ENABLED); - updateUseShellFolder(); - fc.setLayout(new BorderLayout(0, 11)); // ********************************* // @@ -432,20 +424,6 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { super.uninstallListeners(fc); } - private void updateUseShellFolder() { - // Decide whether to use the ShellFolder class to populate shortcut - // panel and combobox. - JFileChooser fc = getFileChooser(); - Boolean prop = - (Boolean)fc.getClientProperty("FileChooser.useShellFolder"); - if (prop != null) { - useShellFolder = prop.booleanValue(); - } else { - useShellFolder = fc.getFileSystemView().equals(FileSystemView.getFileSystemView()); - } - } - - private String fileNameString(File file) { if (file == null) { return null; @@ -761,6 +739,8 @@ public class SynthFileChooserUIImpl extends SynthFileChooserUI { return; } + boolean useShellFolder = FilePane.usesShellFolder(chooser); + int oldSize = directories.size(); directories.clear(); if (oldSize > 0) { diff --git a/jdk/src/share/classes/sun/text/resources/FormatData_th.java b/jdk/src/share/classes/sun/text/resources/FormatData_th.java index 18e1da8ffbb..e1fe418f597 100644 --- a/jdk/src/share/classes/sun/text/resources/FormatData_th.java +++ b/jdk/src/share/classes/sun/text/resources/FormatData_th.java @@ -47,6 +47,19 @@ public class FormatData_th extends ListResourceBundle { * Overrides ListResourceBundle */ protected final Object[][] getContents() { + String[] dateTimePatterns = new String[] { + "H' \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 'm' \u0e19\u0e32\u0e17\u0e35 'ss' \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35'", // full time pattern + "H' \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 'm' \u0e19\u0e32\u0e17\u0e35'", // long time pattern + "H:mm:ss", // medium time pattern + "H:mm' \u0e19.'", // short time pattern (modified) -- add ' \u0e19.' + // (it means something like "o'clock" in english) + "EEEE'\u0e17\u0e35\u0e48 'd MMMM G yyyy", // full date pattern + "d MMMM yyyy", // long date pattern + "d MMM yyyy", // medium date pattern + "d/M/yyyy", // short date pattern + "{1}, {0}" // date-time pattern + }; + return new Object[][] { { "MonthNames", new String[] { @@ -129,18 +142,10 @@ public class FormatData_th extends ListResourceBundle { } }, { "sun.util.BuddhistCalendar.DateTimePatterns", - new String[] { - "H' \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 'm' \u0e19\u0e32\u0e17\u0e35 'ss' \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35'", // full time pattern - "H' \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 'm' \u0e19\u0e32\u0e17\u0e35'", // long time pattern - "H:mm:ss", // medium time pattern - "H:mm' \u0e19.'", // short time pattern (modified) -- add ' \u0e19.' - // (it means something like "o'clock" in english) - "EEEE'\u0e17\u0e35\u0e48 'd MMMM G yyyy", // full date pattern - "d MMMM yyyy", // long date pattern - "d MMM yyyy", // medium date pattern - "d/M/yyyy", // short date pattern - "{1}, {0}" // date-time pattern - } + dateTimePatterns + }, + { "DateTimePatterns", + dateTimePatterns }, { "DateTimePatternChars", "GanjkHmsSEDFwWxhKzZ" }, }; diff --git a/jdk/src/share/classes/sun/tools/jar/Main.java b/jdk/src/share/classes/sun/tools/jar/Main.java index 693866e1866..6d2a67810fe 100644 --- a/jdk/src/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/share/classes/sun/tools/jar/Main.java @@ -74,7 +74,6 @@ class Main { static final String MANIFEST = JarFile.MANIFEST_NAME; static final String MANIFEST_DIR = "META-INF/"; static final String VERSION = "1.0"; - static final char SEPARATOR = File.separatorChar; static final String INDEX = JarIndex.INDEX_NAME; private static ResourceBundle rsrc; @@ -227,19 +226,32 @@ class Main { } tmpFile.delete(); } - } else if (xflag || tflag) { - InputStream in; + } else if (tflag) { + replaceFSC(files); if (fname != null) { - in = new FileInputStream(fname); + list(fname, files); } else { - in = new FileInputStream(FileDescriptor.in); + InputStream in = new FileInputStream(FileDescriptor.in); + try{ + list(new BufferedInputStream(in), files); + } finally { + in.close(); + } } - if (xflag) { - extract(new BufferedInputStream(in), files); + } else if (xflag) { + replaceFSC(files); + if (fname != null && files != null) { + extract(fname, files); } else { - list(new BufferedInputStream(in), files); + InputStream in = (fname == null) + ? new FileInputStream(FileDescriptor.in) + : new FileInputStream(fname); + try { + extract(new BufferedInputStream(in), files); + } finally { + in.close(); + } } - in.close(); } else if (iflag) { genIndex(rootjar, files); } @@ -760,6 +772,31 @@ class Main { e.setCrc(crc32.getValue()); } + void replaceFSC(String files[]) { + if (files != null) { + for (String file : files) { + file = file.replace(File.separatorChar, '/'); + } + } + } + + Set newDirSet() { + return new HashSet() { + public boolean add(ZipEntry e) { + return ((e == null || useExtractionTime) ? false : super.add(e)); + }}; + } + + void updateLastModifiedTime(Set zes) throws IOException { + for (ZipEntry ze : zes) { + long lastModified = ze.getTime(); + if (lastModified != -1) { + File f = new File(ze.getName().replace('/', File.separatorChar)); + f.setLastModified(lastModified); + } + } + } + /* * Extracts specified entries from JAR file. */ @@ -768,19 +805,13 @@ class Main { ZipEntry e; // Set of all directory entries specified in archive. Disallows // null entries. Disallows all entries if using pre-6.0 behavior. - Set dirs = new HashSet() { - public boolean add(ZipEntry e) { - return ((e == null || useExtractionTime) ? false : super.add(e)); - }}; - + Set dirs = newDirSet(); while ((e = zis.getNextEntry()) != null) { if (files == null) { dirs.add(extractFile(zis, e)); - } else { String name = e.getName(); - for (int i = 0; i < files.length; i++) { - String file = files[i].replace(File.separatorChar, '/'); + for (String file : files) { if (name.startsWith(file)) { dirs.add(extractFile(zis, e)); break; @@ -793,13 +824,33 @@ class Main { // timestamps as given in the archive. We do this after extraction, // instead of during, because creating a file in a directory changes // that directory's timestamp. - for (ZipEntry dirEntry : dirs) { - long lastModified = dirEntry.getTime(); - if (lastModified != -1) { - File dir = new File(dirEntry.getName().replace('/', File.separatorChar)); - dir.setLastModified(lastModified); + updateLastModifiedTime(dirs); + } + + /* + * Extracts specified entries from JAR file, via ZipFile. + */ + void extract(String fname, String files[]) throws IOException { + ZipFile zf = new ZipFile(fname); + Set dirs = newDirSet(); + Enumeration zes = zf.entries(); + while (zes.hasMoreElements()) { + ZipEntry e = zes.nextElement(); + InputStream is; + if (files == null) { + dirs.add(extractFile(zf.getInputStream(e), e)); + } else { + String name = e.getName(); + for (String file : files) { + if (name.startsWith(file)) { + dirs.add(extractFile(zf.getInputStream(e), e)); + break; + } + } } } + zf.close(); + updateLastModifiedTime(dirs); } /* @@ -807,7 +858,7 @@ class Main { * the entry is for a directory which doesn't exist prior to this * invocation, returns that entry, otherwise returns null. */ - ZipEntry extractFile(ZipInputStream zis, ZipEntry e) throws IOException { + ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException { ZipEntry rc = null; String name = e.getName(); File f = new File(e.getName().replace('/', File.separatorChar)); @@ -838,13 +889,19 @@ class Main { } } OutputStream os = new FileOutputStream(f); - byte[] b = new byte[512]; + byte[] b = new byte[8192]; int len; - while ((len = zis.read(b, 0, b.length)) != -1) { - os.write(b, 0, len); + try { + while ((len = is.read(b, 0, b.length)) != -1) { + os.write(b, 0, len); + } + } finally { + if (is instanceof ZipInputStream) + ((ZipInputStream)is).closeEntry(); + else + is.close(); + os.close(); } - zis.closeEntry(); - os.close(); if (vflag) { if (e.getMethod() == ZipEntry.DEFLATED) { output(formatMsg("out.inflated", name)); @@ -869,7 +926,6 @@ class Main { ZipInputStream zis = new ZipInputStream(in); ZipEntry e; while ((e = zis.getNextEntry()) != null) { - String name = e.getName(); /* * In the case of a compressed (deflated) entry, the entry size * is stored immediately following the entry data and cannot be @@ -877,20 +933,22 @@ class Main { * the entry first before printing out its attributes. */ zis.closeEntry(); - if (files == null) { - printEntry(e); - } else { - for (int i = 0; i < files.length; i++) { - String file = files[i].replace(File.separatorChar, '/'); - if (name.startsWith(file)) { - printEntry(e); - break; - } - } - } + printEntry(e, files); } } + /* + * Lists contents of JAR file, via ZipFile. + */ + void list(String fname, String files[]) throws IOException { + ZipFile zf = new ZipFile(fname); + Enumeration zes = zf.entries(); + while (zes.hasMoreElements()) { + printEntry(zes.nextElement(), files); + } + zf.close(); + } + /** * Output the class index table to the INDEX.LIST file of the * root jar file. @@ -974,13 +1032,29 @@ class Main { dumpIndex(rootjar, index); } + /* + * Prints entry information, if requested. + */ + void printEntry(ZipEntry e, String[] files) throws IOException { + if (files == null) { + printEntry(e); + } else { + String name = e.getName(); + for (String file : files) { + if (name.startsWith(file)) { + printEntry(e); + return; + } + } + } + } /* * Prints entry information. */ void printEntry(ZipEntry e) throws IOException { if (vflag) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); String s = Long.toString(e.getSize()); for (int i = 6 - s.length(); i > 0; --i) { sb.append(' '); diff --git a/jdk/src/share/classes/sun/util/resources/LocaleNames.properties b/jdk/src/share/classes/sun/util/resources/LocaleNames.properties index 15466144bf9..440f21534b5 100644 --- a/jdk/src/share/classes/sun/util/resources/LocaleNames.properties +++ b/jdk/src/share/classes/sun/util/resources/LocaleNames.properties @@ -257,6 +257,7 @@ BG=Bulgaria BH=Bahrain BI=Burundi BJ=Benin +BL=Saint Barth\u00e9lemy BM=Bermuda BN=Brunei BO=Bolivia @@ -370,6 +371,7 @@ MA=Morocco MC=Monaco MD=Moldova ME=Montenegro +MF=Saint Martin MG=Madagascar MH=Marshall Islands MK=Macedonia diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java index aae4dd35ea2..7b820ecd7c7 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -141,6 +141,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Malaysia Summer Time", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha Time", "FNT", "Fernando de Noronha Summer Time", "FNST"}; + String NPT[] = new String[] {"Nepal Time", "NPT", + "Nepal Summer Time", "NPST"}; String NST[] = new String[] {"Newfoundland Standard Time", "NST", "Newfoundland Daylight Time", "NDT"}; String NZST[] = new String[] {"New Zealand Standard Time", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Pakistan Summer Time", "PKST"}; String PST[] = new String[] {"Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}; + String RST[] = new String[] {"Eastern Standard Time", "EST", + "Central Daylight Time", "CDT"}; String SAST[] = new String[] {"South Africa Standard Time", "SAST", "South Africa Summer Time", "SAST"}; String SBT[] = new String[] {"Solomon Is. Time", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Petropavlovsk-Kamchatski Summer Time", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Nepal Time", "NPT", - "Nepal Summer Time", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Krasnoyarsk Time", "KRAT", "Krasnoyarsk Summer Time", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java index cdcb454601a..f8bd8ba84fa 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Malaysische Sommerzeit", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha Zeit", "FNT", "Fernando de Noronha Sommerzeit", "FNST"}; + String NPT[] = new String[] {"Nepalesische Zeit", "NPT", + "Nepalesische Sommerzeit", "NPST"}; String NST[] = new String[] {"Neufundland Normalzeit", "NST", "Neufundland Sommerzeit", "NDT"}; String NZST[] = new String[] {"Neuseeland Normalzeit", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Pakistanische Sommerzeit", "PKST"}; String PST[] = new String[] {"Pazifische Normalzeit", "PST", "Pazifische Sommerzeit", "PDT"}; + String RST[] = new String[] {"\u00d6stliche Normalzeit", "EST", + "Zentrale Sommerzeit", "CDT"}; String SAST[] = new String[] {"S\u00fcdafrikanische Normalzeit", "SAST", "S\u00fcdafrikanische Sommerzeit", "SAST"}; String SBT[] = new String[] {"Salomoninseln Zeit", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Petropawlowsk-Kamtschatkische Sommerzeit", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Nepalesische Zeit", "NPT", - "Nepalesische Sommerzeit", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Krasnojarsker Zeit", "KRAT", "Krasnojarsker Sommerzeit", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java index 557ea90c8d0..54651d69226 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Malasia", "MYST"}; String NORONHA[] = new String[] {"Hora de Fernando de Noronha", "FNT", "Hora de verano de Fernando de Noronha", "FNST"}; + String NPT[] = new String[] {"Hora de Nepal", "NPT", + "Hora de verano de Nepal", "NPST"}; String NST[] = new String[] {"Hora est\u00e1ndar de Terranova", "NST", "Hora de verano de Terranova", "NDT"}; String NZST[] = new String[] {"Hora est\u00e1ndar de Nueva Zelanda", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Pakist\u00e1n", "PKST"}; String PST[] = new String[] {"Hora est\u00e1ndar del Pac\u00edfico", "PST", "Hora de verano del Pac\u00edfico", "PDT"}; + String RST[] = new String[] {"Hora est\u00e1ndar Oriental", "EST", + "Hora de verano Central", "CDT"}; String SAST[] = new String[] {"Hora est\u00e1ndar de Sud\u00e1frica", "SAST", "Hora de verano de Sud\u00e1frica", "SAST"}; String SBT[] = new String[] {"Hora de las Islas Solomon", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Petropavlovsk-Kamchatski", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Hora de Nepal", "NPT", - "Hora de verano de Nepal", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Hora de Krasnoyarsk", "KRAT", "Hora de verano de Krasnoyarsk", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java index ec537df4671..0a91a783058 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Malaisie", "MYST"}; String NORONHA[] = new String[] {"Heure de Fernando de Noronha", "FNT", "Heure d'\u00e9t\u00e9 de Fernando de Noronha", "FNST"}; + String NPT[] = new String[] {"Heure du N\u00e9pal", "NPT", + "Heure d'\u00e9t\u00e9 du N\u00e9pal", "NPST"}; String NST[] = new String[] {"Heure normale de Terre-Neuve", "NST", "Heure avanc\u00e9e de Terre-Neuve", "NDT"} ; String NZST[] = new String[] {"Heure normale de Nouvelle-Z\u00e9lande", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 du Pakistan", "PKST"} ; String PST[] = new String[] {"Heure normale du Pacifique", "PST", "Heure avanc\u00e9e du Pacifique", "PDT"} ; + String RST[] = new String[] {"Heure normale de l'Est", "EST", + "Heure avanc\u00e9e du Centre", "CDT"} ; String SAST[] = new String[] {"Heure normale d'Afrique du Sud", "SAST", "Heure d'\u00e9t\u00e9 d'Afrique du Sud", "SAST"} ; String SBT[] = new String[] {"Heure des \u00celes Salomon", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Petropavlovsk-Kamchatski", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Heure du N\u00e9pal", "NPT", - "Heure d'\u00e9t\u00e9 du N\u00e9pal", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Heure de Krasno\u00efarsk", "KRAT", "Heure d'\u00e9t\u00e9 de Krasno\u00efarsk", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java index 4c7d79a8a7c..197dd5e8729 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva della Malaysia", "MYST"}; String NORONHA[] = new String[] {"Ora di Fernando de Noronha", "FNT", "Ora estiva di Fernando de Noronha", "FNST"}; + String NPT[] = new String[] {"Ora del Nepal", "NPT", + "Ora estiva del Nepal", "NPST"}; String NST[] = new String[] {"Ora solare di Terranova", "NST", "Ora legale di Terranova", "NDT"}; String NZST[] = new String[] {"Ora solare della Nuova Zelanda", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva del Pakistan", "PKST"}; String PST[] = new String[] {"Ora solare della costa occidentale USA", "PST", "Ora legale della costa occidentale USA", "PDT"}; + String RST[] = new String[] {"Ora solare USA orientale", "EST", + "Ora legale USA centrale", "CDT"}; String SAST[] = new String[] {"Ora solare del Sudafrica", "SAST", "Ora estiva del Sudafrica", "SAST"}; String SBT[] = new String[] {"Ora delle Isole Salomone", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva di Petropavlovsk-Kamchatski", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Ora del Nepal", "NPT", - "Ora estiva del Nepal", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Ora di Krasnojarsk", "KRAT", "Ora estiva di Krasnojarsk", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java index 2eb8063cbc7..3cf518acf41 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30de\u30ec\u30fc\u30b7\u30a2\u590f\u6642\u9593", "MYST"}; String NORONHA[] = new String[] {"\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u6642\u9593", "FNT", "\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u590f\u6642\u9593", "FNST"}; + String NPT[] = new String[] {"\u30cd\u30d1\u30fc\u30eb\u6642\u9593", "NPT", + "\u30cd\u30d1\u30fc\u30eb\u590f\u6642\u9593", "NPST"}; String NST[] = new String[] {"\u30cb\u30e5\u30fc\u30d5\u30a1\u30f3\u30c9\u30e9\u30f3\u30c9\u6a19\u6e96\u6642", "NST", "\u30cb\u30e5\u30fc\u30d5\u30a1\u30f3\u30c9\u30e9\u30f3\u30c9\u590f\u6642\u9593", "NDT"}; String NZST[] = new String[] {"\u30cb\u30e5\u30fc\u30b8\u30fc\u30e9\u30f3\u30c9\u6a19\u6e96\u6642", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30d1\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "PKST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642", "PST", "\u592a\u5e73\u6d0b\u590f\u6642\u9593", "PDT"}; + String RST[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642", "EST", + "\u4e2d\u90e8\u590f\u6642\u9593", "CDT"}; String SAST[] = new String[] {"\u5357\u30a2\u30d5\u30ea\u30ab\u6a19\u6e96\u6642", "SAST", "\u5357\u30a2\u30d5\u30ea\u30ab\u590f\u6642\u9593", "SAST"}; String SBT[] = new String[] {"\u30bd\u30ed\u30e2\u30f3\u8af8\u5cf6\u6642\u9593", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30da\u30c8\u30ed\u30d1\u30d6\u30ed\u30d5\u30b9\u30af\u30ab\u30e0\u30c1\u30e3\u30c4\u30ad\u30fc\u590f\u6642\u9593", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"\u30cd\u30d1\u30fc\u30eb\u6642\u9593", "NPT", - "\u30cd\u30d1\u30fc\u30eb\u590f\u6642\u9593", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u6642\u9593", "KRAT", "\u30af\u30e9\u30b9\u30ce\u30e4\u30eb\u30b9\u30af\u590f\u6642\u9593", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java index 81a23dd01e2..d03e1504491 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ub9d0\ub808\uc774\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha \uc2dc\uac04", "FNT", "Fernando de Noronha \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "FNST"}; + String NPT[] = new String[] {"\ub124\ud314 \uc2dc\uac04", "NPT", + "\ub124\ud314 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NPST"}; String NST[] = new String[] {"\ub274\ud380\ub4e4\ub79c\ub4dc \ud45c\uc900\uc2dc", "NST", "\ub274\ud380\ub4e4\ub79c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NDT"}; String NZST[] = new String[] {"\ub274\uc9c8\ub79c\ub4dc \ud45c\uc900\uc2dc", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ud30c\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PKST"}; String PST[] = new String[] {"\ud0dc\ud3c9\uc591 \ud45c\uc900\uc2dc", "PST", "\ud0dc\ud3c9\uc591 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PDT"}; + String RST[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc", "EST", + "\uc911\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CDT"}; String SAST[] = new String[] {"\ub0a8\uc544\ud504\ub9ac\uce74 \ud45c\uc900\uc2dc", "SAST", "\ub0a8\uc544\ud504\ub9ac\uce74 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SAST"}; String SBT[] = new String[] {"\uc194\ub85c\ubaac \uad70\ub3c4 \uc2dc\uac04", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ud398\ud2b8\ub85c\ud30c\ube14\ub85c\ud504\uc2a4\ud06c-\uce84\ucc28\uce20\ud0a4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"\ub124\ud314 \uc2dc\uac04", "NPT", - "\ub124\ud314 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc2dc\uac04", "KRAT", "\ud06c\ub77c\uc2a4\ub178\uc57c\ub974\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java index e56a8dbff30..2ede6f80801 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Malaysia, sommartid", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha, normaltid", "FNT", "Fernando de Noronha, sommartid", "FNST"}; + String NPT[] = new String[] {"Nepal, normaltid", "NPT", + "Nepal, sommartid", "NPST"}; String NST[] = new String[] {"Newfoundland, normaltid", "NST", "Newfoundland, sommartid", "NDT"}; String NZST[] = new String[] {"Nya Zeeland, normaltid", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Pakistan, sommartid", "PKST"}; String PST[] = new String[] {"Stilla havet, normaltid", "PST", "Stilla havet, sommartid", "PDT"}; + String RST[] = new String[] {"Eastern, normaltid", "EST", + "Central sommartid", "CDT"}; String SAST[] = new String[] {"Sydafrika, normaltid", "SAST", "Sydafrika, sommartid", "SAST"}; String SBT[] = new String[] {"Salomon\u00f6arna, normaltid", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Petropavlovsk-Kamtjatka, sommartid", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"Nepal, normaltid", "NPT", - "Nepal, sommartid", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"Krasnojarsk, normaltid", "KRAT", "Krasnojarsk, sommartid", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java index 41fec630ecd..121492ce4ab 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u9a6c\u6765\u897f\u4e9a\u590f\u4ee4\u65f6", "MYST"}; String NORONHA[] = new String[] {"\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u65f6\u95f4", "FNT", "\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u590f\u4ee4\u65f6", "FNST"}; + String NPT[] = new String[] {"\u5c3c\u6cca\u5c14\u65f6\u95f4", "NPT", + "\u5c3c\u6cca\u5c14\u590f\u4ee4\u65f6", "NPST"}; String NST[] = new String[] {"\u7ebd\u82ac\u5170\u6807\u51c6\u65f6\u95f4", "NST", "\u7ebd\u82ac\u5170\u590f\u4ee4\u65f6", "NDT"}; String NZST[] = new String[] {"\u65b0\u897f\u5170\u6807\u51c6\u65f6\u95f4", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u5df4\u57fa\u65af\u5766\u590f\u4ee4\u65f6", "PKST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4", "PST", "\u592a\u5e73\u6d0b\u590f\u4ee4\u65f6", "PDT"}; + String RST[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "EST", + "\u4e2d\u592e\u590f\u4ee4\u65f6", "CDT"}; String SAST[] = new String[] {"\u5357\u975e\u6807\u51c6\u65f6\u95f4", "SAST", "\u5357\u975e\u590f\u4ee4\u65f6", "SAST"}; String SBT[] = new String[] {"\u6240\u7f57\u95e8\u7fa4\u5c9b\u65f6\u95f4", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u5f7c\u5f97\u7f57\u5df4\u752b\u6d1b\u592b\u65af\u514b\u590f\u4ee4\u65f6", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"\u5c3c\u6cca\u5c14\u65f6\u95f4", "NPT", - "\u5c3c\u6cca\u5c14\u590f\u4ee4\u65f6", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u65f6\u95f4", "KRAT", "\u514b\u62c9\u65af\u8bfa\u4e9a\u5c14\u65af\u514b\u590f\u4ee4\u65f6", "KRAST"}}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java index 1bd6bf739d9..afd61097653 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java @@ -141,6 +141,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u99ac\u4f86\u897f\u4e9e\u590f\u4ee4\u6642\u9593", "MYST"}; String NORONHA[] = new String[] {"\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u6642\u9593", "FNT", "\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u590f\u4ee4\u6642\u9593", "FNST"}; + String NPT[] = new String[] {"\u5c3c\u6cca\u723e\u6642\u9593", "NPT", + "\u5c3c\u6cca\u723e\u590f\u4ee4\u6642\u9593", "NPST"}; String NST[] = new String[] {"\u7d10\u82ac\u862d\u6a19\u6e96\u6642\u9593", "NST", "\u7d10\u82ac\u862d\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "NDT"}; String NZST[] = new String[] {"\u7d10\u897f\u862d\u6a19\u6e96\u6642\u9593", "NZST", @@ -151,6 +153,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u5df4\u57fa\u65af\u5766\u590f\u4ee4\u6642\u9593", "PKST"}; String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642\u9593", "PST", "\u592a\u5e73\u6d0b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PDT"}; + String RST[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593", "EST", + "\u4e2d\u592e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CDT"}; String SAST[] = new String[] {"\u5357\u975e\u6a19\u6e96\u6642\u9593", "SAST", "\u5357\u975e\u590f\u4ee4\u6642\u9593", "SAST"}; String SBT[] = new String[] {"\u6240\u7f85\u9580\u7fa4\u5cf6\u6642\u9593", "SBT", @@ -290,6 +294,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Argentina/La_Rioja", AGT}, {"America/Argentina/Mendoza", AGT}, {"America/Argentina/Rio_Gallegos", AGT}, + {"America/Argentina/Salta", AGT}, {"America/Argentina/San_Juan", AGT}, {"America/Argentina/San_Luis", AGT}, {"America/Argentina/Tucuman", AGT}, @@ -407,7 +412,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"America/Rankin_Inlet", CST}, {"America/Recife", BRT}, {"America/Regina", CST}, - {"America/Resolute", EST}, + {"America/Resolute", RST}, {"America/Rio_Branco", AMT}, {"America/Rosario", AGT}, {"America/Santarem", BRT}, @@ -505,8 +510,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "Petropavlovsk-Kamchatski \u590f\u4ee4\u6642\u9593", "PETST"}}, {"Asia/Karachi", PKT}, {"Asia/Kashgar", CTT}, - {"Asia/Katmandu", new String[] {"\u5c3c\u6cca\u723e\u6642\u9593", "NPT", - "\u5c3c\u6cca\u723e\u590f\u4ee4\u6642\u9593", "NPST"}}, + {"Asia/Kathmandu", NPT}, + {"Asia/Katmandu", NPT}, {"Asia/Kolkata", IST}, {"Asia/Krasnoyarsk", new String[] {"\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u6642\u9593", "KRAT", "\u514b\u62c9\u65af\u8afe\u4e9e\u723e\u65af\u514b\u590f\u4ee4\u6642\u9593", "KRAST"}}, diff --git a/jdk/src/share/lib/audio/soundbank.gm b/jdk/src/share/lib/audio/soundbank.gm deleted file mode 100644 index 83c2f878d80..00000000000 Binary files a/jdk/src/share/lib/audio/soundbank.gm and /dev/null differ diff --git a/jdk/src/share/native/java/util/zip/zip_util.c b/jdk/src/share/native/java/util/zip/zip_util.c index 3b00b9500ac..9767dba451e 100644 --- a/jdk/src/share/native/java/util/zip/zip_util.c +++ b/jdk/src/share/native/java/util/zip/zip_util.c @@ -135,11 +135,6 @@ ZFILE_Close(ZFILE zfd) { #endif } -static jlong -ZFILE_Lseek(ZFILE zfd, off_t offset, int whence) { - return IO_Lseek(zfd, offset, whence); -} - static int ZFILE_read(ZFILE zfd, char *buf, jint nbytes) { #ifdef WIN32 @@ -216,7 +211,7 @@ readFully(ZFILE zfd, void *buf, jlong len) { static int readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset) { - if (ZFILE_Lseek(zfd, (off_t) offset, SEEK_SET) == -1) { + if (IO_Lseek(zfd, offset, SEEK_SET) == -1) { return -1; /* lseek failure. */ } @@ -476,7 +471,7 @@ readCEN(jzfile *zip, jint knownTotal) unsigned char *cp; #ifdef USE_MMAP static jlong pagesize; - off_t offset; + jlong offset; #endif unsigned char endbuf[ENDHDR]; jzcell *entries; @@ -534,7 +529,7 @@ readCEN(jzfile *zip, jint knownTotal) */ zip->mlen = cenpos - offset + cenlen + ENDHDR; zip->offset = offset; - mappedAddr = mmap(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, offset); + mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset); zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL : (unsigned char*)mappedAddr; @@ -720,7 +715,7 @@ ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified) return NULL; } - len = zip->len = ZFILE_Lseek(zfd, 0, SEEK_END); + len = zip->len = IO_Lseek(zfd, 0, SEEK_END); if (len <= 0) { if (len == 0) { /* zip file is empty */ if (pmsg) { diff --git a/jdk/src/share/native/java/util/zip/zip_util.h b/jdk/src/share/native/java/util/zip/zip_util.h index 5fdebaf1347..353ebd23862 100644 --- a/jdk/src/share/native/java/util/zip/zip_util.h +++ b/jdk/src/share/native/java/util/zip/zip_util.h @@ -174,7 +174,7 @@ typedef struct jzfile { /* Zip file */ #ifdef USE_MMAP unsigned char *maddr; /* beginning address of the CEN & ENDHDR */ jlong mlen; /* length (in bytes) mmaped */ - off_t offset; /* offset of the mmapped region from the + jlong offset; /* offset of the mmapped region from the start of the file. */ #else cencache cencache; /* CEN header cache */ diff --git a/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c b/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c index 70f95c6c59b..bcd546b1394 100644 --- a/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c +++ b/jdk/src/share/native/sun/nio/ch/genSocketOptionRegistry.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,9 +71,9 @@ int main(int argc, const char* argv[]) { out("class SocketOptionRegistry { "); out(" private SocketOptionRegistry() { } "); out(" private static class RegistryKey { "); - out(" private final SocketOption name; "); + out(" private final SocketOption name; "); out(" private final ProtocolFamily family; "); - out(" RegistryKey(SocketOption name, ProtocolFamily family) { "); + out(" RegistryKey(SocketOption name, ProtocolFamily family) { "); out(" this.name = name; "); out(" this.family = family; "); out(" } "); @@ -119,7 +119,7 @@ int main(int argc, const char* argv[]) { out(" return map; "); out(" } "); out(" } "); - out(" public static OptionKey findOption(SocketOption name, ProtocolFamily family) { "); + out(" public static OptionKey findOption(SocketOption name, ProtocolFamily family) { "); out(" RegistryKey key = new RegistryKey(name, family); "); out(" return LazyInitialization.options.get(key); "); out(" } "); diff --git a/jdk/src/share/sample/nio/file/AclEdit.java b/jdk/src/share/sample/nio/file/AclEdit.java new file mode 100644 index 00000000000..55ed9c00bee --- /dev/null +++ b/jdk/src/share/sample/nio/file/AclEdit.java @@ -0,0 +1,296 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.util.regex.Pattern; + +/** + * Sample utility for editing a file's ACL. + */ + +public class AclEdit { + + // parse string as list of ACE permissions separated by / + static Set parsePermissions(String permsString) { + Set perms = new HashSet(); + String[] result = permsString.split("/"); + for (String s : result) { + if (s.equals("")) + continue; + try { + perms.add(AclEntryPermission.valueOf(s.toUpperCase())); + } catch (IllegalArgumentException x) { + System.err.format("Invalid permission '%s'\n", s); + System.exit(-1); + } + } + return perms; + } + + // parse string as list of ACE flags separated by / + static Set parseFlags(String flagsString) { + Set flags = new HashSet(); + String[] result = flagsString.split("/"); + for (String s : result) { + if (s.equals("")) + continue; + try { + flags.add(AclEntryFlag.valueOf(s.toUpperCase())); + } catch (IllegalArgumentException x) { + System.err.format("Invalid flag '%s'\n", s); + System.exit(-1); + } + } + return flags; + } + + // parse ACE type + static AclEntryType parseType(String typeString) { + // FIXME: support audit and alarm types in the future + if (typeString.equalsIgnoreCase("allow")) + return AclEntryType.ALLOW; + if (typeString.equalsIgnoreCase("deny")) + return AclEntryType.DENY; + System.err.format("Invalid type '%s'\n", typeString); + System.exit(-1); + return null; // keep compiler happy + } + + /** + * Parse string of the form: + * [user|group:]:[:flags]: + */ + static AclEntry parseAceString(String s, + UserPrincipalLookupService lookupService) + { + String[] result = s.split(":"); + + // must have at least 3 components (username:perms:type) + if (result.length < 3) + usage(); + + int index = 0; + int remaining = result.length; + + // optional first component can indicate user or group type + boolean isGroup = false; + if (result[index].equalsIgnoreCase("user") || + result[index].equalsIgnoreCase("group")) + { + if (--remaining < 3) + usage(); + isGroup = result[index++].equalsIgnoreCase("group"); + } + + // user and permissions required + String userString = result[index++]; remaining--; + String permsString = result[index++]; remaining--; + + // flags are optional + String flagsString = ""; + String typeString = null; + if (remaining == 1) { + typeString = result[index++]; + } else { + if (remaining == 2) { + flagsString = result[index++]; + typeString = result[index++]; + } else { + usage(); + } + } + + // lookup UserPrincipal + UserPrincipal user = null; + try { + user = (isGroup) ? + lookupService.lookupPrincipalByGroupName(userString) : + lookupService.lookupPrincipalByName(userString); + } catch (UserPrincipalNotFoundException x) { + System.err.format("Invalid %s '%s'\n", + ((isGroup) ? "group" : "user"), + userString); + System.exit(-1); + } catch (IOException x) { + System.err.format("Lookup of '%s' failed: %s\n", userString, x); + System.exit(-1); + } + + // map string representation of permissions, flags, and type + Set perms = parsePermissions(permsString); + Set flags = parseFlags(flagsString); + AclEntryType type = parseType(typeString); + + // build the ACL entry + return AclEntry.newBuilder() + .setType(type) + .setPrincipal(user) + .setPermissions(perms).setFlags(flags).build(); + } + + static void usage() { + System.err.println("usage: java AclEdit [ACL-operation] file"); + System.err.println(""); + System.err.println("Example 1: Prepends access control entry to the begining of the myfile's ACL"); + System.err.println(" java AclEdit A+alice:read_data/read_attributes:allow myfile"); + System.err.println(""); + System.err.println("Example 2: Remove the entry at index 6 of myfile's ACL"); + System.err.println(" java AclEdit A6- myfile"); + System.err.println(""); + System.err.println("Example 3: Replace the entry at index 2 of myfile's ACL"); + System.err.println(" java AclEdit A2=bob:write_data/append_data:deny myfile"); + System.exit(-1); + } + + static enum Action { + PRINT, + ADD, + REMOVE, + REPLACE; + } + + /** + * Main class: parses arguments and prints or edits ACL + */ + public static void main(String[] args) throws IOException { + Action action = null; + int index = -1; + String entryString = null; + + // parse arguments + if (args.length < 1 || args[0].equals("-help") || args[0].equals("-?")) + usage(); + + if (args.length == 1) { + action = Action.PRINT; + } else { + String s = args[0]; + + // A[index]+entry + if (Pattern.matches("^A[0-9]*\\+.*", s)) { + String[] result = s.split("\\+", 2); + if (result.length == 2) { + if (result[0].length() < 2) { + index = 0; + } else { + index = Integer.parseInt(result[0].substring(1)); + } + entryString = result[1]; + action = Action.ADD; + } + } + + // Aindex- + if (Pattern.matches("^A[0-9]+\\-", s)) { + String[] result = s.split("\\-", 2); + if (result.length == 2) { + index = Integer.parseInt(result[0].substring(1)); + entryString = result[1]; + action = Action.REMOVE; + } + } + + // Aindex=entry + if (Pattern.matches("^A[0-9]+=.*", s)) { + String[] result = s.split("=", 2); + if (result.length == 2) { + index = Integer.parseInt(result[0].substring(1)); + entryString = result[1]; + action = Action.REPLACE; + } + } + } + if (action == null) + usage(); + + int fileArg = (action == Action.PRINT) ? 0 : 1; + Path file = Paths.get(args[fileArg]); + + // read file's ACL + AclFileAttributeView view = + file.getFileAttributeView(AclFileAttributeView.class); + if (view == null) { + System.err.println("ACLs not supported on this platform"); + System.exit(-1); + } + List acl = view.getAcl(); + + switch (action) { + // print ACL + case PRINT : { + for (int i=0; i= acl.size()) { + acl.add(entry); + } else { + acl.add(index, entry); + } + view.setAcl(acl); + break; + } + + // remove ACE + case REMOVE: { + if (index >= acl.size()) { + System.err.format("Index '%d' is invalid", index); + System.exit(-1); + } + acl.remove(index); + view.setAcl(acl); + break; + } + + // replace ACE + case REPLACE: { + if (index >= acl.size()) { + System.err.format("Index '%d' is invalid", index); + System.exit(-1); + } + AclEntry entry = parseAceString(entryString, file + .getFileSystem().getUserPrincipalLookupService()); + acl.set(index, entry); + view.setAcl(acl); + break; + } + } + } +} diff --git a/jdk/src/share/sample/nio/file/Chmod.java b/jdk/src/share/sample/nio/file/Chmod.java new file mode 100644 index 00000000000..eeb54ad6cd5 --- /dev/null +++ b/jdk/src/share/sample/nio/file/Chmod.java @@ -0,0 +1,347 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import static java.nio.file.attribute.PosixFilePermission.*; +import static java.nio.file.FileVisitResult.*; +import java.io.IOException; +import java.util.*; + +/** + * Sample code that changes the permissions of files in a similar manner to the + * chmod(1) program. + */ + +public class Chmod { + + /** + * Compiles a list of one or more symbolic mode expressions that + * may be used to change a set of file permissions. This method is + * intended for use where file permissions are required to be changed in + * a manner similar to the UNIX chmod program. + * + *

The {@code exprs} parameter is a comma separated list of expressions + * where each takes the form: + *

+ * who operator [permissions] + *
+ * where who is one or more of the characters {@code 'u'}, {@code 'g'}, + * {@code 'o'}, or {@code 'a'} meaning the owner (user), group, others, or + * all (owner, group, and others) respectively. + * + *

operator is the character {@code '+'}, {@code '-'}, or {@code + * '='} signifying how permissions are to be changed. {@code '+'} means the + * permissions are added, {@code '-'} means the permissions are removed, and + * {@code '='} means the permissions are assigned absolutely. + * + *

permissions is a sequence of zero or more of the following: + * {@code 'r'} for read permission, {@code 'w'} for write permission, and + * {@code 'x'} for execute permission. If permissions is omitted + * when assigned absolutely, then the permissions are cleared for + * the owner, group, or others as identified by who. When omitted + * when adding or removing then the expression is ignored. + * + *

The following examples demonstrate possible values for the {@code + * exprs} parameter: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
{@code u=rw} Sets the owner permissions to be read and write.
{@code ug+w} Sets the owner write and group write permissions.
{@code u+w,o-rwx} Sets the owner write, and removes the others read, others write + * and others execute permissions.
{@code o=} Sets the others permission to none (others read, others write and + * others execute permissions are removed if set)
+ * + * @param exprs + * List of one or more symbolic mode expressions + * + * @return A {@code Changer} that may be used to changer a set of + * file permissions + * + * @throws IllegalArgumentException + * If the value of the {@code exprs} parameter is invalid + */ + public static Changer compile(String exprs) { + // minimum is who and operator (u= for example) + if (exprs.length() < 2) + throw new IllegalArgumentException("Invalid mode"); + + // permissions that the changer will add or remove + final Set toAdd = new HashSet(); + final Set toRemove = new HashSet(); + + // iterate over each of expression modes + for (String expr: exprs.split(",")) { + // minimum of who and operator + if (expr.length() < 2) + throw new IllegalArgumentException("Invalid mode"); + + int pos = 0; + + // who + boolean u = false; + boolean g = false; + boolean o = false; + boolean done = false; + for (;;) { + switch (expr.charAt(pos)) { + case 'u' : u = true; break; + case 'g' : g = true; break; + case 'o' : o = true; break; + case 'a' : u = true; g = true; o = true; break; + default : done = true; + } + if (done) + break; + pos++; + } + if (!u && !g && !o) + throw new IllegalArgumentException("Invalid mode"); + + // get operator and permissions + char op = expr.charAt(pos++); + String mask = (expr.length() == pos) ? "" : expr.substring(pos); + + // operator + boolean add = (op == '+'); + boolean remove = (op == '-'); + boolean assign = (op == '='); + if (!add && !remove && !assign) + throw new IllegalArgumentException("Invalid mode"); + + // who= means remove all + if (assign && mask.length() == 0) { + assign = false; + remove = true; + mask = "rwx"; + } + + // permissions + boolean r = false; + boolean w = false; + boolean x = false; + for (int i=0; i change(Set perms) { + perms.addAll(toAdd); + perms.removeAll(toRemove); + return perms; + } + }; + } + + /** + * A task that changes a set of {@link PosixFilePermission} elements. + */ + public interface Changer { + /** + * Applies the changes to the given set of permissions. + * + * @param perms + * The set of permissions to change + * + * @return The {@code perms} parameter + */ + Set change(Set perms); + } + + /** + * Changes the permissions of the file using the given Changer. + */ + static void chmod(FileRef file, Changer changer) { + try { + Set perms = Attributes + .readPosixFileAttributes(file).permissions(); + Attributes.setPosixFilePermissions(file, changer.change(perms)); + } catch (IOException x) { + System.err.println(x); + } + } + + /** + * Changes the permission of each file and directory visited + */ + static class TreeVisitor implements FileVisitor { + private final Changer changer; + + TreeVisitor(Changer changer) { + this.changer = changer; + } + + @Override + public FileVisitResult preVisitDirectory(FileRef dir) { + chmod(dir, changer); + return CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) { + System.err.println("WARNING: " + exc); + return CONTINUE; + } + + @Override + public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) { + chmod(file, changer); + return CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) { + if (exc != null) + System.err.println("WARNING: " + exc); + return CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(FileRef file, IOException exc) { + System.err.println("WARNING: " + exc); + return CONTINUE; + } + } + + static void usage() { + System.err.println("java Chmod [-R] symbolic-mode-list file..."); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + if (args.length < 2) + usage(); + int argi = 0; + int maxDepth = 0; + if (args[argi].equals("-R")) { + if (args.length < 3) + usage(); + argi++; + maxDepth = Integer.MAX_VALUE; + } + + // compile the symbolic mode expressions + Changer changer = compile(args[argi++]); + TreeVisitor visitor = new TreeVisitor(changer); + + Set opts = Collections.emptySet(); + while (argi < args.length) { + Path file = Paths.get(args[argi]); + Files.walkFileTree(file, opts, maxDepth, visitor); + argi++; + } + } +} diff --git a/jdk/src/share/sample/nio/file/Copy.java b/jdk/src/share/sample/nio/file/Copy.java new file mode 100644 index 00000000000..e1d5d044ef5 --- /dev/null +++ b/jdk/src/share/sample/nio/file/Copy.java @@ -0,0 +1,217 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import static java.nio.file.StandardCopyOption.*; +import java.nio.file.attribute.*; +import static java.nio.file.FileVisitResult.*; +import java.io.IOException; +import java.util.*; + +/** + * Sample code that copies files in a similar manner to the cp(1) program. + */ + +public class Copy { + + /** + * Returns {@code true} if okay to overwrite a file ("cp -i") + */ + static boolean okayToOverwrite(FileRef file) { + String answer = System.console().readLine("overwrite %s (yes/no)? ", file); + return (answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("yes")); + } + + /** + * Copy source file to target location. If {@code prompt} is true then + * prompted user to overwrite target if it exists. The {@code preserve} + * parameter determines if file attributes should be copied/preserved. + */ + static void copyFile(Path source, Path target, boolean prompt, boolean preserve) { + CopyOption[] options = (preserve) ? + new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } : + new CopyOption[] { REPLACE_EXISTING }; + if (!prompt || target.notExists() || okayToOverwrite(target)) { + try { + source.copyTo(target, options); + } catch (IOException x) { + System.err.format("Unable to create: %s: %s%n", target, x); + } + } + } + + /** + * A {@code FileVisitor} that copies a file-tree ("cp -r") + */ + static class TreeCopier implements FileVisitor { + private final Path source; + private final Path target; + private final boolean prompt; + private final boolean preserve; + + TreeCopier(Path source, Path target, boolean prompt, boolean preserve) { + this.source = source; + this.target = target; + this.prompt = prompt; + this.preserve = preserve; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir) { + // before visiting entries in a directory we copy the directory + // (okay if directory already exists). + CopyOption[] options = (preserve) ? + new CopyOption[] { COPY_ATTRIBUTES } : new CopyOption[0]; + + Path newdir = target.resolve(source.relativize(dir)); + try { + dir.copyTo(newdir, options); + } catch (FileAlreadyExistsException x) { + // ignore + } catch (IOException x) { + System.err.format("Unable to create: %s: %s%n", newdir, x); + return SKIP_SUBTREE; + } + return CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) { + System.err.format("Unable to copy: %s: %s%n", dir, exc); + return CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (attrs.isDirectory()) { + System.err.println("cycle detected: " + file); + } else { + copyFile(file, target.resolve(source.relativize(file)), + prompt, preserve); + } + return CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + // fix up modification time of directory when done + if (exc == null && preserve) { + try { + BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir); + Path newdir = target.resolve(source.relativize(dir)); + Attributes.setLastModifiedTime(newdir, + attrs.lastModifiedTime(), attrs.resolution()); + } catch (IOException x) { + // ignore + } + } + return CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + System.err.format("Unable to copy: %s: %s%n", file, exc); + return CONTINUE; + } + } + + static void usage() { + System.err.println("java Copy [-ip] source... target"); + System.err.println("java Copy -r [-ip] source-dir... target"); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + boolean recursive = false; + boolean prompt = false; + boolean preserve = false; + + // process options + int argi = 0; + while (argi < args.length) { + String arg = args[argi]; + if (!arg.startsWith("-")) + break; + if (arg.length() < 2) + usage(); + for (int i=1; i 1) { + source[i++] = Paths.get(args[argi++]); + remaining--; + } + Path target = Paths.get(args[argi]); + + // check if target is a directory + boolean isDir = false; + try { + isDir = Attributes.readBasicFileAttributes(target).isDirectory(); + } catch (IOException x) { + } + + // copy each source file/directory to target + for (i=0; i opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS); + TreeCopier tc = new TreeCopier(source[i], dest, prompt, preserve); + Files.walkFileTree(source[i], opts, -1, tc); + } else { + // not recursive so source must not be a directory + try { + if (Attributes.readBasicFileAttributes(source[i]).isDirectory()) { + System.err.format("%s: is a directory%n", source[i]); + continue; + } + } catch (IOException x) { } + copyFile(source[i], dest, prompt, preserve); + } + } + } +} diff --git a/jdk/src/share/sample/nio/file/DiskUsage.java b/jdk/src/share/sample/nio/file/DiskUsage.java new file mode 100644 index 00000000000..ff16d888490 --- /dev/null +++ b/jdk/src/share/sample/nio/file/DiskUsage.java @@ -0,0 +1,74 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + +/** + * Example utility that works like the df(1M) program to print out disk space + * information + */ + +public class DiskUsage { + + static final long K = 1024; + + static void printFileStore(FileStore store) throws IOException { + FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store); + + long total = attrs.totalSpace() / K; + long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K; + long avail = attrs.usableSpace() / K; + + String s = store.toString(); + if (s.length() > 20) { + System.out.println(s); + s = ""; + } + System.out.format("%-20s %12d %12d %12d\n", s, total, used, avail); + } + + public static void main(String[] args) throws IOException { + System.out.format("%-20s %12s %12s %12s\n", "Filesystem", "kbytes", "used", "avail"); + if (args.length == 0) { + FileSystem fs = FileSystems.getDefault(); + for (FileStore store: fs.getFileStores()) { + printFileStore(store); + } + } else { + for (String file: args) { + FileStore store = Paths.get(file).getFileStore(); + printFileStore(store); + } + } + } +} diff --git a/jdk/src/share/sample/nio/file/FileType.java b/jdk/src/share/sample/nio/file/FileType.java new file mode 100644 index 00000000000..31fb45299a2 --- /dev/null +++ b/jdk/src/share/sample/nio/file/FileType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + +public class FileType { + public static void main(String[] args) throws IOException { + if (args.length == 0) { + System.err.println("usage: java FileType file..."); + System.exit(-1); + } + for (String arg: args) { + Path file = Paths.get(arg); + BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file); + + String type; + if (attrs.isDirectory()) { + type = "directory"; + } else { + type = Files.probeContentType(file); + if (type == null) + type = ""; + } + System.out.format("%s\t%s%n", file, type); + } + } +} diff --git a/jdk/src/share/sample/nio/file/WatchDir.java b/jdk/src/share/sample/nio/file/WatchDir.java new file mode 100644 index 00000000000..b8b6474dc6f --- /dev/null +++ b/jdk/src/share/sample/nio/file/WatchDir.java @@ -0,0 +1,196 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKind.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.io.*; +import java.util.*; + +/** + * Example to watch a directory (or tree) for changes to files. + */ + +public class WatchDir { + + private final WatchService watcher; + private final Map keys; + private final boolean recursive; + private boolean trace = false; + + @SuppressWarnings("unchecked") + static WatchEvent cast(WatchEvent event) { + return (WatchEvent)event; + } + + /** + * Register the given directory with the WatchService + */ + private void register(Path dir) throws IOException { + WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); + if (trace) { + FileRef prev = keys.get(key); + if (prev == null) { + System.out.format("register: %s\n", dir); + } else { + if (!dir.equals(prev)) { + System.out.format("update: %s -> %s\n", prev, dir); + } + } + } + keys.put(key, dir); + } + + /** + * Register the given directory, and all its sub-directories, with the + * WatchService. + */ + private void registerAll(final Path start) throws IOException { + // register directory and sub-directories + Files.walkFileTree(start, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir) { + try { + register(dir); + } catch (IOException x) { + throw new IOError(x); + } + return FileVisitResult.CONTINUE; + } + }); + } + + /** + * Creates a WatchService and registers the given directory + */ + WatchDir(Path dir, boolean recursive) throws IOException { + this.watcher = FileSystems.getDefault().newWatchService(); + this.keys = new HashMap(); + this.recursive = recursive; + + if (recursive) { + System.out.format("Scanning %s ...\n", dir); + registerAll(dir); + System.out.println("Done."); + } else { + register(dir); + } + + // enable trace after initial registration + this.trace = true; + } + + /** + * Process all events for keys queued to the watcher + */ + void processEvents() { + for (;;) { + + // wait for key to be signalled + WatchKey key; + try { + key = watcher.take(); + } catch (InterruptedException x) { + return; + } + + Path dir = keys.get(key); + if (dir == null) { + System.err.println("WatchKey not recognized!!"); + continue; + } + + for (WatchEvent event: key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + + // TBD - provide example of how OVERFLOW event is handled + if (kind == OVERFLOW) { + continue; + } + + // Context for directory entry event is the file name of entry + WatchEvent ev = cast(event); + Path name = ev.context(); + Path child = dir.resolve(name); + + // print out event + System.out.format("%s: %s\n", event.kind().name(), child); + + // if directory is created, and watching recursively, then + // register it and its sub-directories + if (recursive && (kind == ENTRY_CREATE)) { + try { + if (Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS).isDirectory()) { + registerAll(child); + } + } catch (IOException x) { + // ignore to keep sample readbale + } + } + } + + // reset key and remove from set if directory no longer accessible + boolean valid = key.reset(); + if (!valid) { + keys.remove(key); + + // all directories are inaccessible + if (keys.isEmpty()) { + break; + } + } + } + } + + static void usage() { + System.err.println("usage: java WatchDir [-r] dir"); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + // parse arguments + if (args.length == 0 || args.length > 2) + usage(); + boolean recursive = false; + int dirArg = 0; + if (args[0].equals("-r")) { + if (args.length < 2) + usage(); + recursive = true; + dirArg++; + } + + // register directory and process its events + Path dir = Paths.get(args[dirArg]); + new WatchDir(dir, recursive).processEvents(); + } +} diff --git a/jdk/src/share/sample/nio/file/Xdd.java b/jdk/src/share/sample/nio/file/Xdd.java new file mode 100644 index 00000000000..f66597eddd4 --- /dev/null +++ b/jdk/src/share/sample/nio/file/Xdd.java @@ -0,0 +1,112 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Sun Microsystems nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + +/** + * Example code to list/set/get/delete the user-defined attributes of a file. + */ + +public class Xdd { + + static void usage() { + System.out.println("Usage: java Xdd "); + System.out.println(" java Xdd -set = "); + System.out.println(" java Xdd -get "); + System.out.println(" java Xdd -del "); + System.exit(-1); + } + + public static void main(String[] args) throws IOException { + // one or three parameters + if (args.length != 1 && args.length != 3) + usage(); + + Path file = (args.length == 1) ? + Paths.get(args[0]) : Paths.get(args[2]); + + // check that user defined attributes are supported by the file system + FileStore store = file.getFileStore(); + if (!store.supportsFileAttributeView("xattr")) { + System.err.format("UserDefinedFileAttributeView not supported on %s\n", store); + System.exit(-1); + + } + UserDefinedFileAttributeView view = file. + getFileAttributeView(UserDefinedFileAttributeView.class); + + // list user defined attributes + if (args.length == 1) { + System.out.println(" Size Name"); + System.out.println("-------- --------------------------------------"); + for (String name: view.list()) { + System.out.format("%8d %s\n", view.size(name), name); + } + return; + } + + // Add/replace a file's user defined attribute + if (args[0].equals("-set")) { + // name=value + String[] s = args[1].split("="); + if (s.length != 2) + usage(); + String name = s[0]; + String value = s[1]; + view.write(name, Charset.defaultCharset().encode(value)); + return; + } + + // Print out the value of a file's user defined attribute + if (args[0].equals("-get")) { + String name = args[1]; + int size = view.size(name); + ByteBuffer buf = ByteBuffer.allocateDirect(size); + view.read(name, buf); + buf.flip(); + System.out.println(Charset.defaultCharset().decode(buf).toString()); + return; + } + + // Delete a file's user defined attribute + if (args[0].equals("-del")) { + view.delete(args[1]); + return; + } + + // option not recognized + usage(); + } + } diff --git a/jdk/src/solaris/classes/sun/awt/X11/WindowDimensions.java b/jdk/src/solaris/classes/sun/awt/X11/WindowDimensions.java index 08511f9e67a..70447fee3ef 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/WindowDimensions.java +++ b/jdk/src/solaris/classes/sun/awt/X11/WindowDimensions.java @@ -32,10 +32,18 @@ class WindowDimensions { private Insets insets; private boolean isClientSizeSet; + /** + * If isClient is true, the bounds represent the client window area. + * Otherwise, they represent the entire window area, with the insets included + */ public WindowDimensions(int x, int y, int width, int height, boolean isClient) { this(new Rectangle(x, y, width, height), null, isClient); } + /** + * If isClient is true, the bounds represent the client window area. + * Otherwise, they represent the entire window area, with the insets included + */ public WindowDimensions(Rectangle rec, Insets ins, boolean isClient) { if (rec == null) { throw new IllegalArgumentException("Client bounds can't be null"); @@ -46,10 +54,18 @@ class WindowDimensions { setInsets(ins); } + /** + * If isClient is true, the bounds represent the client window area. + * Otherwise, they represent the entire window area, with the insets included + */ public WindowDimensions(Point loc, Dimension size, Insets in, boolean isClient) { this(new Rectangle(loc, size), in, isClient); } + /** + * If isClient is true, the bounds represent the client window area. + * Otherwise, they represent the entire window area, with the insets included + */ public WindowDimensions(Rectangle bounds, boolean isClient) { this(bounds, null, isClient); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java index f853d506784..ace8b583077 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java @@ -979,8 +979,13 @@ public class XBaseWindow { */ public void handleButtonPressRelease(XEvent xev) { XButtonEvent xbe = xev.get_xbutton(); - final int buttonState = xbe.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask - | XConstants.Button3Mask | XConstants.Button4Mask | XConstants.Button5Mask); + int buttonState = 0; + for (int i = 0; i XToolkit.getNumMouseButtons()) { + return buttonState == 0; + } else { + return buttonState == XConstants.buttonsMask[button - 1]; } - return buttonState == 0; } static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java index 651d10a2905..8a14cfe5f0f 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java @@ -1534,13 +1534,23 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget } XToolkit.awtLock(); try { - XlibWrapper.SetRectangularShape( - XToolkit.getDisplay(), - getWindow(), - shape.getLoX(), shape.getLoY(), - shape.getHiX(), shape.getHiY(), - (shape.isRectangular() ? null : shape) - ); + if (shape != null) { + XlibWrapper.SetRectangularShape( + XToolkit.getDisplay(), + getWindow(), + shape.getLoX(), shape.getLoY(), + shape.getHiX(), shape.getHiY(), + (shape.isRectangular() ? null : shape) + ); + } else { + XlibWrapper.SetRectangularShape( + XToolkit.getDisplay(), + getWindow(), + 0, 0, + 0, 0, + null + ); + } } finally { XToolkit.awtUnlock(); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java index e9de6804bea..7d9077ee6a9 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java @@ -197,12 +197,30 @@ final public class XConstants { /* button masks. Used in same manner as Key masks above. Not to be confused with button names below. */ - - public static final int Button1Mask = (1<<8) ; - public static final int Button2Mask = (1<<9) ; - public static final int Button3Mask = (1<<10) ; - public static final int Button4Mask = (1<<11) ; - public static final int Button5Mask = (1<<12) ; + public static final int [] buttonsMask = new int []{ 1<<8, + 1<<9, + 1<<10, + 1<<11, + 1<<12, + 1<<13, + 1<<14, + 1<<15, + 1<<16, + 1<<17, + 1<<18, + 1<<19, + 1<<20, + 1<<21, + 1<<22, + 1<<23, + 1<<24, + 1<<25, + 1<<26, + 1<<27, + 1<<28, + 1<<29, + 1<<30, + 1<<31 }; public static final int AnyModifier = (1<<15) ; /* used in GrabButton, GrabKey */ @@ -211,11 +229,7 @@ final public class XConstants { and ButtonRelease events. Not to be confused with button masks above. Note that 0 is already defined above as "AnyButton". */ - public static final int Button1 = 1 ; - public static final int Button2 = 2 ; - public static final int Button3 = 3 ; - public static final int Button4 = 4 ; - public static final int Button5 = 5 ; + public static final int buttons [] = new int [] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; /* Notify modes */ diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java index 5984db22493..42ccabee313 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java @@ -492,7 +492,14 @@ abstract class XDecoratedPeer extends XWindowPeer { // do nothing but accept it. Rectangle reqBounds = newDimensions.getBounds(); Rectangle newBounds = constrainBounds(reqBounds.x, reqBounds.y, reqBounds.width, reqBounds.height); - newDimensions = new WindowDimensions(newBounds, newDimensions.getInsets(), newDimensions.isClientSizeSet()); + Insets insets = newDimensions.getInsets(); + // Inherit isClientSizeSet from newDimensions + if (newDimensions.isClientSizeSet()) { + newBounds = new Rectangle(newBounds.x, newBounds.y, + newBounds.width - insets.left - insets.right, + newBounds.height - insets.top - insets.bottom); + } + newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet()); } XToolkit.awtLock(); try { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java index af3a3219cff..a079fdb2bab 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java @@ -694,8 +694,8 @@ public final class XDragSourceContextPeer } finally { xmotion.dispose(); } - if (xbutton.get_button() == XConstants.Button1 - || xbutton.get_button() == XConstants.Button2) { + if (xbutton.get_button() == XConstants.buttons[0] + || xbutton.get_button() == XConstants.buttons[1]) { // drag is initiated with Button1 or Button2 pressed and // ended on release of either of these buttons (as the same // behavior was with our old Motif DnD-based implementation) diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java index 139f375fa40..8be2390754c 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java @@ -31,6 +31,9 @@ import sun.awt.SunToolkit; import java.awt.Component; import java.awt.Container; +import sun.awt.X11GraphicsConfig; +import sun.awt.X11GraphicsDevice; + /** * Helper class implementing XEmbed protocol handling routines(client side) * Window which wants to participate in a protocol should create an instance, @@ -39,20 +42,34 @@ import java.awt.Container; public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher { private static final Logger xembedLog = Logger.getLogger("sun.awt.X11.xembed.XEmbedClientHelper"); - private XEmbeddedFramePeer embedded; + private XEmbeddedFramePeer embedded; // XEmbed client + private long server; // XEmbed server + private boolean active; - private long server; private boolean applicationActive; XEmbedClientHelper() { super(); } - void install(XEmbeddedFramePeer embedded) { - this.embedded = embedded; + void setClient(XEmbeddedFramePeer client) { + if (xembedLog.isLoggable(Level.FINE)) { + xembedLog.fine("XEmbed client: " + client); + } + if (embedded != null) { + XToolkit.removeEventDispatcher(embedded.getWindow(), this); + active = false; + } + embedded = client; + if (embedded != null) { + XToolkit.addEventDispatcher(embedded.getWindow(), this); + } + } - if (xembedLog.isLoggable(Level.FINE)) xembedLog.fine("Installing xembedder on " + embedded); - XToolkit.addEventDispatcher(embedded.getWindow(), this); + void install() { + if (xembedLog.isLoggable(Level.FINE)) { + xembedLog.fine("Installing xembedder on " + embedded); + } long[] info = new long[] { XEMBED_VERSION, XEMBED_MAPPED }; long data = Native.card32ToData(info); try { @@ -155,7 +172,24 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher } public void handleReparentNotify(XEvent xev) { XReparentEvent re = xev.get_xreparent(); - server = re.get_parent(); + long newParent = re.get_parent(); + if (active) { + // unregister accelerators, etc. for old parent + embedded.notifyStopped(); + // check if newParent is a root window + X11GraphicsConfig gc = (X11GraphicsConfig)embedded.getGraphicsConfiguration(); + X11GraphicsDevice gd = (X11GraphicsDevice)gc.getDevice(); + if ((newParent == XlibUtil.getRootWindow(gd.getScreen())) || + (newParent == XToolkit.getDefaultRootWindow())) + { + // reparenting to root means XEmbed termination + active = false; + } else { + // continue XEmbed with a new parent + server = newParent; + embedded.notifyStarted(); + } + } } boolean requestFocus() { if (active && embedded.focusAllowedFor()) { @@ -201,12 +235,16 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher } void registerAccelerator(AWTKeyStroke stroke, int id) { - long sym = getX11KeySym(stroke); - long mods = getX11Mods(stroke); - sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods); + if (active) { + long sym = getX11KeySym(stroke); + long mods = getX11Mods(stroke); + sendMessage(server, XEMBED_REGISTER_ACCELERATOR, id, sym, mods); + } } void unregisterAccelerator(int id) { - sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0); + if (active) { + sendMessage(server, XEMBED_UNREGISTER_ACCELERATOR, id, 0, 0); + } } long getX11KeySym(AWTKeyStroke stroke) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java index 90eb7ff8ddc..892d7c94e99 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbeddedFramePeer.java @@ -63,7 +63,10 @@ public class XEmbeddedFramePeer extends XFramePeer { void postInit(XCreateWindowParams params) { super.postInit(params); if (embedder != null) { - embedder.install(this); + // install X11 event dispatcher + embedder.setClient(this); + // reparent to XEmbed server + embedder.install(); } else if (getParentWindowHandle() != 0) { XToolkit.awtLock(); try { @@ -77,6 +80,15 @@ public class XEmbeddedFramePeer extends XFramePeer { } } + @Override + public void dispose() { + if (embedder != null) { + // uninstall X11 event dispatcher + embedder.setClient(null); + } + super.dispose(); + } + public void updateMinimumSize() { } @@ -249,6 +261,14 @@ public class XEmbeddedFramePeer extends XFramePeer { // XEmbed. updateDropTarget(); } + void notifyStopped() { + if (embedder != null && embedder.isActive()) { + for (int i = strokes.size() - 1; i >= 0; i--) { + embedder.unregisterAccelerator(i); + } + } + } + long getFocusTargetWindow() { return getWindow(); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java index 4dae66c0183..9ec3d1c7109 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java @@ -63,6 +63,8 @@ public class XKeysym { // TODO: or not to do: add reverse lookup javakeycode2keysym, // for robot only it seems to me. After that, we can remove lookup table // from XWindow.c altogether. + // Another use for reverse lookup: query keyboard state, for some keys. + static Hashtable javaKeycode2KeysymHash = new Hashtable(); static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize()); static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize()); public static char convertKeysym( long ks, int state ) { @@ -196,6 +198,10 @@ public class XKeysym { Keysym2JavaKeycode jkc = getJavaKeycode( ev ); return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode(); } + static long javaKeycode2Keysym( int jkey ) { + Long ks = javaKeycode2KeysymHash.get( jkey ); + return (ks == null ? 0 : ks.longValue()); + } /** Return keysym derived from a keycode and modifiers. Usually an input method does this. However non-system input methods (e.g. Java IMs) do not. @@ -1583,6 +1589,14 @@ public class XKeysym { keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD)); keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN)); + + /* Reverse search of keysym by keycode. */ + + /* Add keyboard locking codes. */ + javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock); + javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock); + javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock); + javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock); }; } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XRobotPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XRobotPeer.java index 12084bf1a6a..2bfe6854f3f 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XRobotPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XRobotPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,11 +81,16 @@ class XRobotPeer implements RobotPeer { return pixelArray; } + public int getNumberOfButtons(){ + return getNumberOfButtonsImpl(); + } + private static native synchronized void setup(); private static native synchronized void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y); private static native synchronized void mousePressImpl(int buttons); private static native synchronized void mouseReleaseImpl(int buttons); + private static native synchronized int getNumberOfButtonsImpl(); private static native synchronized void mouseWheelImpl(int wheelAmt); private static native synchronized void keyPressImpl(int keycode); diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 9349ee8d1c9..c3011dfa6a2 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -27,6 +27,7 @@ package sun.awt.X11; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; +import java.awt.event.KeyEvent; import java.awt.datatransfer.Clipboard; import java.awt.dnd.DragSource; import java.awt.dnd.DragGestureListener; @@ -61,6 +62,10 @@ public final class XToolkit extends UNIXToolkit implements Runnable { private static Logger keyEventLog = Logger.getLogger("sun.awt.X11.kye.XToolkit"); private static final Logger backingStoreLog = Logger.getLogger("sun.awt.X11.backingStore.XToolkit"); + //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME. + //We use the same hardcoded constant. + private final static int AWT_MULTICLICK_DEFAULT_TIME = 500; + static final boolean PRIMARY_LOOP = false; static final boolean SECONDARY_LOOP = true; @@ -74,6 +79,25 @@ public final class XToolkit extends UNIXToolkit implements Runnable { // Dynamic Layout Resize client code setting protected static boolean dynamicLayoutSetting = false; + //Is it allowed to generate events assigned to extra mouse buttons. + //Set to true by default. + private static boolean areExtraMouseButtonsEnabled = true; + + /** + * Number of buttons. + * By default it's taken from the system. If system value does not + * fit into int type range, use our own MAX_BUTTONS_SUPPORT value. + */ + private static int numberOfButtons = 0; + + /* XFree standard mention 24 buttons as maximum: + * http://www.xfree86.org/current/mouse.4.html + * We workaround systems supporting more than 24 buttons. + * Otherwise, we have to use long type values as masks + * which leads to API change. + */ + private static int MAX_BUTTONS_SUPPORT = 24; + /** * True when the x settings have been loaded. */ @@ -273,6 +297,9 @@ public final class XToolkit extends UNIXToolkit implements Runnable { arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), XCursorFontConstants.XC_arrow); + areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); + //set system property if not yet assigned + System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); } finally { awtUnlock(); } @@ -1080,6 +1107,19 @@ public final class XToolkit extends UNIXToolkit implements Runnable { public Map mapInputMethodHighlight(InputMethodHighlight highlight) { return XInputMethod.mapInputMethodHighlight(highlight); } + @Override + public boolean getLockingKeyState(int key) { + if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || + key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { + throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); + } + awtLock(); + try { + return getModifierState( key ); + } finally { + awtUnlock(); + } + } public Clipboard getSystemClipboard() { SecurityManager security = System.getSecurityManager(); @@ -1216,7 +1256,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable { String multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(), "*", "multiClickTime"); if (multiclick_time_query != null) { awt_multiclick_time = (int)Long.parseLong(multiclick_time_query); - // awt_multiclick_time = XtGetMultiClickTime(awt_display); } else { multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(), "OpenWindows", "MultiClickTimeout"); @@ -1226,20 +1265,19 @@ public final class XToolkit extends UNIXToolkit implements Runnable { milliseconds */ awt_multiclick_time = (int)Long.parseLong(multiclick_time_query) * 100; } else { - awt_multiclick_time = 200; - // awt_multiclick_time = XtGetMultiClickTime(awt_display); + awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; } } } catch (NumberFormatException nf) { - awt_multiclick_time = 200; + awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; } catch (NullPointerException npe) { - awt_multiclick_time = 200; + awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; } } finally { awtUnlock(); } if (awt_multiclick_time == 0) { - awt_multiclick_time = 200; + awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; } } @@ -1383,10 +1421,15 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } } - private int getNumMouseButtons() { + public static int getNumMouseButtons() { awtLock(); try { - return XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), 0, 0); + if (numberOfButtons == 0) { + numberOfButtons = Math.min( + XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), 0, 0), + MAX_BUTTONS_SUPPORT); + } + return numberOfButtons; } finally { awtUnlock(); } @@ -1542,6 +1585,66 @@ public final class XToolkit extends UNIXToolkit implements Runnable { awtUnlock(); } } + static boolean getModifierState( int jkc ) { + int iKeyMask = 0; + long ks = XKeysym.javaKeycode2Keysym( jkc ); + int kc = XlibWrapper.XKeysymToKeycode(getDisplay(), ks); + if (kc == 0) { + return false; + } + awtLock(); + try { + XModifierKeymap modmap = new XModifierKeymap( + XlibWrapper.XGetModifierMapping(getDisplay())); + + int nkeys = modmap.get_max_keypermod(); + + long map_ptr = modmap.get_modifiermap(); + for( int k = 0; k < 8; k++ ) { + for (int i = 0; i < nkeys; ++i) { + int keycode = Native.getUByte(map_ptr, k * nkeys + i); + if (keycode == 0) { + continue; // ignore zero keycode + } + if (kc == keycode) { + iKeyMask = 1 << k; + break; + } + } + if( iKeyMask != 0 ) { + break; + } + } + XlibWrapper.XFreeModifiermap(modmap.pData); + if (iKeyMask == 0 ) { + return false; + } + // Now we know to which modifier is assigned the keycode + // correspondent to the keysym correspondent to the java + // keycode. We are going to check a state of this modifier. + // If a modifier is a weird one, we cannot help it. + long window = 0; + try{ + // get any application window + window = ((Long)(winMap.firstKey())).longValue(); + }catch(NoSuchElementException nex) { + // get root window + window = getDefaultRootWindow(); + } + boolean res = XlibWrapper.XQueryPointer(getDisplay(), window, + XlibWrapper.larg1, //root + XlibWrapper.larg2, //child + XlibWrapper.larg3, //root_x + XlibWrapper.larg4, //root_y + XlibWrapper.larg5, //child_x + XlibWrapper.larg6, //child_y + XlibWrapper.larg7);//mask + int mask = Native.getInt(XlibWrapper.larg7); + return ((mask & iKeyMask) != 0); + } finally { + awtUnlock(); + } + } /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5. * Only consider primary symbols on keycodes attached to modifiers. @@ -2166,4 +2269,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } public static native void setNoisyXErrorHandler(); + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return areExtraMouseButtonsEnabled; + } } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java index 2c894ce1b20..5601273d879 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java @@ -553,6 +553,10 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { } static int getModifiers(int state, int button, int keyCode) { + return getModifiers(state, button, keyCode, 0, false); + } + + static int getModifiers(int state, int button, int keyCode, int type, boolean wheel_mouse) { int modifiers = 0; if (((state & XConstants.ShiftMask) != 0) ^ (keyCode == KeyEvent.VK_SHIFT)) { @@ -570,14 +574,23 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { if (((state & XToolkit.modeSwitchMask) != 0) ^ (keyCode == KeyEvent.VK_ALT_GRAPH)) { modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; } - if (((state & XConstants.Button1Mask) != 0) ^ (button == MouseEvent.BUTTON1)) { - modifiers |= InputEvent.BUTTON1_DOWN_MASK; - } - if (((state & XConstants.Button2Mask) != 0) ^ (button == MouseEvent.BUTTON2)) { - modifiers |= InputEvent.BUTTON2_DOWN_MASK; - } - if (((state & XConstants.Button3Mask) != 0) ^ (button == MouseEvent.BUTTON3)) { - modifiers |= InputEvent.BUTTON3_DOWN_MASK; + //InputEvent.BUTTON_DOWN_MASK array is starting from BUTTON1_DOWN_MASK on index == 0. + // button currently reflects a real button number and starts from 1. (except NOBUTTON which is zero ) + + /* this is an attempt to refactor button IDs in : MouseEvent, InputEvent, XlibWrapper and XWindow.*/ + + //reflects a button number similar to MouseEvent.BUTTON1, 2, 3 etc. + for (int i = 0; i < XConstants.buttonsMask.length; i ++){ + //modifier should be added if : + // 1) current button is now still in PRESSED state (means that user just pressed mouse but not released yet) or + // 2) if Xsystem reports that "state" represents that button was just released. This only happens on RELEASE with 1,2,3 buttons. + // ONLY one of these conditions should be TRUE to add that modifier. + if (((state & XConstants.buttonsMask[i]) != 0) != (button == XConstants.buttons[i])){ + //exclude wheel buttons from adding their numbers as modifiers + if (!wheel_mouse) { + modifiers |= InputEvent.getMaskForButton(i+1); + } + } } return modifiers; } @@ -603,17 +616,6 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { return res; } - private static int getButtonMask(long mouseButton) { - if (mouseButton == XConstants.Button1) { - return XConstants.Button1Mask; - } else if (mouseButton == XConstants.Button2) { - return XConstants.Button2Mask; - } else if (mouseButton == XConstants.Button3) { - return XConstants.Button3Mask; - } - return 0; - } - /** * Returns true if this event is disabled and shouldn't be passed to Java. * Default implementation returns false for all events. @@ -648,7 +650,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { boolean popupTrigger = false; int button=0; boolean wheel_mouse = false; - long lbutton = xbe.get_button(); + int lbutton = xbe.get_button(); int type = xev.get_type(); when = xbe.get_time(); long jWhen = XToolkit.nowMillisUTC_offset(when); @@ -663,7 +665,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { if (type == XConstants.ButtonPress) { //Allow this mouse button to generate CLICK event on next ButtonRelease - mouseButtonClickAllowed |= getButtonMask(lbutton); + mouseButtonClickAllowed |= XConstants.buttonsMask[lbutton]; XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null); /* multiclick checking @@ -693,21 +695,22 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { } } - if (lbutton == XConstants.Button1) - button = MouseEvent.BUTTON1; - else if (lbutton == XConstants.Button2 ) - button = MouseEvent.BUTTON2; - else if (lbutton == XConstants.Button3) - button = MouseEvent.BUTTON3; - else if (lbutton == XConstants.Button4) { - button = 4; - wheel_mouse = true; - } else if (lbutton == XConstants.Button5) { - button = 5; + button = XConstants.buttons[lbutton - 1]; + // 4 and 5 buttons are usually considered assigned to a first wheel + if (lbutton == XConstants.buttons[3] || + lbutton == XConstants.buttons[4]) { wheel_mouse = true; } - modifiers = getModifiers(xbe.get_state(),button,0); + // mapping extra buttons to numbers starting from 4. + if ((button > XConstants.buttons[4]) && (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled())){ + return; + } + + if (button > XConstants.buttons[4]){ + button -= 2; + } + modifiers = getModifiers(xbe.get_state(),button,0, type, wheel_mouse); if (!wheel_mouse) { MouseEvent me = new MouseEvent((Component)getEventSource(), @@ -720,7 +723,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { postEventToEventQueue(me); if ((type == XConstants.ButtonRelease) && - ((mouseButtonClickAllowed & getButtonMask(lbutton)) != 0) ) // No up-button in the drag-state + ((mouseButtonClickAllowed & XConstants.buttonsMask[lbutton]) != 0) ) // No up-button in the drag-state { postEventToEventQueue(me = new MouseEvent((Component)getEventSource(), MouseEvent.MOUSE_CLICKED, @@ -750,7 +753,7 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { /* Update the state variable AFTER the CLICKED event post. */ if (type == XConstants.ButtonRelease) { /* Exclude this mouse button from allowed list.*/ - mouseButtonClickAllowed &= ~getButtonMask(lbutton); + mouseButtonClickAllowed &= ~XConstants.buttonsMask[lbutton]; } } @@ -761,7 +764,19 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { return; } - int mouseKeyState = (xme.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask | XConstants.Button3Mask)); + int mouseKeyState = 0; //(xme.get_state() & (XConstants.buttonsMask[0] | XConstants.buttonsMask[1] | XConstants.buttonsMask[2])); + + //this doesn't work for extra buttons because Xsystem is sending state==0 for every extra button event. + // we can't correct it in MouseEvent class as we done it with modifiers, because exact type (DRAG|MOVE) + // should be passed from XWindow. + //TODO: eliminate it with some other value obtained w/o AWTLock. + for (int i = 0; i < XToolkit.getNumMouseButtons(); i++){ + // TODO : here is the bug in WM: extra buttons doesn't have state!=0 as they should. + if ((i != 4) && (i != 5)) { + mouseKeyState = mouseKeyState | (xme.get_state() & XConstants.buttonsMask[i]); + } + } + boolean isDragging = (mouseKeyState != 0); int mouseEventType = 0; diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java index 77b39c13d90..5666cab8cda 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java @@ -1936,7 +1936,13 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, new Object[] {xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root())}); } if (isGrabbed()) { - boolean dragging = (xme.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask | XConstants.Button3Mask)) != 0; + boolean dragging = false; + for (int i = 0; i uppercaseHash = new Hashtable javaKeycode2KeysymHash = new Hashtable(); tojava static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize()); tojava static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize()); tojava public static char convertKeysym( long ks, int state ) { @@ -234,6 +236,10 @@ tojava static int getJavaKeycodeOnly( XKeyEvent ev ) { tojava Keysym2JavaKeycode jkc = getJavaKeycode( ev ); tojava return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode(); tojava } +tojava static long javaKeycode2Keysym( int jkey ) { +tojava Long ks = javaKeycode2KeysymHash.get( jkey ); +tojava return (ks == null ? 0 : ks.longValue()); +tojava } tojava /** tojava Return keysym derived from a keycode and modifiers. tojava Usually an input method does this. However non-system input methods (e.g. Java IMs) do not. @@ -2634,6 +2640,14 @@ tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mu tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD)); tojava tojava keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN)); +tojava +tojava /* Reverse search of keysym by keycode. */ +tojava +tojava /* Add keyboard locking codes. */ +tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock); +tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock); +tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock); +tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock); tojava }; tojava tojava } diff --git a/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java b/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java index 8ac3e1e8d4f..9d0a1d1d7d3 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java +++ b/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,11 +56,11 @@ class DatagramDispatcher extends NativeDispatcher } void close(FileDescriptor fd) throws IOException { - FileDispatcher.close0(fd); + FileDispatcherImpl.close0(fd); } void preClose(FileDescriptor fd) throws IOException { - FileDispatcher.preClose0(fd); + FileDispatcherImpl.preClose0(fd); } static native int read0(FileDescriptor fd, long address, int len) diff --git a/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java new file mode 100644 index 00000000000..949c817ff1e --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; + +/** + * Creates this platform's default asynchronous channel provider + */ + +public class DefaultAsynchronousChannelProvider { + + /** + * Prevent instantiation. + */ + private DefaultAsynchronousChannelProvider() { } + + /** + * Returns the default AsynchronousChannelProvider. + */ + public static AsynchronousChannelProvider create() { + String osname = AccessController + .doPrivileged(new GetPropertyAction("os.name")); + if (osname.equals("SunOS")) + return new SolarisAsynchronousChannelProvider(); + if (osname.equals("Linux")) + return new LinuxAsynchronousChannelProvider(); + throw new InternalError("platform not recognized"); + } + +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java index 7317a8eab1c..f569c2dbe09 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java +++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,7 +172,7 @@ class DevPollArrayWrapper { } void closeDevPollFD() throws IOException { - FileDispatcher.closeIntFD(wfd); + FileDispatcherImpl.closeIntFD(wfd); pollArray.free(); } diff --git a/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java b/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java index cdf19cda207..f3f26e48e7f 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,8 +139,8 @@ class DevPollSelectorImpl interruptTriggered = true; } - FileDispatcher.closeIntFD(fd0); - FileDispatcher.closeIntFD(fd1); + FileDispatcherImpl.closeIntFD(fd0); + FileDispatcherImpl.closeIntFD(fd1); pollWrapper.release(fd0); pollWrapper.closeDevPollFD(); diff --git a/jdk/src/solaris/classes/sun/nio/ch/EPoll.java b/jdk/src/solaris/classes/sun/nio/ch/EPoll.java new file mode 100644 index 00000000000..065dced7a8a --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/EPoll.java @@ -0,0 +1,121 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.io.IOException; +import sun.misc.Unsafe; + +/** + * Provides access to the Linux epoll facility. + */ + +class EPoll { + private EPoll() { } + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + /** + * typedef union epoll_data { + * void *ptr; + * int fd; + * __uint32_t u32; + * __uint64_t u64; + * } epoll_data_t; + * + * struct epoll_event { + * __uint32_t events; + * epoll_data_t data; + * } + */ + private static final int SIZEOF_EPOLLEVENT = eventSize(); + private static final int OFFSETOF_EVENTS = eventsOffset(); + private static final int OFFSETOF_FD = dataOffset(); + + // opcodes + static final int EPOLL_CTL_ADD = 1; + static final int EPOLL_CTL_DEL = 2; + static final int EPOLL_CTL_MOD = 3; + + // flags + static final int EPOLLONESHOT = (1 << 30); + + /** + * Allocates a poll array to handle up to {@code count} events. + */ + static long allocatePollArray(int count) { + return unsafe.allocateMemory(count * SIZEOF_EPOLLEVENT); + } + + /** + * Free a poll array + */ + static void freePollArray(long address) { + unsafe.freeMemory(address); + } + + /** + * Returns event[i]; + */ + static long getEvent(long address, int i) { + return address + (SIZEOF_EPOLLEVENT*i); + } + + /** + * Returns event->data.fd + */ + static int getDescriptor(long eventAddress) { + return unsafe.getInt(eventAddress + OFFSETOF_FD); + } + + /** + * Returns event->events + */ + static int getEvents(long eventAddress) { + return unsafe.getInt(eventAddress + OFFSETOF_EVENTS); + } + + // -- Native methods -- + + private static native void init(); + + private static native int eventSize(); + + private static native int eventsOffset(); + + private static native int dataOffset(); + + static native int epollCreate() throws IOException; + + static native int epollCtl(int epfd, int opcode, int fd, int events); + + static native int epollWait(int epfd, long pollAddress, int numfds) + throws IOException; + + static { + Util.load(); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java index d8542e1b03d..362bd97089c 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java +++ b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -224,7 +224,7 @@ class EPollArrayWrapper { * Close epoll file descriptor and free poll array */ void closeEPollFD() throws IOException { - FileDispatcher.closeIntFD(epfd); + FileDispatcherImpl.closeIntFD(epfd); pollArray.free(); } diff --git a/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java b/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java new file mode 100644 index 00000000000..a79cb731841 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java @@ -0,0 +1,322 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.io.IOException; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicInteger; +import static sun.nio.ch.EPoll.*; + +/** + * AsynchronousChannelGroup implementation based on the Linux epoll facility. + */ + +final class EPollPort + extends Port +{ + // maximum number of events to poll at a time + private static final int MAX_EPOLL_EVENTS = 512; + + // errors + private static final int ENOENT = 2; + + // epoll file descriptor + private final int epfd; + + // true if epoll closed + private boolean closed; + + // socket pair used for wakeup + private final int sp[]; + + // number of wakeups pending + private final AtomicInteger wakeupCount = new AtomicInteger(); + + // address of the poll array passed to epoll_wait + private final long address; + + // encapsulates an event for a channel + static class Event { + final PollableChannel channel; + final int events; + + Event(PollableChannel channel, int events) { + this.channel = channel; + this.events = events; + } + + PollableChannel channel() { return channel; } + int events() { return events; } + } + + // queue of events for cases that a polling thread dequeues more than one + // event + private final ArrayBlockingQueue queue; + private final Event NEED_TO_POLL = new Event(null, 0); + private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0); + + EPollPort(AsynchronousChannelProvider provider, ThreadPool pool) + throws IOException + { + super(provider, pool); + + // open epoll + this.epfd = epollCreate(); + + // create socket pair for wakeup mechanism + int[] sv = new int[2]; + try { + socketpair(sv); + // register one end with epoll + epollCtl(epfd, EPOLL_CTL_ADD, sv[0], POLLIN); + } catch (IOException x) { + close0(epfd); + throw x; + } + this.sp = sv; + + // allocate the poll array + this.address = allocatePollArray(MAX_EPOLL_EVENTS); + + // create the queue and offer the special event to ensure that the first + // threads polls + this.queue = new ArrayBlockingQueue(MAX_EPOLL_EVENTS); + this.queue.offer(NEED_TO_POLL); + } + + EPollPort start() { + startThreads(new EventHandlerTask()); + return this; + } + + /** + * Release all resources + */ + private void implClose() { + synchronized (this) { + if (closed) + return; + closed = true; + } + freePollArray(address); + close0(sp[0]); + close0(sp[1]); + close0(epfd); + } + + private void wakeup() { + if (wakeupCount.incrementAndGet() == 1) { + // write byte to socketpair to force wakeup + try { + interrupt(sp[1]); + } catch (IOException x) { + throw new AssertionError(x); + } + } + } + + @Override + void executeOnHandlerTask(Runnable task) { + synchronized (this) { + if (closed) + throw new RejectedExecutionException(); + offerTask(task); + wakeup(); + } + } + + @Override + void shutdownHandlerTasks() { + /* + * If no tasks are running then just release resources; otherwise + * write to the one end of the socketpair to wakeup any polling threads. + */ + int nThreads = threadCount(); + if (nThreads == 0) { + implClose(); + } else { + // send interrupt to each thread + while (nThreads-- > 0) { + wakeup(); + } + } + } + + // invoke by clients to register a file descriptor + @Override + void startPoll(int fd, int events) { + // update events (or add to epoll on first usage) + int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT)); + if (err == ENOENT) + err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT)); + if (err != 0) + throw new AssertionError(); // should not happen + } + + /* + * Task to process events from epoll and dispatch to the channel's + * onEvent handler. + * + * Events are retreived from epoll in batch and offered to a BlockingQueue + * where they are consumed by handler threads. A special "NEED_TO_POLL" + * event is used to signal one consumer to re-poll when all events have + * been consumed. + */ + private class EventHandlerTask implements Runnable { + private Event poll() throws IOException { + try { + for (;;) { + int n = epollWait(epfd, address, MAX_EPOLL_EVENTS); + /* + * 'n' events have been read. Here we map them to their + * corresponding channel in batch and queue n-1 so that + * they can be handled by other handler threads. The last + * event is handled by this thread (and so is not queued). + */ + fdToChannelLock.readLock().lock(); + try { + while (n-- > 0) { + long eventAddress = getEvent(address, n); + int fd = getDescriptor(eventAddress); + + // wakeup + if (fd == sp[0]) { + if (wakeupCount.decrementAndGet() == 0) { + // no more wakeups so drain pipe + drain1(sp[0]); + } + + // queue special event if there are more events + // to handle. + if (n > 0) { + queue.offer(EXECUTE_TASK_OR_SHUTDOWN); + continue; + } + return EXECUTE_TASK_OR_SHUTDOWN; + } + + PollableChannel channel = fdToChannel.get(fd); + if (channel != null) { + int events = getEvents(eventAddress); + Event ev = new Event(channel, events); + + // n-1 events are queued; This thread handles + // the last one except for the wakeup + if (n > 0) { + queue.offer(ev); + } else { + return ev; + } + } + } + } finally { + fdToChannelLock.readLock().unlock(); + } + } + } finally { + // to ensure that some thread will poll when all events have + // been consumed + queue.offer(NEED_TO_POLL); + } + } + + public void run() { + Invoker.GroupAndInvokeCount myGroupAndInvokeCount = + Invoker.getGroupAndInvokeCount(); + boolean replaceMe = false; + Event ev; + try { + for (;;) { + // reset invoke count + if (myGroupAndInvokeCount != null) + myGroupAndInvokeCount.resetInvokeCount(); + + try { + replaceMe = false; + ev = queue.take(); + + // no events and this thread has been "selected" to + // poll for more. + if (ev == NEED_TO_POLL) { + try { + ev = poll(); + } catch (IOException x) { + x.printStackTrace(); + return; + } + } + } catch (InterruptedException x) { + continue; + } + + // handle wakeup to execute task or shutdown + if (ev == EXECUTE_TASK_OR_SHUTDOWN) { + Runnable task = pollTask(); + if (task == null) { + // shutdown request + return; + } + // run task (may throw error/exception) + replaceMe = true; + task.run(); + continue; + } + + // process event + try { + ev.channel().onEvent(ev.events()); + } catch (Error x) { + replaceMe = true; throw x; + } catch (RuntimeException x) { + replaceMe = true; throw x; + } + } + } finally { + // last handler to exit when shutdown releases resources + int remaining = threadExit(this, replaceMe); + if (remaining == 0 && isShutdown()) { + implClose(); + } + } + } + } + + // -- Native methods -- + + private static native void socketpair(int[] sv) throws IOException; + + private static native void interrupt(int fd) throws IOException; + + private static native void drain1(int fd) throws IOException; + + private static native void close0(int fd); + + static { + Util.load(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java b/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java index 5dc17bb014c..a9bf82353f6 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,8 +136,8 @@ class EPollSelectorImpl interruptTriggered = true; } - FileDispatcher.closeIntFD(fd0); - FileDispatcher.closeIntFD(fd1); + FileDispatcherImpl.closeIntFD(fd0); + FileDispatcherImpl.closeIntFD(fd1); pollWrapper.release(fd0); pollWrapper.closeEPollFD(); diff --git a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java similarity index 72% rename from jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java rename to jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java index 335ac49b951..34d3451bb20 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcher.java +++ b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,7 @@ package sun.nio.ch; import java.io.*; -/** - * Allows different platforms to call different native methods - * for read and write operations. - */ - -class FileDispatcher extends NativeDispatcher +class FileDispatcherImpl extends FileDispatcher { static { @@ -69,6 +64,28 @@ class FileDispatcher extends NativeDispatcher return writev0(fd, address, len); } + int force(FileDescriptor fd, boolean metaData) throws IOException { + return force0(fd, metaData); + } + + int truncate(FileDescriptor fd, long size) throws IOException { + return truncate0(fd, size); + } + + long size(FileDescriptor fd) throws IOException { + return size0(fd); + } + + int lock(FileDescriptor fd, boolean blocking, long pos, long size, + boolean shared) throws IOException + { + return lock0(fd, blocking, pos, size, shared); + } + + void release(FileDescriptor fd, long pos, long size) throws IOException { + release0(fd, pos, size); + } + void close(FileDescriptor fd) throws IOException { close0(fd); } @@ -97,6 +114,20 @@ class FileDispatcher extends NativeDispatcher static native long writev0(FileDescriptor fd, long address, int len) throws IOException; + static native int force0(FileDescriptor fd, boolean metaData) + throws IOException; + + static native int truncate0(FileDescriptor fd, long size) + throws IOException; + + static native long size0(FileDescriptor fd) throws IOException; + + static native int lock0(FileDescriptor fd, boolean blocking, long pos, + long size, boolean shared) throws IOException; + + static native void release0(FileDescriptor fd, long pos, long size) + throws IOException; + static native void close0(FileDescriptor fd) throws IOException; static native void preClose0(FileDescriptor fd) throws IOException; diff --git a/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java b/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java new file mode 100644 index 00000000000..775380e8bc6 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java @@ -0,0 +1,99 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.net.ProtocolFamily; +import java.io.IOException; + +public class LinuxAsynchronousChannelProvider + extends AsynchronousChannelProvider +{ + private static volatile EPollPort defaultPort; + + private EPollPort defaultEventPort() throws IOException { + if (defaultPort == null) { + synchronized (LinuxAsynchronousChannelProvider.class) { + if (defaultPort == null) { + defaultPort = new EPollPort(this, ThreadPool.getDefault()).start(); + } + } + } + return defaultPort; + } + + public LinuxAsynchronousChannelProvider() { + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory) + throws IOException + { + return new EPollPort(this, ThreadPool.create(nThreads, factory)).start(); + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) + throws IOException + { + return new EPollPort(this, ThreadPool.wrap(executor, initialSize)).start(); + } + + private Port toPort(AsynchronousChannelGroup group) throws IOException { + if (group == null) { + return defaultEventPort(); + } else { + if (!(group instanceof EPollPort)) + throw new IllegalChannelGroupException(); + return (Port)group; + } + } + + @Override + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new UnixAsynchronousServerSocketChannelImpl(toPort(group)); + } + + @Override + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new UnixAsynchronousSocketChannelImpl(toPort(group)); + } + + @Override + public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family, + AsynchronousChannelGroup group) + throws IOException + { + return new SimpleAsynchronousDatagramChannelImpl(family, toPort(group)); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java b/jdk/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java index ab135c9b105..05fbda57d97 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,8 +93,8 @@ class PollSelectorImpl synchronized (interruptLock) { interruptTriggered = true; } - FileDispatcher.closeIntFD(fd0); - FileDispatcher.closeIntFD(fd1); + FileDispatcherImpl.closeIntFD(fd0); + FileDispatcherImpl.closeIntFD(fd1); fd0 = -1; fd1 = -1; pollWrapper.release(0); diff --git a/jdk/src/solaris/classes/sun/nio/ch/Port.java b/jdk/src/solaris/classes/sun/nio/ch/Port.java new file mode 100644 index 00000000000..8b19637bc2a --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/Port.java @@ -0,0 +1,168 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.nio.channels.*; +import java.io.IOException; +import java.io.Closeable; +import java.io.FileDescriptor; +import java.util.Map; +import java.util.HashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Base implementation of AsynchronousChannelGroupImpl for Unix systems. + */ + +abstract class Port extends AsynchronousChannelGroupImpl { + static final short POLLIN = 0x0001; + static final short POLLOUT = 0x0004; + static final short POLLERR = 0x0008; + static final short POLLHUP = 0x0010; + + /** + * Implemented by clients registered with this port. + */ + interface PollableChannel extends Closeable { + void onEvent(int events); + } + + // maps fd to "pollable" channel + protected final ReadWriteLock fdToChannelLock = new ReentrantReadWriteLock(); + protected final Map fdToChannel = + new HashMap(); + + + Port(AsynchronousChannelProvider provider, ThreadPool pool) { + super(provider, pool); + } + + /** + * Register channel identified by its file descriptor + */ + final void register(int fd, PollableChannel ch) { + fdToChannelLock.writeLock().lock(); + try { + if (isShutdown()) + throw new ShutdownChannelGroupException(); + fdToChannel.put(Integer.valueOf(fd), ch); + } finally { + fdToChannelLock.writeLock().unlock(); + } + } + + /** + * Unregister channel identified by its file descriptor + */ + final void unregister(int fd) { + boolean checkForShutdown = false; + + fdToChannelLock.writeLock().lock(); + try { + fdToChannel.remove(Integer.valueOf(fd)); + + // last key to be removed so check if group is shutdown + if (fdToChannel.isEmpty()) + checkForShutdown = true; + + } finally { + fdToChannelLock.writeLock().unlock(); + } + + // continue shutdown + if (checkForShutdown && isShutdown()) { + try { + shutdownNow(); + } catch (IOException ignore) { } + } + } + /** + * Register file descriptor with polling mechanism for given events. + * The implementation should translate the events as required. + */ + abstract void startPoll(int fd, int events); + + @Override + final boolean isEmpty() { + fdToChannelLock.writeLock().lock(); + try { + return fdToChannel.isEmpty(); + } finally { + fdToChannelLock.writeLock().unlock(); + } + } + + @Override + final Object attachForeignChannel(final Channel channel, FileDescriptor fd) { + int fdVal = IOUtil.fdVal(fd); + register(fdVal, new PollableChannel() { + public void onEvent(int events) { } + public void close() throws IOException { + channel.close(); + } + }); + return Integer.valueOf(fdVal); + } + + @Override + final void detachForeignChannel(Object key) { + unregister((Integer)key); + } + + @Override + final void closeAllChannels() { + /** + * Close channels in batches of up to 128 channels. This allows close + * to remove the channel from the map without interference. + */ + final int MAX_BATCH_SIZE = 128; + PollableChannel channels[] = new PollableChannel[MAX_BATCH_SIZE]; + int count; + do { + // grab a batch of up to 128 channels + fdToChannelLock.writeLock().lock(); + count = 0; + try { + for (Integer fd: fdToChannel.keySet()) { + channels[count++] = fdToChannel.get(fd); + if (count >= MAX_BATCH_SIZE) + break; + } + } finally { + fdToChannelLock.writeLock().unlock(); + } + + // close them + for (int i=0; i 0); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java index bc58ba9ab3c..ced3b608e77 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ class SinkChannelImpl static { Util.load(); - nd = new FileDispatcher(); + nd = new FileDispatcherImpl(); } } diff --git a/jdk/src/solaris/classes/sun/nio/ch/SocketDispatcher.java b/jdk/src/solaris/classes/sun/nio/ch/SocketDispatcher.java index 46c8e135e02..fc884c4c9a0 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/SocketDispatcher.java +++ b/jdk/src/solaris/classes/sun/nio/ch/SocketDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,26 +36,26 @@ class SocketDispatcher extends NativeDispatcher { int read(FileDescriptor fd, long address, int len) throws IOException { - return FileDispatcher.read0(fd, address, len); + return FileDispatcherImpl.read0(fd, address, len); } long readv(FileDescriptor fd, long address, int len) throws IOException { - return FileDispatcher.readv0(fd, address, len); + return FileDispatcherImpl.readv0(fd, address, len); } int write(FileDescriptor fd, long address, int len) throws IOException { - return FileDispatcher.write0(fd, address, len); + return FileDispatcherImpl.write0(fd, address, len); } long writev(FileDescriptor fd, long address, int len) throws IOException { - return FileDispatcher.writev0(fd, address, len); + return FileDispatcherImpl.writev0(fd, address, len); } void close(FileDescriptor fd) throws IOException { - FileDispatcher.close0(fd); + FileDispatcherImpl.close0(fd); } void preClose(FileDescriptor fd) throws IOException { - FileDispatcher.preClose0(fd); + FileDispatcherImpl.preClose0(fd); } } diff --git a/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java b/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java new file mode 100644 index 00000000000..0da0935cac7 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisAsynchronousChannelProvider.java @@ -0,0 +1,102 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.net.ProtocolFamily; +import java.io.IOException; + +public class SolarisAsynchronousChannelProvider + extends AsynchronousChannelProvider +{ + private static volatile SolarisEventPort defaultEventPort; + + private SolarisEventPort defaultEventPort() throws IOException { + if (defaultEventPort == null) { + synchronized (SolarisAsynchronousChannelProvider.class) { + if (defaultEventPort == null) { + defaultEventPort = + new SolarisEventPort(this, ThreadPool.getDefault()).start(); + } + } + } + return defaultEventPort; + } + + public SolarisAsynchronousChannelProvider() { + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory) + throws IOException + { + return new SolarisEventPort(this, ThreadPool.create(nThreads, factory)).start(); + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) + throws IOException + { + return new SolarisEventPort(this, ThreadPool.wrap(executor, initialSize)).start(); + } + + private SolarisEventPort toEventPort(AsynchronousChannelGroup group) + throws IOException + { + if (group == null) { + return defaultEventPort(); + } else { + if (!(group instanceof SolarisEventPort)) + throw new IllegalChannelGroupException(); + return (SolarisEventPort)group; + } + } + + @Override + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group)); + } + + @Override + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new UnixAsynchronousSocketChannelImpl(toEventPort(group)); + } + + @Override + public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family, + AsynchronousChannelGroup group) + throws IOException + { + return new SimpleAsynchronousDatagramChannelImpl(family, toEventPort(group)); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java b/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java new file mode 100644 index 00000000000..908eecce024 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java @@ -0,0 +1,244 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.util.concurrent.RejectedExecutionException; +import java.io.IOException; +import sun.misc.Unsafe; + +/** + * AsynchronousChannelGroup implementation based on the Solaris 10 event port + * framework. + */ + +class SolarisEventPort + extends Port +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int addressSize = unsafe.addressSize(); + + private static int dependsArch(int value32, int value64) { + return (addressSize == 4) ? value32 : value64; + } + + /* + * typedef struct port_event { + * int portev_events; + * ushort_t portev_source; + * ushort_t portev_pad; + * uintptr_t portev_object; + * void *portev_user; + * } port_event_t; + */ + private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24); + private static final int OFFSETOF_EVENTS = 0; + private static final int OFFSETOF_SOURCE = 4; + private static final int OFFSETOF_OBJECT = 8; + + // port sources + private static final short PORT_SOURCE_USER = 3; + private static final short PORT_SOURCE_FD = 4; + + // file descriptor to event port. + private final int port; + + // true when port is closed + private boolean closed; + + SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool) + throws IOException + { + super(provider, pool); + + // create event port + this.port = portCreate(); + } + + SolarisEventPort start() { + startThreads(new EventHandlerTask()); + return this; + } + + // releass resources + private void implClose() { + synchronized (this) { + if (closed) + return; + closed = true; + } + portClose(port); + } + + private void wakeup() { + try { + portSend(port, 0); + } catch (IOException x) { + throw new AssertionError(x); + } + } + + @Override + void executeOnHandlerTask(Runnable task) { + synchronized (this) { + if (closed) + throw new RejectedExecutionException(); + offerTask(task); + wakeup(); + } + } + + @Override + void shutdownHandlerTasks() { + /* + * If no tasks are running then just release resources; otherwise + * write to the one end of the socketpair to wakeup any polling threads.. + */ + int nThreads = threadCount(); + if (nThreads == 0) { + implClose(); + } else { + // send user event to wakeup each thread + while (nThreads-- > 0) { + try { + portSend(port, 0); + } catch (IOException x) { + throw new AssertionError(x); + } + } + } + } + + @Override + void startPoll(int fd, int events) { + // (re-)associate file descriptor + // no need to translate events + try { + portAssociate(port, PORT_SOURCE_FD, fd, events); + } catch (IOException x) { + throw new AssertionError(); // should not happen + } + } + + /* + * Task to read a single event from the port and dispatch it to the + * channel's onEvent handler. + */ + private class EventHandlerTask implements Runnable { + public void run() { + Invoker.GroupAndInvokeCount myGroupAndInvokeCount = + Invoker.getGroupAndInvokeCount(); + boolean replaceMe = false; + long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT); + try { + for (;;) { + // reset invoke count + if (myGroupAndInvokeCount != null) + myGroupAndInvokeCount.resetInvokeCount(); + + // wait for I/O completion event + // A error here is fatal (thread will not be replaced) + replaceMe = false; + try { + portGet(port, address); + } catch (IOException x) { + x.printStackTrace(); + return; + } + + // event source + short source = unsafe.getShort(address + OFFSETOF_SOURCE); + if (source != PORT_SOURCE_FD) { + // user event is trigger to invoke task or shutdown + if (source == PORT_SOURCE_USER) { + Runnable task = pollTask(); + if (task == null) { + // shutdown request + return; + } + // run task (may throw error/exception) + replaceMe = true; + task.run(); + } + // ignore + continue; + } + + // pe->portev_object is file descriptor + int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT); + // pe->portev_events + int events = unsafe.getInt(address + OFFSETOF_EVENTS); + + // lookup channel + PollableChannel ch; + fdToChannelLock.readLock().lock(); + try { + ch = fdToChannel.get(fd); + } finally { + fdToChannelLock.readLock().unlock(); + } + + // notify channel + if (ch != null) { + replaceMe = true; + // no need to translate events + ch.onEvent(events); + } + } + } finally { + // free per-thread resources + unsafe.freeMemory(address); + // last task to exit when shutdown release resources + int remaining = threadExit(this, replaceMe); + if (remaining == 0 && isShutdown()) + implClose(); + } + } + } + + // -- Native methods -- + + private static native void init(); + + private static native int portCreate() throws IOException; + + private static native void portAssociate(int port, int source, long object, + int events) throws IOException; + + private static native void portGet(int port, long pe) throws IOException; + + private static native int portGetn(int port, long address, int max) + throws IOException; + + private static native void portSend(int port, int events) throws IOException; + + private static native void portClose(int port); + + static { + Util.load(); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java index a55543e923e..e1080c917d1 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java +++ b/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ class SourceChannelImpl static { Util.load(); - nd = new FileDispatcher(); + nd = new FileDispatcherImpl(); } } diff --git a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java new file mode 100644 index 00000000000..1a8c92352d2 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java @@ -0,0 +1,327 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.net.InetSocketAddress; +import java.util.concurrent.atomic.AtomicBoolean; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Unix implementation of AsynchronousServerSocketChannel + */ + +class UnixAsynchronousServerSocketChannelImpl + extends AsynchronousServerSocketChannelImpl + implements Port.PollableChannel +{ + private final static NativeDispatcher nd = new SocketDispatcher(); + + private final Port port; + private final int fdVal; + + // flag to indicate an accept is outstanding + private final AtomicBoolean accepting = new AtomicBoolean(); + private void enableAccept() { + accepting.set(false); + } + + // used to ensure that the context for an asynchronous accept is visible + // the pooled thread that handles the I/O event + private final Object updateLock = new Object(); + + // pending accept + private PendingFuture pendingAccept; + + // context for permission check when security manager set + private AccessControlContext acc; + + + UnixAsynchronousServerSocketChannelImpl(Port port) + throws IOException + { + super(port); + + try { + IOUtil.configureBlocking(fd, false); + } catch (IOException x) { + nd.close(fd); // prevent leak + throw x; + } + this.port = port; + this.fdVal = IOUtil.fdVal(fd); + + // add mapping from file descriptor to this channel + port.register(fdVal, this); + } + + // returns and clears the result of a pending accept + private PendingFuture grabPendingAccept() { + synchronized (updateLock) { + PendingFuture result = pendingAccept; + pendingAccept = null; + return result; + } + } + + @Override + void implClose() throws IOException { + // remove the mapping + port.unregister(fdVal); + + // close file descriptor + nd.close(fd); + + // if there is a pending accept then complete it + final PendingFuture result = + grabPendingAccept(); + if (result != null) { + // discard the stack trace as otherwise it may appear that implClose + // has thrown the exception. + AsynchronousCloseException x = new AsynchronousCloseException(); + x.setStackTrace(new StackTraceElement[0]); + result.setFailure(x); + + // invoke by submitting task rather than directly + Invoker.invokeIndirectly(result.handler(), result); + } + } + + @Override + public AsynchronousChannelGroupImpl group() { + return port; + } + + /** + * Invoked by event handling thread when listener socket is polled + */ + @Override + public void onEvent(int events) { + PendingFuture result = grabPendingAccept(); + if (result == null) + return; // may have been grabbed by asynchronous close + + // attempt to accept connection + FileDescriptor newfd = new FileDescriptor(); + InetSocketAddress[] isaa = new InetSocketAddress[1]; + boolean accepted = false; + try { + begin(); + int n = accept0(this.fd, newfd, isaa); + + // spurious wakeup, is this possible? + if (n == IOStatus.UNAVAILABLE) { + synchronized (updateLock) { + this.pendingAccept = result; + } + port.startPoll(fdVal, Port.POLLIN); + return; + } + + // connection accepted + accepted = true; + + } catch (Throwable x) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + enableAccept(); + result.setFailure(x); + } finally { + end(); + } + + // Connection accepted so finish it when not holding locks. + AsynchronousSocketChannel child = null; + if (accepted) { + try { + child = finishAccept(newfd, isaa[0], acc); + enableAccept(); + result.setResult(child); + } catch (Throwable x) { + enableAccept(); + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + result.setFailure(x); + } + } + + // if an async cancel has already cancelled the operation then + // close the new channel so as to free resources + if (child != null && result.isCancelled()) { + try { + child.close(); + } catch (IOException ignore) { } + } + + // invoke the handler + Invoker.invoke(result.handler(), result); + } + + /** + * Completes the accept by creating the AsynchronousSocketChannel for + * the given file descriptor and remote address. If this method completes + * with an IOException or SecurityException then the channel/file descriptor + * will be closed. + */ + private AsynchronousSocketChannel finishAccept(FileDescriptor newfd, + final InetSocketAddress remote, + AccessControlContext acc) + throws IOException, SecurityException + { + AsynchronousSocketChannel ch = null; + try { + ch = new UnixAsynchronousSocketChannelImpl(port, newfd, remote); + } catch (IOException x) { + nd.close(newfd); + throw x; + } + + // permission check must always be in initiator's context + try { + if (acc != null) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkAccept(remote.getAddress().getHostAddress(), + remote.getPort()); + } + return null; + } + }, acc); + } else { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkAccept(remote.getAddress().getHostAddress(), + remote.getPort()); + } + } + } catch (SecurityException x) { + try { + ch.close(); + } catch (IOException ignore) { } + throw x; + } + return ch; + } + + @Override + @SuppressWarnings("unchecked") + public Future accept(A attachment, + final CompletionHandler handler) + { + // complete immediately if channel is closed + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invokeIndirectly(handler, result); + return result; + } + if (localAddress == null) + throw new NotYetBoundException(); + + // cancel was invoked with pending accept so connection may have been + // dropped. + if (isAcceptKilled()) + throw new RuntimeException("Accept not allowed due cancellation"); + + // check and set flag to prevent concurrent accepting + if (!accepting.compareAndSet(false, true)) + throw new AcceptPendingException(); + + // attempt accept + AbstractFuture result = null; + FileDescriptor newfd = new FileDescriptor(); + InetSocketAddress[] isaa = new InetSocketAddress[1]; + try { + begin(); + + int n = accept0(this.fd, newfd, isaa); + if (n == IOStatus.UNAVAILABLE) { + // no connection to accept + result = new PendingFuture(this, handler, attachment); + + // need calling context when there is security manager as + // permission check may be done in a different thread without + // any application call frames on the stack + synchronized (this) { + this.acc = (System.getSecurityManager() == null) ? + null : AccessController.getContext(); + this.pendingAccept = + (PendingFuture)result; + } + + // register for connections + port.startPoll(fdVal, Port.POLLIN); + return result; + } + } catch (Throwable x) { + // accept failed + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result = CompletedFuture.withFailure(this, x, attachment); + } finally { + end(); + } + + // connection accepted immediately + if (result == null) { + try { + AsynchronousSocketChannel ch = finishAccept(newfd, isaa[0], null); + result = CompletedFuture.withResult(this, ch, attachment); + } catch (Throwable x) { + result = CompletedFuture.withFailure(this, x, attachment); + } + } + + // re-enable accepting and invoke handler + enableAccept(); + Invoker.invokeIndirectly(handler, result); + return result; + } + + // -- Native methods -- + + private static native void initIDs(); + + // Accepts a new connection, setting the given file descriptor to refer to + // the new socket and setting isaa[0] to the socket's remote address. + // Returns 1 on success, or IOStatus.UNAVAILABLE. + // + private native int accept0(FileDescriptor ssfd, FileDescriptor newfd, + InetSocketAddress[] isaa) + throws IOException; + + static { + Util.load(); + initIDs(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java new file mode 100644 index 00000000000..702b28cbbeb --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -0,0 +1,673 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA conne02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.net.*; +import java.util.concurrent.*; +import java.io.IOException; +import java.io.FileDescriptor; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; + +/** + * Unix implementation of AsynchronousSocketChannel + */ + +class UnixAsynchronousSocketChannelImpl + extends AsynchronousSocketChannelImpl implements Port.PollableChannel +{ + private final static NativeDispatcher nd = new SocketDispatcher(); + private static enum OpType { CONNECT, READ, WRITE }; + + private static final boolean disableSynchronousRead; + static { + String propValue = AccessController.doPrivileged( + new GetPropertyAction("sun.nio.ch.disableSynchronousRead", "false")); + disableSynchronousRead = (propValue.length() == 0) ? + true : Boolean.valueOf(propValue); + } + + private final Port port; + private final int fdVal; + + // used to ensure that the context for I/O operations that complete + // ascynrhonously is visible to the pooled threads handling I/O events. + private final Object updateLock = new Object(); + + // pending connect (updateLock) + private PendingFuture pendingConnect; + + // pending remote address (statLock) + private SocketAddress pendingRemote; + + // pending read (updateLock) + private ByteBuffer[] readBuffers; + private boolean scatteringRead; + private PendingFuture pendingRead; + + // pending write (updateLock) + private ByteBuffer[] writeBuffers; + private boolean gatheringWrite; + private PendingFuture pendingWrite; + + + UnixAsynchronousSocketChannelImpl(Port port) + throws IOException + { + super(port); + + // set non-blocking + try { + IOUtil.configureBlocking(fd, false); + } catch (IOException x) { + nd.close(fd); + throw x; + } + + this.port = port; + this.fdVal = IOUtil.fdVal(fd); + + // add mapping from file descriptor to this channel + port.register(fdVal, this); + } + + // Constructor for sockets created by UnixAsynchronousServerSocketChannelImpl + UnixAsynchronousSocketChannelImpl(Port port, + FileDescriptor fd, + InetSocketAddress remote) + throws IOException + { + super(port, fd, remote); + + this.fdVal = IOUtil.fdVal(fd); + IOUtil.configureBlocking(fd, false); + + try { + port.register(fdVal, this); + } catch (ShutdownChannelGroupException x) { + // ShutdownChannelGroupException thrown if we attempt to register a + // new channel after the group is shutdown + throw new IOException(x); + } + + this.port = port; + } + + @Override + public AsynchronousChannelGroupImpl group() { + return port; + } + + // register for events if there are outstanding I/O operations + private void updateEvents() { + assert Thread.holdsLock(updateLock); + int events = 0; + if (pendingRead != null) + events |= Port.POLLIN; + if (pendingConnect != null || pendingWrite != null) + events |= Port.POLLOUT; + if (events != 0) + port.startPoll(fdVal, events); + } + + /** + * Invoked by event handler thread when file descriptor is polled + */ + @Override + public void onEvent(int events) { + boolean readable = (events & Port.POLLIN) > 0; + boolean writable = (events & Port.POLLOUT) > 0; + if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) { + readable = true; + writable = true; + } + + PendingFuture connectResult = null; + PendingFuture readResult = null; + PendingFuture writeResult = null; + + // map event to pending result + synchronized (updateLock) { + if (readable && (pendingRead != null)) { + readResult = pendingRead; + pendingRead = null; + } + if (writable) { + if (pendingWrite != null) { + writeResult = pendingWrite; + pendingWrite = null; + } else if (pendingConnect != null) { + connectResult = pendingConnect; + pendingConnect = null; + } + } + } + + // complete the I/O operation. Special case for when channel is + // ready for both reading and writing. In that case, submit task to + // complete write if write operation has a completion handler. + if (readResult != null) { + if (writeResult != null) + finishWrite(writeResult, false); + finishRead(readResult, true); + return; + } + if (writeResult != null) { + finishWrite(writeResult, true); + } + if (connectResult != null) { + finishConnect(connectResult, true); + } + } + + // returns and clears the result of a pending read + PendingFuture grabPendingRead() { + synchronized (updateLock) { + PendingFuture result = pendingRead; + pendingRead = null; + return result; + } + } + + // returns and clears the result of a pending write + PendingFuture grabPendingWrite() { + synchronized (updateLock) { + PendingFuture result = pendingWrite; + pendingWrite = null; + return result; + } + } + + @Override + void implClose() throws IOException { + // remove the mapping + port.unregister(fdVal); + + // close file descriptor + nd.close(fd); + + // All outstanding I/O operations are required to fail + final PendingFuture readyToConnect; + final PendingFuture readyToRead; + final PendingFuture readyToWrite; + synchronized (updateLock) { + readyToConnect = pendingConnect; + pendingConnect = null; + readyToRead = pendingRead; + pendingRead = null; + readyToWrite = pendingWrite; + pendingWrite = null; + } + if (readyToConnect != null) { + finishConnect(readyToConnect, false); + } + if (readyToRead != null) { + finishRead(readyToRead, false); + } + if (readyToWrite != null) { + finishWrite(readyToWrite, false); + } + } + + @Override + public void onCancel(PendingFuture task) { + if (task.getContext() == OpType.CONNECT) + killConnect(); + if (task.getContext() == OpType.READ) + killConnect(); + if (task.getContext() == OpType.WRITE) + killConnect(); + } + + // -- connect -- + + private void setConnected() throws IOException { + synchronized (stateLock) { + state = ST_CONNECTED; + localAddress = Net.localAddress(fd); + remoteAddress = pendingRemote; + } + } + + private void finishConnect(PendingFuture result, + boolean invokeDirect) + { + Throwable e = null; + try { + begin(); + checkConnect(fdVal); + setConnected(); + result.setResult(null); + } catch (Throwable x) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + e = x; + } finally { + end(); + } + if (e != null) { + // close channel if connection cannot be established + try { + close(); + } catch (IOException ignore) { } + result.setFailure(e); + } + if (invokeDirect) { + Invoker.invoke(result.handler(), result); + } else { + Invoker.invokeIndirectly(result.handler(), result); + } + } + + @Override + @SuppressWarnings("unchecked") + public Future connect(SocketAddress remote, + A attachment, + CompletionHandler handler) + { + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + InetSocketAddress isa = Net.checkAddress(remote); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); + + // check and set state + synchronized (stateLock) { + if (state == ST_CONNECTED) + throw new AlreadyConnectedException(); + if (state == ST_PENDING) + throw new ConnectionPendingException(); + state = ST_PENDING; + pendingRemote = remote; + } + + AbstractFuture result = null; + Throwable e = null; + try { + begin(); + int n = Net.connect(fd, isa.getAddress(), isa.getPort()); + if (n == IOStatus.UNAVAILABLE) { + // connection could not be established immediately + result = new PendingFuture(this, handler, attachment, OpType.CONNECT); + synchronized (updateLock) { + this.pendingConnect = (PendingFuture)result; + updateEvents(); + } + return result; + } + setConnected(); + result = CompletedFuture.withResult(this, null, attachment); + } catch (Throwable x) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + e = x; + } finally { + end(); + } + + // close channel if connect fails + if (e != null) { + try { + close(); + } catch (IOException ignore) { } + result = CompletedFuture.withFailure(this, e, attachment); + } + + Invoker.invoke(handler, result); + return result; + } + + // -- read -- + + @SuppressWarnings("unchecked") + private void finishRead(PendingFuture result, + boolean invokeDirect) + { + int n = -1; + PendingFuture pending = null; + try { + begin(); + + ByteBuffer[] dsts = readBuffers; + if (dsts.length == 1) { + n = IOUtil.read(fd, dsts[0], -1, nd, null); + } else { + n = (int)IOUtil.read(fd, dsts, nd); + } + if (n == IOStatus.UNAVAILABLE) { + // spurious wakeup, is this possible? + pending = result; + return; + } + + // allow buffer(s) to be GC'ed. + readBuffers = null; + + // allow another read to be initiated + boolean wasScatteringRead = scatteringRead; + enableReading(); + + // result is Integer or Long + if (wasScatteringRead) { + result.setResult(Long.valueOf(n)); + } else { + result.setResult(Integer.valueOf(n)); + } + + } catch (Throwable x) { + enableReading(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result.setFailure(x); + } finally { + // restart poll in case of concurrent write + synchronized (updateLock) { + if (pending != null) + this.pendingRead = pending; + updateEvents(); + } + end(); + } + + if (invokeDirect) { + Invoker.invoke(result.handler(), result); + } else { + Invoker.invokeIndirectly(result.handler(), result); + } + } + + private Runnable readTimeoutTask = new Runnable() { + public void run() { + PendingFuture result = grabPendingRead(); + if (result == null) + return; // already completed + + // kill further reading before releasing waiters + enableReading(true); + + // set completed and invoke handler + result.setFailure(new InterruptedByTimeoutException()); + Invoker.invokeIndirectly(result.handler(), result); + } + }; + + /** + * Initiates a read or scattering read operation + */ + @Override + @SuppressWarnings("unchecked") + Future readImpl(ByteBuffer[] dsts, + boolean isScatteringRead, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + // A synchronous read is not attempted if disallowed by system property + // or, we are using a fixed thread pool and the completion handler may + // not be invoked directly (because the thread is not a pooled thread or + // there are too many handlers on the stack). + Invoker.GroupAndInvokeCount myGroupAndInvokeCount = null; + boolean invokeDirect = false; + boolean attemptRead = false; + if (!disableSynchronousRead) { + myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount(); + invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port); + attemptRead = (handler == null) || invokeDirect || + !port.isFixedThreadPool(); // okay to attempt read with user thread pool + } + + AbstractFuture result; + try { + begin(); + + int n; + if (attemptRead) { + if (isScatteringRead) { + n = (int)IOUtil.read(fd, dsts, nd); + } else { + n = IOUtil.read(fd, dsts[0], -1, nd, null); + } + } else { + n = IOStatus.UNAVAILABLE; + } + + if (n == IOStatus.UNAVAILABLE) { + result = new PendingFuture(this, handler, attachment, OpType.READ); + + // update evetns so that read will complete asynchronously + synchronized (updateLock) { + this.readBuffers = dsts; + this.scatteringRead = isScatteringRead; + this.pendingRead = (PendingFuture)result; + updateEvents(); + } + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = + port.schedule(readTimeoutTask, timeout, unit); + ((PendingFuture)result).setTimeoutTask(timeoutTask); + } + return result; + } + + // data available + enableReading(); + + // result type is Long or Integer + if (isScatteringRead) { + result = (CompletedFuture)CompletedFuture + .withResult(this, Long.valueOf(n), attachment); + } else { + result = (CompletedFuture)CompletedFuture + .withResult(this, Integer.valueOf(n), attachment); + } + } catch (Throwable x) { + enableReading(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result = CompletedFuture.withFailure(this, x, attachment); + } finally { + end(); + } + + if (invokeDirect) { + Invoker.invokeDirect(myGroupAndInvokeCount, handler, result); + } else { + Invoker.invokeIndirectly(handler, result); + } + return result; + } + + // -- write -- + + private void finishWrite(PendingFuture result, + boolean invokeDirect) + { + PendingFuture pending = null; + try { + begin(); + + ByteBuffer[] srcs = writeBuffers; + int n; + if (srcs.length == 1) { + n = IOUtil.write(fd, srcs[0], -1, nd, null); + } else { + n = (int)IOUtil.write(fd, srcs, nd); + } + if (n == IOStatus.UNAVAILABLE) { + // spurious wakeup, is this possible? + pending = result; + return; + } + + // allow buffer(s) to be GC'ed. + writeBuffers = null; + + // allow another write to be initiated + boolean wasGatheringWrite = gatheringWrite; + enableWriting(); + + // result is a Long or Integer + if (wasGatheringWrite) { + result.setResult(Long.valueOf(n)); + } else { + result.setResult(Integer.valueOf(n)); + } + + } catch (Throwable x) { + enableWriting(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result.setFailure(x); + } finally { + // restart poll in case of concurrent read + synchronized (this) { + if (pending != null) + this.pendingWrite = pending; + updateEvents(); + } + end(); + } + if (invokeDirect) { + Invoker.invoke(result.handler(), result); + } else { + Invoker.invokeIndirectly(result.handler(), result); + } + } + + private Runnable writeTimeoutTask = new Runnable() { + public void run() { + PendingFuture result = grabPendingWrite(); + if (result == null) + return; // already completed + + // kill further writing before releasing waiters + enableWriting(true); + + // set completed and invoke handler + result.setFailure(new InterruptedByTimeoutException()); + Invoker.invokeIndirectly(result.handler(), result); + } + }; + + /** + * Initiates a read or scattering read operation + */ + @Override + @SuppressWarnings("unchecked") + Future writeImpl(ByteBuffer[] srcs, + boolean isGatheringWrite, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + Invoker.GroupAndInvokeCount myGroupAndInvokeCount = + Invoker.getGroupAndInvokeCount(); + boolean invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port); + boolean attemptWrite = (handler == null) || invokeDirect || + !port.isFixedThreadPool(); // okay to attempt read with user thread pool + + AbstractFuture result; + try { + begin(); + + int n; + if (attemptWrite) { + if (isGatheringWrite) { + n = (int)IOUtil.write(fd, srcs, nd); + } else { + n = IOUtil.write(fd, srcs[0], -1, nd, null); + } + } else { + n = IOStatus.UNAVAILABLE; + } + + if (n == IOStatus.UNAVAILABLE) { + result = new PendingFuture(this, handler, attachment, OpType.WRITE); + + // update evetns so that read will complete asynchronously + synchronized (updateLock) { + this.writeBuffers = srcs; + this.gatheringWrite = isGatheringWrite; + this.pendingWrite = (PendingFuture)result; + updateEvents(); + } + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = + port.schedule(writeTimeoutTask, timeout, unit); + ((PendingFuture)result).setTimeoutTask(timeoutTask); + } + return result; + } + + // data available + enableWriting(); + if (isGatheringWrite) { + result = (CompletedFuture)CompletedFuture + .withResult(this, Long.valueOf(n), attachment); + } else { + result = (CompletedFuture)CompletedFuture + .withResult(this, Integer.valueOf(n), attachment); + } + } catch (Throwable x) { + enableWriting(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + result = CompletedFuture.withFailure(this, x, attachment); + } finally { + end(); + } + if (invokeDirect) { + Invoker.invokeDirect(myGroupAndInvokeCount, handler, result); + } else { + Invoker.invokeIndirectly(handler, result); + } + return result; + } + + // -- Native methods -- + + private static native void checkConnect(int fdVal) throws IOException; + + static { + Util.load(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java new file mode 100644 index 00000000000..e86ff075c4e --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java @@ -0,0 +1,73 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.spi.FileSystemProvider; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + +/** + * Creates this platform's default FileSystemProvider. + */ + +public class DefaultFileSystemProvider { + private DefaultFileSystemProvider() { } + + @SuppressWarnings("unchecked") + private static FileSystemProvider createProvider(final String cn) { + return AccessController + .doPrivileged(new PrivilegedAction() { + public FileSystemProvider run() { + Class c; + try { + c = (Class)Class.forName(cn, true, null); + } catch (ClassNotFoundException x) { + throw new AssertionError(x); + } + try { + return c.newInstance(); + } catch (IllegalAccessException x) { + throw new AssertionError(x); + } catch (InstantiationException x) { + throw new AssertionError(x); + } + }}); + } + + /** + * Returns the default FileSystemProvider. + */ + public static FileSystemProvider create() { + String osname = AccessController + .doPrivileged(new GetPropertyAction("os.name")); + if (osname.equals("SunOS")) + return createProvider("sun.nio.fs.SolarisFileSystemProvider"); + if (osname.equals("Linux")) + return createProvider("sun.nio.fs.LinuxFileSystemProvider"); + throw new AssertionError("Platform not recognized"); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java new file mode 100644 index 00000000000..22db3165d01 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/DefaultFileTypeDetector.java @@ -0,0 +1,36 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.spi.FileTypeDetector; + +public class DefaultFileTypeDetector { + private DefaultFileTypeDetector() { } + + public static FileTypeDetector create() { + return new GnomeFileTypeDetector(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java b/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java new file mode 100644 index 00000000000..bf9e87a8912 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java @@ -0,0 +1,101 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.FileRef; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * File type detector that uses the GNOME I/O library or the deprecated + * GNOME VFS to guess the MIME type of a file. + */ + +public class GnomeFileTypeDetector + extends AbstractFileTypeDetector +{ + private static final String GNOME_VFS_MIME_TYPE_UNKNOWN = + "application/octet-stream"; + + // true if GIO available + private final boolean gioAvailable; + + // true if GNOME VFS available and GIO is not available + private final boolean gnomeVfsAvailable; + + public GnomeFileTypeDetector() { + gioAvailable = initializeGio(); + if (gioAvailable) { + gnomeVfsAvailable = false; + } else { + gnomeVfsAvailable = initializeGnomeVfs(); + } + } + + @Override + public String implProbeContentType(FileRef obj) throws IOException { + if (!gioAvailable && !gnomeVfsAvailable) + return null; + if (!(obj instanceof UnixPath)) + return null; + + UnixPath path = (UnixPath)obj; + NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls()); + try { + if (gioAvailable) { + byte[] type = probeUsingGio(buffer.address()); + return (type == null) ? null : new String(type); + } else { + byte[] type = probeUsingGnomeVfs(buffer.address()); + if (type == null) + return null; + String s = new String(type); + return s.equals(GNOME_VFS_MIME_TYPE_UNKNOWN) ? null : s; + } + + } finally { + buffer.release(); + } + + } + + // GIO + private static native boolean initializeGio(); + private static native byte[] probeUsingGio(long pathAddress); + + // GNOME VFS + private static native boolean initializeGnomeVfs(); + private static native byte[] probeUsingGnomeVfs(long pathAddress); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java new file mode 100644 index 00000000000..85f83e23553 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -0,0 +1,297 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.io.IOException; +import sun.misc.Unsafe; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + +/** + * Linux implementation of DosFileAttributeView for use on file systems such + * as ext3 that have extended attributes enabled and SAMBA configured to store + * DOS attributes. + */ + +class LinuxDosFileAttributeView + extends UnixFileAttributeViews.Basic implements DosFileAttributeView +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private static final String READONLY_NAME = "readonly"; + private static final String ARCHIVE_NAME = "archive"; + private static final String SYSTEM_NAME = "system"; + private static final String HIDDEN_NAME = "hidden"; + + private static final String DOS_XATTR_NAME = "user.DOSATTRIB"; + private static final byte[] DOS_XATTR_NAME_AS_BYTES = DOS_XATTR_NAME.getBytes(); + + private static final int DOS_XATTR_READONLY = 0x01; + private static final int DOS_XATTR_HIDDEN = 0x02; + private static final int DOS_XATTR_SYSTEM = 0x04; + private static final int DOS_XATTR_ARCHIVE = 0x20; + + LinuxDosFileAttributeView(UnixPath file, boolean followLinks) { + super(file, followLinks); + } + + @Override + public String name() { + return "dos"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(READONLY_NAME)) + return readAttributes().isReadOnly(); + if (attribute.equals(ARCHIVE_NAME)) + return readAttributes().isArchive(); + if (attribute.equals(SYSTEM_NAME)) + return readAttributes().isSystem(); + if (attribute.equals(HIDDEN_NAME)) + return readAttributes().isHidden(); + return super.getAttribute(attribute); + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(READONLY_NAME)) { + setReadOnly((Boolean)value); + return; + } + if (attribute.equals(ARCHIVE_NAME)) { + setArchive((Boolean)value); + return; + } + if (attribute.equals(SYSTEM_NAME)) { + setSystem((Boolean)value); + return; + } + if (attribute.equals(HIDDEN_NAME)) { + setHidden((Boolean)value); + return; + } + super.setAttribute(attribute, value); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + DosFileAttributes attrs = readAttributes(); + addBasicAttributesToBuilder(attrs, builder); + if (builder.match(READONLY_NAME)) + builder.add(READONLY_NAME, attrs.isReadOnly()); + if (builder.match(ARCHIVE_NAME)) + builder.add(ARCHIVE_NAME, attrs.isArchive()); + if (builder.match(SYSTEM_NAME)) + builder.add(SYSTEM_NAME, attrs.isSystem()); + if (builder.match(HIDDEN_NAME)) + builder.add(HIDDEN_NAME, attrs.isHidden()); + return builder.unmodifiableMap(); + } + + @Override + public DosFileAttributes readAttributes() throws IOException { + file.checkRead(); + + int fd = file.openForAttributeAccess(followLinks); + try { + final UnixFileAttributes attrs = UnixFileAttributes.get(fd); + final int dosAttribute = getDosAttribute(fd); + + return new DosFileAttributes() { + @Override + public long lastModifiedTime() { + return attrs.lastModifiedTime(); + } + @Override + public long lastAccessTime() { + return attrs.lastAccessTime(); + } + @Override + public long creationTime() { + return attrs.creationTime(); + } + @Override + public TimeUnit resolution() { + return attrs.resolution(); + } + @Override + public boolean isRegularFile() { + return attrs.isRegularFile(); + } + @Override + public boolean isDirectory() { + return attrs.isDirectory(); + } + @Override + public boolean isSymbolicLink() { + return attrs.isSymbolicLink(); + } + @Override + public boolean isOther() { + return attrs.isOther(); + } + @Override + public long size() { + return attrs.size(); + } + @Override + public int linkCount() { + return attrs.linkCount(); + } + @Override + public Object fileKey() { + return attrs.fileKey(); + } + @Override + public boolean isReadOnly() { + return (dosAttribute & DOS_XATTR_READONLY) != 0; + } + @Override + public boolean isHidden() { + return (dosAttribute & DOS_XATTR_HIDDEN) != 0; + } + @Override + public boolean isArchive() { + return (dosAttribute & DOS_XATTR_ARCHIVE) != 0; + } + @Override + public boolean isSystem() { + return (dosAttribute & DOS_XATTR_SYSTEM) != 0; + } + }; + + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } finally { + close(fd); + } + } + + @Override + public void setReadOnly(boolean value) throws IOException { + updateDosAttribute(DOS_XATTR_READONLY, value); + } + + @Override + public void setHidden(boolean value) throws IOException { + updateDosAttribute(DOS_XATTR_HIDDEN, value); + } + + @Override + public void setArchive(boolean value) throws IOException { + updateDosAttribute(DOS_XATTR_ARCHIVE, value); + } + + @Override + public void setSystem(boolean value) throws IOException { + updateDosAttribute(DOS_XATTR_SYSTEM, value); + } + + /** + * Reads the value of the user.DOSATTRIB extended attribute + */ + private int getDosAttribute(int fd) throws UnixException { + final int size = 24; + + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + int len = LinuxNativeDispatcher + .fgetxattr(fd, DOS_XATTR_NAME_AS_BYTES, buffer.address(), size); + + if (len > 0) { + // ignore null terminator + if (unsafe.getByte(buffer.address()+len-1) == 0) + len--; + + // convert to String and parse + byte[] buf = new byte[len]; + unsafe.copyMemory(null, buffer.address(), buf, + Unsafe.ARRAY_BYTE_BASE_OFFSET, len); + String value = new String(buf); // platform encoding + + // should be something like 0x20 + if (value.length() >= 3 && value.startsWith("0x")) { + try { + return Integer.parseInt(value.substring(2), 16); + } catch (NumberFormatException x) { + // ignore + } + } + } + throw new UnixException("Value of " + DOS_XATTR_NAME + " attribute is invalid"); + } catch (UnixException x) { + // default value when attribute does not exist + if (x.errno() == ENODATA) + return 0; + throw x; + } finally { + buffer.release(); + } + } + + /** + * Updates the value of the user.DOSATTRIB extended attribute + */ + private void updateDosAttribute(int flag, boolean enable) throws IOException { + file.checkWrite(); + + int fd = file.openForAttributeAccess(followLinks); + try { + int oldValue = getDosAttribute(fd); + int newValue = oldValue; + if (enable) { + newValue |= flag; + } else { + newValue &= ~flag; + } + if (newValue != oldValue) { + byte[] value = ("0x" + Integer.toHexString(newValue)).getBytes(); + NativeBuffer buffer = NativeBuffers.asNativeBuffer(value); + try { + LinuxNativeDispatcher.fsetxattr(fd, DOS_XATTR_NAME_AS_BYTES, + buffer.address(), value.length+1); + } finally { + buffer.release(); + } + } + } catch (UnixException x) { + x.rethrowAsIOException(file); + } finally { + close(fd); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java new file mode 100644 index 00000000000..8c07ce5f66a --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java @@ -0,0 +1,152 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.util.*; +import java.io.IOException; + +/** + * Linux implementation of FileStore + */ + +class LinuxFileStore + extends UnixFileStore +{ + // used when checking if extended attributes are enabled or not + private volatile boolean xattrChecked; + private volatile boolean xattrEnabled; + + LinuxFileStore(UnixPath file) throws IOException { + super(file); + } + + LinuxFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException { + super(fs, entry); + } + + /** + * Finds, and returns, the mount entry for the file system where the file + * resides. + */ + @Override + UnixMountEntry findMountEntry() throws IOException { + UnixFileSystem fs = file().getFileSystem(); + + // step 1: get realpath + UnixPath path = null; + try { + byte[] rp = UnixNativeDispatcher.realpath(file()); + path = new UnixPath(fs, rp); + } catch (UnixException x) { + x.rethrowAsIOException(file()); + } + + // step 2: find mount point + UnixPath parent = path.getParent(); + while (parent != null) { + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(parent, true); + } catch (UnixException x) { + x.rethrowAsIOException(parent); + } + if (attrs.dev() != dev()) + break; + path = parent; + parent = parent.getParent(); + } + + // step 3: lookup mounted file systems + byte[] dir = path.asByteArray(); + for (UnixMountEntry entry: fs.getMountEntries()) { + if (Arrays.equals(dir, entry.dir())) + return entry; + } + + throw new IOException("Mount point not found in mtab"); + } + + // returns true if extended attributes enabled on file system where given + // file resides, returns false if disabled or unable to determine. + private boolean isExtendedAttributesEnabled(UnixPath path) { + try { + int fd = path.openForAttributeAccess(false); + try { + // fgetxattr returns size if called with size==0 + LinuxNativeDispatcher.fgetxattr(fd, "user.java".getBytes(), 0L, 0); + return true; + } catch (UnixException e) { + // attribute does not exist + if (e.errno() == UnixConstants.ENODATA) + return true; + } finally { + UnixNativeDispatcher.close(fd); + } + } catch (IOException ignore) { + // nothing we can do + } + return false; + } + + @Override + public boolean supportsFileAttributeView(String name) { + // support DosFileAttributeView and NamedAttributeView if extended + // attributes enabled + if (name.equals("dos") || name.equals("xattr")) { + // lookup fstypes.properties + FeatureStatus status = checkIfFeaturePresent("user_xattr"); + if (status == FeatureStatus.PRESENT) + return true; + if (status == FeatureStatus.NOT_PRESENT) + return false; + + // if file system is mounted with user_xattr option then assume + // extended attributes are enabled + if ((entry().hasOption("user_xattr"))) + return true; + + // user_xattr option not present but we special-case ext3/4 as we + // know that extended attributes are not enabled by default. + if (entry().fstype().equals("ext3") || entry().fstype().equals("ext4")) + return false; + + // not ext3/4 so probe mount point + if (!xattrChecked) { + UnixPath dir = new UnixPath(file().getFileSystem(), entry().dir()); + xattrEnabled = isExtendedAttributesEnabled(dir); + xattrChecked = true; + } + return xattrEnabled; + } + + return super.supportsFileAttributeView(name); + } + + @Override + boolean isLoopback() { + return false; + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java new file mode 100644 index 00000000000..d574c9dff09 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java @@ -0,0 +1,175 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; +import static sun.nio.fs.LinuxNativeDispatcher.*; + +/** + * Linux implementation of FileSystem + */ + +class LinuxFileSystem extends UnixFileSystem { + private final boolean hasInotify; + private final boolean hasAtSysCalls; + + LinuxFileSystem(UnixFileSystemProvider provider, String dir) { + super(provider, dir); + + // assume X.Y[-Z] format + String osversion = AccessController + .doPrivileged(new GetPropertyAction("os.version")); + String[] vers = osversion.split("\\.", 0); + assert vers.length >= 2; + + int majorVersion = Integer.parseInt(vers[0]); + int minorVersion = Integer.parseInt(vers[1]); + int microVersion = 0; + if (vers.length > 2) { + String[] microVers = vers[2].split("-", 0); + microVersion = (microVers.length > 0) ? + Integer.parseInt(microVers[0]) : 0; + } + + // inotify available since 2.6.13 + this.hasInotify = ((majorVersion > 2) || + (majorVersion == 2 && minorVersion > 6) || + ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 13))); + + // openat etc. available since 2.6.16 + this.hasAtSysCalls = ((majorVersion > 2) || + (majorVersion == 2 && minorVersion > 6) || + ((majorVersion == 2) && (minorVersion == 6) && (microVersion >= 16))); + } + + @Override + public WatchService newWatchService() + throws IOException + { + if (hasInotify) { + return new LinuxWatchService(this); + } else { + // use polling implementation on older kernels + return new PollingWatchService(); + } + } + + @Override + @SuppressWarnings("unchecked") + public V newFileAttributeView(Class view, + UnixPath file, + LinkOption... options) + { + if (view == DosFileAttributeView.class) + return (V) new LinuxDosFileAttributeView(file, followLinks(options)); + if (view == UserDefinedFileAttributeView.class) + return (V) new LinuxUserDefinedFileAttributeView(file, followLinks(options)); + return super.newFileAttributeView(view, file, options); + } + + @Override + @SuppressWarnings("unchecked") + public FileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) + { + if (name.equals("dos")) + return new LinuxDosFileAttributeView(file, followLinks(options)); + if (name.equals("xattr")) + return new LinuxUserDefinedFileAttributeView(file, followLinks(options)); + return super.newFileAttributeView(name, file, options); + } + + // lazy initialization of the list of supported attribute views + private static class SupportedFileFileAttributeViewsHolder { + static final Set supportedFileAttributeViews = + supportedFileAttributeViews(); + private static Set supportedFileAttributeViews() { + Set result = new HashSet(); + result.addAll(UnixFileSystem.standardFileAttributeViews()); + // additional Linux-specific views + result.add("dos"); + result.add("xattr"); + return Collections.unmodifiableSet(result); + } + } + + @Override + public Set supportedFileAttributeViews() { + return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews; + } + + @Override + void copyNonPosixAttributes(int ofd, int nfd) { + LinuxUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd); + } + + @Override + boolean supportsSecureDirectoryStreams() { + return hasAtSysCalls; + } + + /** + * Returns object to iterate over entries in /etc/mtab + */ + @Override + Iterable getMountEntries() { + ArrayList entries = new ArrayList(); + try { + long fp = setmntent("/etc/mtab".getBytes(), "r".getBytes()); + try { + for (;;) { + UnixMountEntry entry = new UnixMountEntry(); + int res = getextmntent(fp, entry); + if (res < 0) + break; + entries.add(entry); + } + } finally { + endmntent(fp); + } + + } catch (UnixException x) { + // nothing we can do + } + return entries; + } + + @Override + FileStore getFileStore(UnixPath path) throws IOException { + return new LinuxFileStore(path); + } + + @Override + FileStore getFileStore(UnixMountEntry entry) throws IOException { + return new LinuxFileStore(this, entry); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java new file mode 100644 index 00000000000..aa979c4759a --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Linux implementation of FileSystemProvider + */ + +public class LinuxFileSystemProvider extends UnixFileSystemProvider { + public LinuxFileSystemProvider() { + super(); + } + + @Override + LinuxFileSystem newFileSystem(String dir) { + return new LinuxFileSystem(this, dir); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java new file mode 100644 index 00000000000..65547badccb --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java @@ -0,0 +1,126 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Linux specific system calls. + */ + +class LinuxNativeDispatcher extends UnixNativeDispatcher { + private LinuxNativeDispatcher() { } + + /** + * FILE *setmntent(const char *filename, const char *type); + */ + static long setmntent(byte[] filename, byte[] type) throws UnixException { + NativeBuffer pathBuffer = NativeBuffers.asNativeBuffer(filename); + NativeBuffer typeBuffer = NativeBuffers.asNativeBuffer(type); + try { + return setmntent0(pathBuffer.address(), typeBuffer.address()); + } finally { + typeBuffer.release(); + pathBuffer.release(); + } + } + private static native long setmntent0(long pathAddress, long typeAddress) + throws UnixException; + + /** + * int endmntent(FILE* filep); + */ + static native void endmntent(long stream) throws UnixException; + + /** + * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size); + */ + static int fgetxattr(int filedes, byte[] name, long valueAddress, + int valueLen) throws UnixException + { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(name); + try { + return fgetxattr0(filedes, buffer.address(), valueAddress, valueLen); + } finally { + buffer.release(); + } + } + + private static native int fgetxattr0(int filedes, long nameAddress, + long valueAdddress, int valueLen) throws UnixException; + + /** + * fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags); + */ + static void fsetxattr(int filedes, byte[] name, long valueAddress, + int valueLen) throws UnixException + { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(name); + try { + fsetxattr0(filedes, buffer.address(), valueAddress, valueLen); + } finally { + buffer.release(); + } + } + + private static native void fsetxattr0(int filedes, long nameAddress, + long valueAdddress, int valueLen) throws UnixException; + + + /** + * fremovexattr(int filedes, const char *name); + */ + static void fremovexattr(int filedes, byte[] name) throws UnixException { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(name); + try { + fremovexattr0(filedes, buffer.address()); + } finally { + buffer.release(); + } + } + + private static native void fremovexattr0(int filedes, long nameAddress) + throws UnixException; + + /** + * size_t flistxattr(int filedes, const char *list, size_t size) + */ + static native int flistxattr(int filedes, long listAddress, int size) + throws UnixException; + + // initialize + private static native void init(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java new file mode 100644 index 00000000000..b51a9e9cb26 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java @@ -0,0 +1,350 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.ByteBuffer; +import java.io.IOException; +import java.util.*; +import sun.misc.Unsafe; + +import static sun.nio.fs.UnixConstants.*; +import static sun.nio.fs.LinuxNativeDispatcher.*; + +/** + * Linux implementation of UserDefinedFileAttributeView using extended attributes. + */ + +class LinuxUserDefinedFileAttributeView + extends AbstractUserDefinedFileAttributeView +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // namespace for extended user attributes + private static final String USER_NAMESPACE = "user."; + + // maximum bytes in extended attribute name (includes namespace) + private static final int XATTR_NAME_MAX = 255; + + private byte[] nameAsBytes(UnixPath file, String name) throws IOException { + if (name == null) + throw new NullPointerException("'name' is null"); + name = USER_NAMESPACE + name; + byte[] bytes = name.getBytes(); + if (bytes.length > XATTR_NAME_MAX) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "'" + name + "' is too big"); + } + return bytes; + } + + // Parses buffer as array of NULL-terminated C strings. + private List asList(long address, int size) { + final List list = new ArrayList(); + int start = 0; + int pos = 0; + while (pos < size) { + if (unsafe.getByte(address + pos) == 0) { + int len = pos - start; + byte[] value = new byte[len]; + unsafe.copyMemory(null, address+start, value, + Unsafe.ARRAY_BYTE_BASE_OFFSET, len); + String s = new String(value); + if (s.startsWith(USER_NAMESPACE)) { + s = s.substring(USER_NAMESPACE.length()); + list.add(s); + } + start = pos + 1; + } + pos++; + } + return list; + } + + private final UnixPath file; + private final boolean followLinks; + + LinuxUserDefinedFileAttributeView(UnixPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + @Override + public List list() throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + int fd = file.openForAttributeAccess(followLinks); + NativeBuffer buffer = null; + try { + int size = 1024; + buffer = NativeBuffers.getNativeBuffer(size); + for (;;) { + try { + int n = flistxattr(fd, buffer.address(), size); + List list = asList(buffer.address(), n); + return Collections.unmodifiableList(list); + } catch (UnixException x) { + // allocate larger buffer if required + if (x.errno() == ERANGE && size < 32*1024) { + buffer.release(); + size *= 2; + buffer = null; + buffer = NativeBuffers.getNativeBuffer(size); + continue; + } + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to get list of extended attributes: " + + x.getMessage()); + } + } + } finally { + if (buffer != null) + buffer.release(); + close(fd); + } + } + + @Override + public int size(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + int fd = file.openForAttributeAccess(followLinks); + try { + // fgetxattr returns size if called with size==0 + return fgetxattr(fd, nameAsBytes(file,name), 0L, 0); + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to get size of extended attribute '" + name + + "': " + x.getMessage()); + } finally { + close(fd); + } + } + + @Override + public int read(String name, ByteBuffer dst) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + int pos = dst.position(); + int lim = dst.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + NativeBuffer nb; + long address; + if (dst instanceof sun.nio.ch.DirectBuffer) { + nb = null; + address = ((sun.nio.ch.DirectBuffer)dst).address() + pos; + } else { + // substitute with native buffer + nb = NativeBuffers.getNativeBuffer(rem); + address = nb.address(); + } + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + int n = fgetxattr(fd, nameAsBytes(file,name), address, rem); + + // if remaining is zero then fgetxattr returns the size + if (rem == 0) { + if (n > 0) + throw new UnixException(ERANGE); + return 0; + } + + // copy from buffer into backing array if necessary + if (nb != null) { + int off = dst.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET; + unsafe.copyMemory(null, address, dst.array(), off, n); + } + dst.position(pos + n); + return n; + } catch (UnixException x) { + String msg = (x.errno() == ERANGE) ? + "Insufficient space in buffer" : x.getMessage(); + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Error reading extended attribute '" + name + "': " + msg); + } finally { + close(fd); + } + } finally { + if (nb != null) + nb.release(); + } + } + + @Override + public int write(String name, ByteBuffer src) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + int pos = src.position(); + int lim = src.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + NativeBuffer nb; + long address; + if (src instanceof sun.nio.ch.DirectBuffer) { + nb = null; + address = ((sun.nio.ch.DirectBuffer)src).address() + pos; + } else { + // substitute with native buffer + nb = NativeBuffers.getNativeBuffer(rem); + address = nb.address(); + + if (src.hasArray()) { + // copy from backing array into buffer + int off = src.arrayOffset() + pos + Unsafe.ARRAY_BYTE_BASE_OFFSET; + unsafe.copyMemory(src.array(), off, null, address, rem); + } else { + // backing array not accessible so transfer via temporary array + byte[] tmp = new byte[rem]; + src.get(tmp); + src.position(pos); // reset position as write may fail + unsafe.copyMemory(tmp, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, + address, rem); + } + } + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + fsetxattr(fd, nameAsBytes(file,name), address, rem); + src.position(pos + rem); + return rem; + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Error writing extended attribute '" + name + "': " + + x.getMessage()); + } finally { + close(fd); + } + } finally { + if (nb != null) + nb.release(); + } + } + + @Override + public void delete(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + int fd = file.openForAttributeAccess(followLinks); + try { + fremovexattr(fd, nameAsBytes(file,name)); + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to delete extended attribute '" + name + "': " + x.getMessage()); + } finally { + close(fd); + } + } + + /** + * Used by copyTo/moveTo to copy extended attributes from source to target. + * + * @param ofd + * file descriptor for source file + * @param nfd + * file descriptor for target file + */ + static void copyExtendedAttributes(int ofd, int nfd) { + NativeBuffer buffer = null; + try { + + // call flistxattr to get list of extended attributes. + int size = 1024; + buffer = NativeBuffers.getNativeBuffer(size); + for (;;) { + try { + size = flistxattr(ofd, buffer.address(), size); + break; + } catch (UnixException x) { + // allocate larger buffer if required + if (x.errno() == ERANGE && size < 32*1024) { + buffer.release(); + size *= 2; + buffer = null; + buffer = NativeBuffers.getNativeBuffer(size); + continue; + } + + // unable to get list of attributes + return; + } + } + + // parse buffer as array of NULL-terminated C strings. + long address = buffer.address(); + int start = 0; + int pos = 0; + while (pos < size) { + if (unsafe.getByte(address + pos) == 0) { + // extract attribute name and copy attribute to target. + // FIXME: We can avoid needless copying by using address+pos + // as the address of the name. + int len = pos - start; + byte[] name = new byte[len]; + unsafe.copyMemory(null, address+start, name, + Unsafe.ARRAY_BYTE_BASE_OFFSET, len); + try { + copyExtendedAttribute(ofd, name, nfd); + } catch (UnixException ignore) { + // ignore + } + start = pos + 1; + } + pos++; + } + + } finally { + if (buffer != null) + buffer.release(); + } + } + + private static void copyExtendedAttribute(int ofd, byte[] name, int nfd) + throws UnixException + { + int size = fgetxattr(ofd, name, 0L, 0); + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + long address = buffer.address(); + size = fgetxattr(ofd, name, address, size); + fsetxattr(nfd, name, address, size); + } finally { + buffer.release(); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java new file mode 100644 index 00000000000..0d4a2ffddff --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java @@ -0,0 +1,466 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; +import java.io.IOException; +import sun.misc.Unsafe; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + +/** + * Linux implementation of WatchService based on inotify. + * + * In summary a background thread polls inotify plus a socket used for the wakeup + * mechanism. Requests to add or remove a watch, or close the watch service, + * cause the thread to wakeup and process the request. Events are processed + * by the thread which causes it to signal/queue the corresponding watch keys. + */ + +class LinuxWatchService + extends AbstractWatchService +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // background thread to read change events + private final Poller poller; + + LinuxWatchService(UnixFileSystem fs) throws IOException { + // initialize inotify + int ifd = - 1; + try { + ifd = inotifyInit(); + } catch (UnixException x) { + throw new IOException(x.errorString()); + } + + // configure inotify to be non-blocking + // create socketpair used in the close mechanism + int sp[] = new int[2]; + try { + configureBlocking(ifd, false); + socketpair(sp); + configureBlocking(sp[0], false); + } catch (UnixException x) { + UnixNativeDispatcher.close(ifd); + throw new IOException(x.errorString()); + } + + this.poller = new Poller(fs, this, ifd, sp); + this.poller.start(); + } + + @Override + WatchKey register(Path dir, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + // delegate to poller + return poller.register(dir, events, modifiers); + } + + @Override + void implClose() throws IOException { + // delegate to poller + poller.close(); + } + + /** + * WatchKey implementation + */ + private static class LinuxWatchKey extends AbstractWatchKey { + // inotify descriptor + private final int ifd; + // watch descriptor + private volatile int wd; + + LinuxWatchKey(LinuxWatchService watcher, int ifd, int wd) { + super(watcher); + this.ifd = ifd; + this.wd = wd; + } + + int descriptor() { + return wd; + } + + void invalidate(boolean remove) { + if (remove) { + try { + inotifyRmWatch(ifd, wd); + } catch (UnixException x) { + // ignore + } + } + wd = -1; + } + + @Override + public boolean isValid() { + return (wd != -1); + } + + @Override + public void cancel() { + if (isValid()) { + // delegate to poller + ((LinuxWatchService)watcher()).poller.cancel(this); + } + } + } + + /** + * Background thread to read from inotify + */ + private static class Poller extends AbstractPoller { + /** + * struct inotify_event { + * int wd; + * uint32_t mask; + * uint32_t len; + * char name __flexarr; // present if len > 0 + * } act_t; + */ + private static final int SIZEOF_INOTIFY_EVENT = eventSize(); + private static final int[] offsets = eventOffsets(); + private static final int OFFSETOF_WD = offsets[0]; + private static final int OFFSETOF_MASK = offsets[1]; + private static final int OFFSETOF_LEN = offsets[3]; + private static final int OFFSETOF_NAME = offsets[4]; + + private static final int IN_MODIFY = 0x00000002; + private static final int IN_ATTRIB = 0x00000004; + private static final int IN_MOVED_FROM = 0x00000040; + private static final int IN_MOVED_TO = 0x00000080; + private static final int IN_CREATE = 0x00000100; + private static final int IN_DELETE = 0x00000200; + + private static final int IN_UNMOUNT = 0x00002000; + private static final int IN_Q_OVERFLOW = 0x00004000; + private static final int IN_IGNORED = 0x00008000; + + // sizeof buffer for when polling inotify + private static final int BUFFER_SIZE = 8192; + + private final UnixFileSystem fs; + private final LinuxWatchService watcher; + + // inotify file descriptor + private final int ifd; + // socketpair used to shutdown polling thread + private final int socketpair[]; + // maps watch descriptor to Key + private final Map wdToKey; + // address of read buffer + private final long address; + + Poller(UnixFileSystem fs, LinuxWatchService watcher, int ifd, int[] sp) { + this.fs = fs; + this.watcher = watcher; + this.ifd = ifd; + this.socketpair = sp; + this.wdToKey = new HashMap(); + this.address = unsafe.allocateMemory(BUFFER_SIZE); + } + + @Override + void wakeup() throws IOException { + // write to socketpair to wakeup polling thread + try { + write(socketpair[1], address, 1); + } catch (UnixException x) { + throw new IOException(x.errorString()); + } + } + + @Override + Object implRegister(Path obj, + Set> events, + WatchEvent.Modifier... modifiers) + { + UnixPath dir = (UnixPath)obj; + + int mask = 0; + for (WatchEvent.Kind event: events) { + if (event == StandardWatchEventKind.ENTRY_CREATE) { + mask |= IN_CREATE | IN_MOVED_TO; + continue; + } + if (event == StandardWatchEventKind.ENTRY_DELETE) { + mask |= IN_DELETE | IN_MOVED_FROM; + continue; + } + if (event == StandardWatchEventKind.ENTRY_MODIFY) { + mask |= IN_MODIFY | IN_ATTRIB; + continue; + } + } + + // no modifiers supported at this time + if (modifiers.length > 0) { + for (WatchEvent.Modifier modifier: modifiers) { + if (modifier == null) + return new NullPointerException(); + if (modifier instanceof com.sun.nio.file.SensitivityWatchEventModifier) + continue; // ignore + return new UnsupportedOperationException("Modifier not supported"); + } + } + + // check file is directory + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(dir, true); + } catch (UnixException x) { + return x.asIOException(dir); + } + if (!attrs.isDirectory()) { + return new NotDirectoryException(dir.getPathForExecptionMessage()); + } + + // register with inotify (replaces existing mask if already registered) + int wd = -1; + try { + NativeBuffer buffer = + NativeBuffers.asNativeBuffer(dir.getByteArrayForSysCalls()); + try { + wd = inotifyAddWatch(ifd, buffer.address(), mask); + } finally { + buffer.release(); + } + } catch (UnixException x) { + if (x.errno() == ENOSPC) { + return new IOException("User limit of inotify watches reached"); + } + return x.asIOException(dir); + } + + // ensure watch descriptor is in map + LinuxWatchKey key = wdToKey.get(wd); + if (key == null) { + key = new LinuxWatchKey(watcher, ifd, wd); + wdToKey.put(wd, key); + } + return key; + } + + // cancel single key + @Override + void implCancelKey(WatchKey obj) { + LinuxWatchKey key = (LinuxWatchKey)obj; + if (key.isValid()) { + wdToKey.remove(key.descriptor()); + key.invalidate(true); + } + } + + // close watch service + @Override + void implCloseAll() { + // invalidate all keys + for (Map.Entry entry: wdToKey.entrySet()) { + entry.getValue().invalidate(true); + } + wdToKey.clear(); + + // free resources + unsafe.freeMemory(address); + UnixNativeDispatcher.close(socketpair[0]); + UnixNativeDispatcher.close(socketpair[1]); + UnixNativeDispatcher.close(ifd); + } + + /** + * Poller main loop + */ + @Override + public void run() { + try { + for (;;) { + int nReady, bytesRead; + + // wait for close or inotify event + nReady = poll(ifd, socketpair[0]); + + // read from inotify + try { + bytesRead = read(ifd, address, BUFFER_SIZE); + } catch (UnixException x) { + if (x.errno() != EAGAIN) + throw x; + bytesRead = 0; + } + + // process any pending requests + if ((nReady > 1) || (nReady == 1 && bytesRead == 0)) { + try { + read(socketpair[0], address, BUFFER_SIZE); + boolean shutdown = processRequests(); + if (shutdown) + break; + } catch (UnixException x) { + if (x.errno() != UnixConstants.EAGAIN) + throw x; + } + } + + // iterate over buffer to decode events + int offset = 0; + while (offset < bytesRead) { + long event = address + offset; + int wd = unsafe.getInt(event + OFFSETOF_WD); + int mask = unsafe.getInt(event + OFFSETOF_MASK); + int len = unsafe.getInt(event + OFFSETOF_LEN); + + // file name + UnixPath name = null; + if (len > 0) { + int actual = len; + + // null-terminated and maybe additional null bytes to + // align the next event + while (actual > 0) { + long last = event + OFFSETOF_NAME + actual - 1; + if (unsafe.getByte(last) != 0) + break; + actual--; + } + if (actual > 0) { + byte[] buf = new byte[actual]; + unsafe.copyMemory(null, event + OFFSETOF_NAME, + buf, Unsafe.ARRAY_BYTE_BASE_OFFSET, actual); + name = new UnixPath(fs, buf); + } + } + + // process event + processEvent(wd, mask, name); + + offset += (SIZEOF_INOTIFY_EVENT + len); + } + } + } catch (UnixException x) { + x.printStackTrace(); + } + } + + + /** + * map inotify event to WatchEvent.Kind + */ + private WatchEvent.Kind maskToEventKind(int mask) { + if ((mask & IN_MODIFY) > 0) + return StandardWatchEventKind.ENTRY_MODIFY; + if ((mask & IN_ATTRIB) > 0) + return StandardWatchEventKind.ENTRY_MODIFY; + if ((mask & IN_CREATE) > 0) + return StandardWatchEventKind.ENTRY_CREATE; + if ((mask & IN_MOVED_TO) > 0) + return StandardWatchEventKind.ENTRY_CREATE; + if ((mask & IN_DELETE) > 0) + return StandardWatchEventKind.ENTRY_DELETE; + if ((mask & IN_MOVED_FROM) > 0) + return StandardWatchEventKind.ENTRY_DELETE; + return null; + } + + /** + * Process event from inotify + */ + private void processEvent(int wd, int mask, final UnixPath name) { + // overflow - signal all keys + if ((mask & IN_Q_OVERFLOW) > 0) { + for (Map.Entry entry: wdToKey.entrySet()) { + entry.getValue() + .signalEvent(StandardWatchEventKind.OVERFLOW, null); + } + return; + } + + // lookup wd to get key + LinuxWatchKey key = wdToKey.get(wd); + if (key == null) + return; // should not happen + + // file deleted + if ((mask & IN_IGNORED) > 0) { + wdToKey.remove(wd); + key.invalidate(false); + key.signal(); + return; + } + + // event for directory itself + if (name == null) + return; + + // map to event and queue to key + WatchEvent.Kind kind = maskToEventKind(mask); + if (kind != null) { + key.signalEvent(kind, name); + } + } + } + + // -- native methods -- + + private static native void init(); + + // sizeof inotify_event + private static native int eventSize(); + + // offsets of inotify_event + private static native int[] eventOffsets(); + + private static native int inotifyInit() throws UnixException; + + private static native int inotifyAddWatch(int fd, long pathAddress, int mask) + throws UnixException; + + private static native void inotifyRmWatch(int fd, int wd) + throws UnixException; + + private static native void configureBlocking(int fd, boolean blocking) + throws UnixException; + + private static native void socketpair(int[] sv) throws UnixException; + + private static native int poll(int fd1, int fd2) throws UnixException; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java new file mode 100644 index 00000000000..e96361e20ba --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java @@ -0,0 +1,408 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; +import sun.misc.Unsafe; + +import static sun.nio.fs.UnixConstants.*; +import static sun.nio.fs.SolarisConstants.*; +import static sun.nio.fs.SolarisNativeDispatcher.*; + + +/** + * Solaris implementation of AclFileAttributeView with native support for + * NFSv4 ACLs on ZFS. + */ + +class SolarisAclFileAttributeView + extends AbstractAclFileAttributeView +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // Maximum number of entries allowed in an ACL + private static final int MAX_ACL_ENTRIES = 1024; + + /** + * typedef struct ace { + * uid_t a_who; + * uitn32_t a_access_mark; + * uint16_t a_flags; + * uint16_t a_type; + * } act_t; + */ + private static final short SIZEOF_ACE_T = 12; + private static final short OFFSETOF_UID = 0; + private static final short OFFSETOF_MASK = 4; + private static final short OFFSETOF_FLAGS = 8; + private static final short OFFSETOF_TYPE = 10; + + private final UnixPath file; + private final boolean followLinks; + + SolarisAclFileAttributeView(UnixPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + /** + * Permission checks to access file + */ + private void checkAccess(UnixPath file, + boolean checkRead, + boolean checkWrite) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (checkRead) + file.checkRead(); + if (checkWrite) + file.checkWrite(); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + } + + /** + * Encode the ACL to the given buffer + */ + private static void encode(List acl, long address) { + long offset = address; + for (AclEntry ace: acl) { + int flags = 0; + + // map UserPrincipal to uid and flags + UserPrincipal who = ace.principal(); + if (!(who instanceof UnixUserPrincipals)) + throw new ProviderMismatchException(); + UnixUserPrincipals.User user = (UnixUserPrincipals.User)who; + int uid; + if (user.isSpecial()) { + uid = -1; + if (who.getName().equals(UnixUserPrincipals.SPECIAL_OWNER.getName())) + flags |= ACE_OWNER; + else if (who.getName().equals(UnixUserPrincipals.SPECIAL_GROUP.getName())) + flags |= ACE_GROUP; + else if (who.getName().equals(UnixUserPrincipals.SPECIAL_EVERYONE.getName())) + flags |= ACE_EVERYONE; + else + throw new AssertionError("Unable to map special identifier"); + } else { + if (user instanceof UnixUserPrincipals.Group) { + uid = user.gid(); + flags |= ACE_IDENTIFIER_GROUP; + } else { + uid = user.uid(); + } + } + + // map ACE type + int type; + switch (ace.type()) { + case ALLOW: + type = ACE_ACCESS_ALLOWED_ACE_TYPE; + break; + case DENY: + type = ACE_ACCESS_DENIED_ACE_TYPE; + break; + case AUDIT: + type = ACE_SYSTEM_AUDIT_ACE_TYPE; + break; + case ALARM: + type = ACE_SYSTEM_ALARM_ACE_TYPE; + break; + default: + throw new AssertionError("Unable to map ACE type"); + } + + // map permissions + Set aceMask = ace.permissions(); + int mask = 0; + if (aceMask.contains(AclEntryPermission.READ_DATA)) + mask |= ACE_READ_DATA; + if (aceMask.contains(AclEntryPermission.WRITE_DATA)) + mask |= ACE_WRITE_DATA; + if (aceMask.contains(AclEntryPermission.APPEND_DATA)) + mask |= ACE_APPEND_DATA; + if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS)) + mask |= ACE_READ_NAMED_ATTRS; + if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS)) + mask |= ACE_WRITE_NAMED_ATTRS; + if (aceMask.contains(AclEntryPermission.EXECUTE)) + mask |= ACE_EXECUTE; + if (aceMask.contains(AclEntryPermission.DELETE_CHILD)) + mask |= ACE_DELETE_CHILD; + if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES)) + mask |= ACE_READ_ATTRIBUTES; + if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES)) + mask |= ACE_WRITE_ATTRIBUTES; + if (aceMask.contains(AclEntryPermission.DELETE)) + mask |= ACE_DELETE; + if (aceMask.contains(AclEntryPermission.READ_ACL)) + mask |= ACE_READ_ACL; + if (aceMask.contains(AclEntryPermission.WRITE_ACL)) + mask |= ACE_WRITE_ACL; + if (aceMask.contains(AclEntryPermission.WRITE_OWNER)) + mask |= ACE_WRITE_OWNER; + if (aceMask.contains(AclEntryPermission.SYNCHRONIZE)) + mask |= ACE_SYNCHRONIZE; + + // FIXME - it would be desirable to know here if the file is a + // directory or not. Solaris returns EINVAL if an ACE has a directory + // -only flag and the file is not a directory. + Set aceFlags = ace.flags(); + if (aceFlags.contains(AclEntryFlag.FILE_INHERIT)) + flags |= ACE_FILE_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT)) + flags |= ACE_DIRECTORY_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT)) + flags |= ACE_NO_PROPAGATE_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY)) + flags |= ACE_INHERIT_ONLY_ACE; + + unsafe.putInt(offset + OFFSETOF_UID, uid); + unsafe.putInt(offset + OFFSETOF_MASK, mask); + unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags); + unsafe.putShort(offset + OFFSETOF_TYPE, (short)type); + + offset += SIZEOF_ACE_T; + } + } + + /** + * Decode the buffer, returning an ACL + */ + private static List decode(long address, int n) { + ArrayList acl = new ArrayList(n); + for (int i=0; i 0) + who = UnixUserPrincipals.SPECIAL_OWNER; + if ((flags & ACE_GROUP) > 0) + who = UnixUserPrincipals.SPECIAL_GROUP; + if ((flags & ACE_EVERYONE) > 0) + who = UnixUserPrincipals.SPECIAL_EVERYONE; + if (who == null) + throw new AssertionError("ACE who not handled"); + } else { + // can be gid + if ((flags & ACE_IDENTIFIER_GROUP) > 0) + who = UnixUserPrincipals.fromGid(uid); + else + who = UnixUserPrincipals.fromUid(uid); + } + + AclEntryType aceType = null; + switch (type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + aceType = AclEntryType.ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + aceType = AclEntryType.DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + aceType = AclEntryType.AUDIT; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + aceType = AclEntryType.ALARM; + break; + default: + assert false; + } + + HashSet aceMask = new HashSet(); + if ((mask & ACE_READ_DATA) > 0) + aceMask.add(AclEntryPermission.READ_DATA); + if ((mask & ACE_WRITE_DATA) > 0) + aceMask.add(AclEntryPermission.WRITE_DATA); + if ((mask & ACE_APPEND_DATA ) > 0) + aceMask.add(AclEntryPermission.APPEND_DATA); + if ((mask & ACE_READ_NAMED_ATTRS) > 0) + aceMask.add(AclEntryPermission.READ_NAMED_ATTRS); + if ((mask & ACE_WRITE_NAMED_ATTRS) > 0) + aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS); + if ((mask & ACE_EXECUTE) > 0) + aceMask.add(AclEntryPermission.EXECUTE); + if ((mask & ACE_DELETE_CHILD ) > 0) + aceMask.add(AclEntryPermission.DELETE_CHILD); + if ((mask & ACE_READ_ATTRIBUTES) > 0) + aceMask.add(AclEntryPermission.READ_ATTRIBUTES); + if ((mask & ACE_WRITE_ATTRIBUTES) > 0) + aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES); + if ((mask & ACE_DELETE) > 0) + aceMask.add(AclEntryPermission.DELETE); + if ((mask & ACE_READ_ACL) > 0) + aceMask.add(AclEntryPermission.READ_ACL); + if ((mask & ACE_WRITE_ACL) > 0) + aceMask.add(AclEntryPermission.WRITE_ACL); + if ((mask & ACE_WRITE_OWNER) > 0) + aceMask.add(AclEntryPermission.WRITE_OWNER); + if ((mask & ACE_SYNCHRONIZE) > 0) + aceMask.add(AclEntryPermission.SYNCHRONIZE); + + HashSet aceFlags = new HashSet(); + if ((flags & ACE_FILE_INHERIT_ACE) > 0) + aceFlags.add(AclEntryFlag.FILE_INHERIT); + if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0) + aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT); + if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0) + aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT); + if ((flags & ACE_INHERIT_ONLY_ACE ) > 0) + aceFlags.add(AclEntryFlag.INHERIT_ONLY); + + // build the ACL entry and add it to the list + AclEntry ace = AclEntry.newBuilder() + .setType(aceType) + .setPrincipal(who) + .setPermissions(aceMask).setFlags(aceFlags).build(); + acl.add(ace); + } + + return acl; + } + + // Retrns true if NFSv4 ACLs not enabled on file system + private static boolean isAclsEnabled(int fd) { + try { + long enabled = fpathconf(fd, _PC_ACL_ENABLED); + if (enabled == _ACL_ACE_ENABLED) + return true; + } catch (UnixException x) { + } + return false; + } + + @Override + public List getAcl() + throws IOException + { + // permission check + checkAccess(file, true, false); + + // open file (will fail if file is a link and not following links) + int fd = file.openForAttributeAccess(followLinks); + try { + long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES); + try { + // read ACL and decode it + int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address); + assert n >= 0; + return decode(address, n); + } catch (UnixException x) { + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, x.getMessage() + " (file system does not support NFSv4 ACLs)"); + } + x.rethrowAsIOException(file); + return null; // keep compiler happy + } finally { + unsafe.freeMemory(address); + } + } finally { + close(fd); + } + } + + @Override + public void setAcl(List acl) throws IOException { + // permission check + checkAccess(file, false, true); + + // open file (will fail if file is a link and not following links) + int fd = file.openForAttributeAccess(followLinks); + try { + // SECURITY: need to copy list as can change during processing + acl = new ArrayList(acl); + int n = acl.size(); + + long address = unsafe.allocateMemory(SIZEOF_ACE_T * n); + try { + encode(acl, address); + facl(fd, ACE_SETACL, n, address); + } catch (UnixException x) { + if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, x.getMessage() + " (file system does not support NFSv4 ACLs)"); + } + if (x.errno() == EINVAL && (n < 3)) + throw new IOException("ACL must contain at least 3 entries"); + x.rethrowAsIOException(file); + } finally { + unsafe.freeMemory(address); + } + } finally { + close(fd); + } + } + + @Override + public UserPrincipal getOwner() + throws IOException + { + checkAccess(file, true, false); + + try { + UnixFileAttributes attrs = + UnixFileAttributes.get(file, followLinks); + return UnixUserPrincipals.fromUid(attrs.uid()); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compile happy + } + } + + @Override + public void setOwner(UserPrincipal owner) throws IOException { + checkAccess(file, true, false); + + if (!(owner instanceof UnixUserPrincipals.User)) + throw new ProviderMismatchException(); + if (owner instanceof UnixUserPrincipals.Group) + throw new IOException("'owner' parameter is a group"); + int uid = ((UnixUserPrincipals.User)owner).uid(); + + try { + if (followLinks) { + lchown(file, uid, -1); + } else { + chown(file, uid, -1); + } + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java new file mode 100644 index 00000000000..bdf71a5593c --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileStore.java @@ -0,0 +1,103 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.io.IOException; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.SolarisConstants.*; + +/** + * Solaris implementation of FileStore + */ + +class SolarisFileStore + extends UnixFileStore +{ + private final boolean xattrEnabled; + + SolarisFileStore(UnixPath file) throws IOException { + super(file); + this.xattrEnabled = xattrEnabled(); + } + + SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException { + super(fs, entry); + this.xattrEnabled = xattrEnabled(); + } + + // returns true if extended attributes enabled + private boolean xattrEnabled() { + long res = 0L; + try { + res = pathconf(file(), _PC_XATTR_ENABLED); + } catch (UnixException x) { + // ignore + } + return (res != 0L); + } + + @Override + UnixMountEntry findMountEntry() throws IOException { + // On Solaris iterate over the entries in the mount table to find device + for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) { + if (entry.dev() == dev()) { + return entry; + } + } + throw new IOException("Device not found in mnttab"); + } + + @Override + public boolean supportsFileAttributeView(String name) { + if (name.equals("acl")) { + // lookup fstypes.properties + FeatureStatus status = checkIfFeaturePresent("nfsv4acl"); + if (status == FeatureStatus.PRESENT) + return true; + if (status == FeatureStatus.NOT_PRESENT) + return false; + // AclFileAttributeView available on ZFS + return (type().equals("zfs")); + } + if (name.equals("xattr")) { + // lookup fstypes.properties + FeatureStatus status = checkIfFeaturePresent("xattr"); + if (status == FeatureStatus.PRESENT) + return true; + if (status == FeatureStatus.NOT_PRESENT) + return false; + return xattrEnabled; + } + + return super.supportsFileAttributeView(name); + } + + @Override + boolean isLoopback() { + return type().equals("lofs"); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java new file mode 100644 index 00000000000..fa7f34f53b0 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java @@ -0,0 +1,164 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; +import static sun.nio.fs.UnixNativeDispatcher.*; + +/** + * Solaris implementation of FileSystem + */ + +class SolarisFileSystem extends UnixFileSystem { + private final boolean hasSolaris11Features; + + SolarisFileSystem(UnixFileSystemProvider provider, String dir) { + super(provider, dir); + + // check os.version + String osversion = AccessController + .doPrivileged(new GetPropertyAction("os.version")); + String[] vers = osversion.split("\\.", 0); + assert vers.length >= 2; + int majorVersion = Integer.parseInt(vers[0]); + int minorVersion = Integer.parseInt(vers[1]); + this.hasSolaris11Features = + (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11)); + } + + @Override + boolean isSolaris() { + return true; + } + + @Override + public WatchService newWatchService() + throws IOException + { + // FEN available since Solaris 11 + if (hasSolaris11Features) { + return new SolarisWatchService(this); + } else { + return new PollingWatchService(); + } + } + + @Override + @SuppressWarnings("unchecked") + public V newFileAttributeView(Class view, + UnixPath file, LinkOption... options) + { + if (view == AclFileAttributeView.class) + return (V) new SolarisAclFileAttributeView(file, followLinks(options)); + if (view == UserDefinedFileAttributeView.class) { + return(V) new SolarisUserDefinedFileAttributeView(file, followLinks(options)); + } + return super.newFileAttributeView(view, file, options); + } + + @Override + protected FileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) + { + if (name.equals("acl")) + return new SolarisAclFileAttributeView(file, followLinks(options)); + if (name.equals("xattr")) + return new SolarisUserDefinedFileAttributeView(file, followLinks(options)); + return super.newFileAttributeView(name, file, options); + } + + // lazy initialization of the list of supported attribute views + private static class SupportedFileFileAttributeViewsHolder { + static final Set supportedFileAttributeViews = + supportedFileAttributeViews(); + private static Set supportedFileAttributeViews() { + Set result = new HashSet(); + result.addAll(UnixFileSystem.standardFileAttributeViews()); + // additional Solaris-specific views + result.add("acl"); + result.add("xattr"); + return Collections.unmodifiableSet(result); + } + } + + @Override + public Set supportedFileAttributeViews() { + return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews; + } + + @Override + void copyNonPosixAttributes(int ofd, int nfd) { + SolarisUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd); + // TDB: copy ACL from source to target + } + + @Override + boolean supportsSecureDirectoryStreams() { + return true; + } + + /** + * Returns object to iterate over entries in /etc/mnttab + */ + @Override + Iterable getMountEntries() { + ArrayList entries = new ArrayList(); + try { + UnixPath mnttab = new UnixPath(this, "/etc/mnttab"); + long fp = fopen(mnttab, "r"); + try { + for (;;) { + UnixMountEntry entry = new UnixMountEntry(); + int res = getextmntent(fp, entry); + if (res < 0) + break; + entries.add(entry); + } + } finally { + fclose(fp); + } + } catch (UnixException x) { + // nothing we can do + } + return entries; + } + + @Override + FileStore getFileStore(UnixPath path) throws IOException { + return new SolarisFileStore(path); + } + + @Override + FileStore getFileStore(UnixMountEntry entry) throws IOException { + return new SolarisFileStore(this, entry); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java new file mode 100644 index 00000000000..9d3c0845773 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Solaris implementation of FileSystemProvider + */ + +public class SolarisFileSystemProvider extends UnixFileSystemProvider { + public SolarisFileSystemProvider() { + super(); + } + + @Override + SolarisFileSystem newFileSystem(String dir) { + return new SolarisFileSystem(this, dir); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java new file mode 100644 index 00000000000..36f2326ce76 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisNativeDispatcher.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Solaris specific system calls. + */ + +class SolarisNativeDispatcher extends UnixNativeDispatcher { + private SolarisNativeDispatcher() { } + + /** + * int facl(int filedes, int cmd, int nentries, void aclbufp) + */ + static native int facl(int fd, int cmd, int nentries, long aclbufp) + throws UnixException; + + + // initialize + private static native void init(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java new file mode 100644 index 00000000000..040628f6093 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java @@ -0,0 +1,293 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.io.IOException; +import java.util.*; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; +import static sun.nio.fs.SolarisConstants.*; + +/** + * Solaris emulation of NamedAttributeView using extended attributes. + */ + +class SolarisUserDefinedFileAttributeView + extends AbstractUserDefinedFileAttributeView +{ + private byte[] nameAsBytes(UnixPath file, String name) throws IOException { + byte[] bytes = name.getBytes(); + // "", "." and ".." not allowed + if (bytes.length == 0 || bytes[0] == '.') { + if (bytes.length <= 1 || + (bytes.length == 2 && bytes[1] == '.')) + { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "'" + name + "' is not a valid name"); + } + } + return bytes; + } + + private final UnixPath file; + private final boolean followLinks; + + SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + @Override + public List list() throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + // open extended attribute directory + int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0); + long dp; + try { + dp = fdopendir(dfd); + } catch (UnixException x) { + close(dfd); + throw x; + } + + // read list of extended attributes + final List list = new ArrayList(); + try { + byte[] name; + while ((name = readdir(dp)) != null) { + String s = new String(name); + if (!s.equals(".") && !s.equals("..")) + list.add(s); + } + } finally { + closedir(dp); + } + return Collections.unmodifiableList(list); + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to get list of extended attributes: " + + x.getMessage()); + } + } finally { + close(fd); + } + } + + @Override + public int size(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + // open attribute file + int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0); + try { + // read attribute's attributes + UnixFileAttributes attrs = UnixFileAttributes.get(afd); + long size = attrs.size(); + if (size > Integer.MAX_VALUE) + throw new ArithmeticException("Extended attribute value too large"); + return (int)size; + } finally { + close(afd); + } + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to get size of extended attribute '" + name + + "': " + x.getMessage()); + } + } finally { + close(fd); + } + } + + @Override + public int read(String name, ByteBuffer dst) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + // open attribute file + int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0); + + // wrap with channel + FileChannel fc = UnixChannelFactory.newFileChannel(afd, true, false); + + // read to EOF (nothing we can do if I/O error occurs) + try { + if (fc.size() > dst.remaining()) + throw new IOException("Extended attribute file too large"); + int total = 0; + while (dst.hasRemaining()) { + int n = fc.read(dst); + if (n < 0) + break; + total += n; + } + return total; + } finally { + fc.close(); + } + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to read extended attribute '" + name + + "': " + x.getMessage()); + } + } finally { + close(fd); + } + } + + @Override + public int write(String name, ByteBuffer src) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + int fd = file.openForAttributeAccess(followLinks); + try { + try { + // open/create attribute file + int afd = openat(fd, nameAsBytes(file,name), + (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR), + UnixFileModeAttribute.ALL_PERMISSIONS); + + // wrap with channel + FileChannel fc = UnixChannelFactory.newFileChannel(afd, false, true); + + // write value (nothing we can do if I/O error occurs) + try { + int rem = src.remaining(); + while (src.hasRemaining()) { + fc.write(src); + } + return rem; + } finally { + fc.close(); + } + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to write extended attribute '" + name + + "': " + x.getMessage()); + } + } finally { + close(fd); + } + } + + @Override + public void delete(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + int fd = file.openForAttributeAccess(followLinks); + try { + int dfd = openat(fd, ".".getBytes(), (O_RDONLY|O_XATTR), 0); + try { + unlinkat(dfd, nameAsBytes(file,name), 0); + } finally { + close(dfd); + } + } catch (UnixException x) { + throw new FileSystemException(file.getPathForExecptionMessage(), + null, "Unable to delete extended attribute '" + name + + "': " + x.getMessage()); + } finally { + close(fd); + } + } + + /** + * Used by copyTo/moveTo to copy extended attributes from source to target. + * + * @param ofd + * file descriptor for source file + * @param nfd + * file descriptor for target file + */ + static void copyExtendedAttributes(int ofd, int nfd) { + try { + // open extended attribute directory + int dfd = openat(ofd, ".".getBytes(), (O_RDONLY|O_XATTR), 0); + long dp = 0L; + try { + dp = fdopendir(dfd); + } catch (UnixException x) { + close(dfd); + throw x; + } + + // copy each extended attribute + try { + byte[] name; + while ((name = readdir(dp)) != null) { + // ignore "." and ".." + if (name[0] == '.') { + if (name.length == 1) + continue; + if (name.length == 2 && name[1] == '.') + continue; + } + copyExtendedAttribute(ofd, name, nfd); + } + } finally { + closedir(dp); + } + } catch (UnixException ignore) { + } + } + + private static void copyExtendedAttribute(int ofd, byte[] name, int nfd) + throws UnixException + { + // open source attribute file + int src = openat(ofd, name, (O_RDONLY|O_XATTR), 0); + try { + // create target attribute file + int dst = openat(nfd, name, (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR), + UnixFileModeAttribute.ALL_PERMISSIONS); + try { + UnixCopyFile.transfer(dst, src, 0L); + } finally { + close(dst); + } + } finally { + close(src); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java new file mode 100644 index 00000000000..6a11ebdd7f7 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java @@ -0,0 +1,770 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; +import java.io.IOException; +import sun.misc.Unsafe; + +import static sun.nio.fs.UnixConstants.*; + +/** + * Solaris implementation of WatchService based on file events notification + * facility. + */ + +class SolarisWatchService + extends AbstractWatchService +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static int addressSize = unsafe.addressSize(); + + private static int dependsArch(int value32, int value64) { + return (addressSize == 4) ? value32 : value64; + } + + /* + * typedef struct port_event { + * int portev_events; + * ushort_t portev_source; + * ushort_t portev_pad; + * uintptr_t portev_object; + * void *portev_user; + * } port_event_t; + */ + private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24); + private static final int OFFSETOF_EVENTS = 0; + private static final int OFFSETOF_SOURCE = 4; + private static final int OFFSETOF_OBJECT = 8; + + /* + * typedef struct file_obj { + * timestruc_t fo_atime; + * timestruc_t fo_mtime; + * timestruc_t fo_ctime; + * uintptr_t fo_pad[3]; + * char *fo_name; + * } file_obj_t; + */ + private static final int SIZEOF_FILEOBJ = dependsArch(40, 80); + private static final int OFFSET_FO_NAME = dependsArch(36, 72); + + // port sources + private static final short PORT_SOURCE_USER = 3; + private static final short PORT_SOURCE_FILE = 7; + + // user-watchable events + private static final int FILE_MODIFIED = 0x00000002; + private static final int FILE_ATTRIB = 0x00000004; + private static final int FILE_NOFOLLOW = 0x10000000; + + // exception events + private static final int FILE_DELETE = 0x00000010; + private static final int FILE_RENAME_TO = 0x00000020; + private static final int FILE_RENAME_FROM = 0x00000040; + private static final int UNMOUNTED = 0x20000000; + private static final int MOUNTEDOVER = 0x40000000; + + // background thread to read change events + private final Poller poller; + + SolarisWatchService(UnixFileSystem fs) throws IOException { + int port = -1; + try { + port = portCreate(); + } catch (UnixException x) { + throw new IOException(x.errorString()); + } + + this.poller = new Poller(fs, this, port); + this.poller.start(); + } + + @Override + WatchKey register(Path dir, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + // delegate to poller + return poller.register(dir, events, modifiers); + } + + @Override + void implClose() throws IOException { + // delegate to poller + poller.close(); + } + + /** + * WatchKey implementation + */ + private class SolarisWatchKey extends AbstractWatchKey + implements DirectoryNode + { + private final UnixPath dir; + private final UnixFileKey fileKey; + + // pointer to native file_obj object + private final long object; + + // events (may be changed). set to null when watch key is invalid + private volatile Set> events; + + // map of entries in directory; created lazily; accessed only by + // poller thread. + private Map children; + + SolarisWatchKey(SolarisWatchService watcher, + UnixPath dir, + UnixFileKey fileKey, + long object, + Set> events) + { + super(watcher); + this.dir = dir; + this.fileKey = fileKey; + this.object = object; + this.events = events; + } + + UnixPath getFileRef() { + return dir; + } + + UnixFileKey getFileKey() { + return fileKey; + } + + @Override + public long object() { + return object; + } + + void invalidate() { + events = null; + } + + Set> events() { + return events; + } + + void setEvents(Set> events) { + this.events = events; + } + + @Override + public boolean isValid() { + return events != null; + } + + @Override + public void cancel() { + if (isValid()) { + // delegate to poller + poller.cancel(this); + } + } + + @Override + public void addChild(Path name, EntryNode node) { + if (children == null) + children = new HashMap(); + children.put(name, node); + } + + @Override + public void removeChild(Path name) { + children.remove(name); + } + + @Override + public EntryNode getChild(Path name) { + if (children != null) + return children.get(name); + return null; + } + } + + /** + * Background thread to read from port + */ + private class Poller extends AbstractPoller { + + // maximum number of events to read per call to port_getn + private static final int MAX_EVENT_COUNT = 128; + + // events that map to ENTRY_DELETE + private static final int FILE_REMOVED = + (FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM); + + // events that tell us not to re-associate the object + private static final int FILE_EXCEPTION = + (FILE_REMOVED|UNMOUNTED|MOUNTEDOVER); + + // address of event buffers (used to receive events with port_getn) + private final long bufferAddress; + + private final SolarisWatchService watcher; + + // the I/O port + private final int port; + + // maps file key (dev/inode) to WatchKey + private final Map fileKey2WatchKey; + + // maps file_obj object to Node + private final Map object2Node; + + /** + * Create a new instance + */ + Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) { + this.watcher = watcher; + this.port = port; + this.bufferAddress = + unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT); + this.fileKey2WatchKey = new HashMap(); + this.object2Node = new HashMap(); + } + + @Override + void wakeup() throws IOException { + // write to port to wakeup polling thread + try { + portSend(port, 0); + } catch (UnixException x) { + throw new IOException(x.errorString()); + } + } + + @Override + Object implRegister(Path obj, + Set> events, + WatchEvent.Modifier... modifiers) + { + // no modifiers supported at this time + if (modifiers.length > 0) { + for (WatchEvent.Modifier modifier: modifiers) { + if (modifier == null) + return new NullPointerException(); + if (modifier instanceof com.sun.nio.file.SensitivityWatchEventModifier) + continue; // ignore + return new UnsupportedOperationException("Modifier not supported"); + } + } + + UnixPath dir = (UnixPath)obj; + + // check file is directory + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(dir, true); + } catch (UnixException x) { + return x.asIOException(dir); + } + if (!attrs.isDirectory()) { + return new NotDirectoryException(dir.getPathForExecptionMessage()); + } + + // return existing watch key after updating events if already + // registered + UnixFileKey fileKey = attrs.fileKey(); + SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey); + if (watchKey != null) { + updateEvents(watchKey, events); + return watchKey; + } + + // register directory + long object = 0L; + try { + object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB)); + } catch (UnixException x) { + return x.asIOException(dir); + } + + // create watch key and insert it into maps + watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events); + object2Node.put(object, watchKey); + fileKey2WatchKey.put(fileKey, watchKey); + + // register all entries in directory + registerChildren(dir, watchKey, false); + + return watchKey; + } + + // cancel single key + @Override + void implCancelKey(WatchKey obj) { + SolarisWatchKey key = (SolarisWatchKey)obj; + if (key.isValid()) { + fileKey2WatchKey.remove(key.getFileKey()); + + // release resources for entries in directory + if (key.children != null) { + for (Map.Entry entry: key.children.entrySet()) { + EntryNode node = entry.getValue(); + long object = node.object(); + object2Node.remove(object); + releaseObject(object, true); + } + } + + // release resources for directory + long object = key.object(); + object2Node.remove(object); + releaseObject(object, true); + + // and finally invalidate the key + key.invalidate(); + } + } + + // close watch service + @Override + void implCloseAll() { + // release all native resources + for (Long object: object2Node.keySet()) { + releaseObject(object, true); + } + + // invalidate all keys + for (Map.Entry entry: fileKey2WatchKey.entrySet()) { + entry.getValue().invalidate(); + } + + // clean-up + object2Node.clear(); + fileKey2WatchKey.clear(); + + // free global resources + unsafe.freeMemory(bufferAddress); + UnixNativeDispatcher.close(port); + } + + /** + * Poller main loop. Blocks on port_getn waiting for events and then + * processes them. + */ + @Override + public void run() { + try { + for (;;) { + int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT); + assert n > 0; + + long address = bufferAddress; + for (int i=0; iportev_source + short source = unsafe.getShort(address + OFFSETOF_SOURCE); + // pe->portev_object + long object = unsafe.getAddress(address + OFFSETOF_OBJECT); + // pe->portev_events + int events = unsafe.getInt(address + OFFSETOF_EVENTS); + + // user event is trigger to process pending requests + if (source != PORT_SOURCE_FILE) { + if (source == PORT_SOURCE_USER) { + // process any pending requests + boolean shutdown = processRequests(); + if (shutdown) + return true; + } + return false; + } + + // lookup object to get Node + Node node = object2Node.get(object); + if (node == null) { + // should not happen + return false; + } + + // As a workaround for 6642290 and 6636438/6636412 we don't use + // FILE_EXCEPTION events to tell use not to register the file. + // boolean reregister = (events & FILE_EXCEPTION) == 0; + boolean reregister = true; + + // If node is EntryNode then event relates to entry in directory + // If node is a SolarisWatchKey (DirectoryNode) then event relates + // to a watched directory. + boolean isDirectory = (node instanceof SolarisWatchKey); + if (isDirectory) { + processDirectoryEvents((SolarisWatchKey)node, events); + } else { + boolean ignore = processEntryEvents((EntryNode)node, events); + if (ignore) + reregister = false; + } + + // need to re-associate to get further events + if (reregister) { + try { + events = FILE_MODIFIED | FILE_ATTRIB; + if (!isDirectory) events |= FILE_NOFOLLOW; + portAssociate(port, + PORT_SOURCE_FILE, + object, + events); + } catch (UnixException x) { + // unable to re-register + reregister = false; + } + } + + // object is not re-registered so release resources. If + // object is a watched directory then signal key + if (!reregister) { + // release resources + object2Node.remove(object); + releaseObject(object, false); + + // if watch key then signal it + if (isDirectory) { + SolarisWatchKey key = (SolarisWatchKey)node; + fileKey2WatchKey.remove( key.getFileKey() ); + key.invalidate(); + key.signal(); + } else { + // if entry then remove it from parent + EntryNode entry = (EntryNode)node; + SolarisWatchKey key = (SolarisWatchKey)entry.parent(); + key.removeChild(entry.name()); + } + } + + return false; + } + + /** + * Process directory events. If directory is modified then re-scan + * directory to register any new entries + */ + void processDirectoryEvents(SolarisWatchKey key, int mask) { + if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) { + registerChildren(key.getFileRef(), key, + key.events().contains(StandardWatchEventKind.ENTRY_CREATE)); + } + } + + /** + * Process events for entries in registered directories. Returns {@code + * true} if events are ignored because the watch key has been cancelled. + */ + boolean processEntryEvents(EntryNode node, int mask) { + SolarisWatchKey key = (SolarisWatchKey)node.parent(); + Set> events = key.events(); + if (events == null) { + // key has been cancelled so ignore event + return true; + } + + // entry modified + if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) && + events.contains(StandardWatchEventKind.ENTRY_MODIFY)) + { + key.signalEvent(StandardWatchEventKind.ENTRY_MODIFY, node.name()); + } + + // entry removed + if (((mask & (FILE_REMOVED)) != 0) && + events.contains(StandardWatchEventKind.ENTRY_DELETE)) + { + // Due to 6636438/6636412 we may get a remove event for cases + // where a rmdir/unlink/rename is attempted but fails. Until + // this issue is resolved we re-lstat the file to check if it + // exists. If it exists then we ignore the event. To keep the + // workaround simple we don't check the st_ino so it isn't + // effective when the file is replaced. + boolean removed = true; + try { + UnixFileAttributes + .get(key.getFileRef().resolve(node.name()), false); + removed = false; + } catch (UnixException x) { } + + if (removed) + key.signalEvent(StandardWatchEventKind.ENTRY_DELETE, node.name()); + } + return false; + } + + /** + * Registers all entries in the given directory + * + * The {@code sendEvents} parameter indicates if ENTRY_CREATE events + * should be queued when new entries are found. When initially + * registering a directory then will always be false. When re-scanning + * a directory then it depends on if the event is enabled or not. + */ + void registerChildren(UnixPath dir, + SolarisWatchKey parent, + boolean sendEvents) + { + // if the ENTRY_MODIFY event is not enabled then we don't need + // modification events for entries in the directory + int events = FILE_NOFOLLOW; + if (parent.events().contains(StandardWatchEventKind.ENTRY_MODIFY)) + events |= (FILE_MODIFIED | FILE_ATTRIB); + + DirectoryStream stream = null; + try { + stream = dir.newDirectoryStream(); + } catch (IOException x) { + // nothing we can do + return; + } + try { + for (Path entry: stream) { + Path name = entry.getName(); + + // skip entry if already registered + if (parent.getChild(name) != null) + continue; + + // send ENTRY_CREATE if enabled + if (sendEvents) { + parent.signalEvent(StandardWatchEventKind.ENTRY_CREATE, name); + } + + // register it + long object = 0L; + try { + object = registerImpl((UnixPath)entry, events); + } catch (UnixException x) { + // can't register so ignore for now. + continue; + } + + // create node + EntryNode node = new EntryNode(object, entry.getName(), parent); + // tell the parent about it + parent.addChild(entry.getName(), node); + object2Node.put(object, node); + } + } catch (ConcurrentModificationException x) { + // error during iteration which we ignore for now + } finally { + try { + stream.close(); + } catch (IOException x) { } + } + } + + /** + * Update watch key's events. Where the ENTRY_MODIFY changes then we + * need to update the events of registered children. + */ + void updateEvents(SolarisWatchKey key, Set> events) { + // update events, rembering if ENTRY_MODIFY was previously + // enabled or disabled. + boolean wasModifyEnabled = key.events() + .contains(StandardWatchEventKind.ENTRY_MODIFY); + key.setEvents(events); + + // check if ENTRY_MODIFY has changed + boolean isModifyEnabled = events + .contains(StandardWatchEventKind.ENTRY_MODIFY); + if (wasModifyEnabled == isModifyEnabled) { + return; + } + + // if changed then update events of children + if (key.children != null) { + int ev = FILE_NOFOLLOW; + if (isModifyEnabled) + ev |= (FILE_MODIFIED | FILE_ATTRIB); + + for (Map.Entry entry: key.children.entrySet()) { + long object = entry.getValue().object(); + try { + portAssociate(port, + PORT_SOURCE_FILE, + object, + ev); + } catch (UnixException x) { + // nothing we can do. + } + } + } + } + + /** + * Calls port_associate to register the given path. + * Returns pointer to fileobj structure that is allocated for + * the registration. + */ + long registerImpl(UnixPath dir, int events) + throws UnixException + { + // allocate memory for the path (file_obj->fo_name field) + byte[] path = dir.getByteArrayForSysCalls(); + int len = path.length; + long name = unsafe.allocateMemory(len+1); + unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, + name, (long)len); + unsafe.putByte(name + len, (byte)0); + + // allocate memory for filedatanode structure - this is the object + // to port_associate + long object = unsafe.allocateMemory(SIZEOF_FILEOBJ); + unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0); + unsafe.putAddress(object + OFFSET_FO_NAME, name); + + // associate the object with the port + try { + portAssociate(port, + PORT_SOURCE_FILE, + object, + events); + } catch (UnixException x) { + // debugging + if (x.errno() == EAGAIN) { + System.err.println("The maximum number of objects associated "+ + "with the port has been reached"); + } + + unsafe.freeMemory(name); + unsafe.freeMemory(object); + throw x; + } + return object; + } + + /** + * Frees all resources for an file_obj object; optionally remove + * association from port + */ + void releaseObject(long object, boolean dissociate) { + // remove association + if (dissociate) { + try { + portDissociate(port, PORT_SOURCE_FILE, object); + } catch (UnixException x) { + // ignore + } + } + + // free native memory + long name = unsafe.getAddress(object + OFFSET_FO_NAME); + unsafe.freeMemory(name); + unsafe.freeMemory(object); + } + } + + /** + * A node with native (file_obj) resources + */ + private static interface Node { + long object(); + } + + /** + * A directory node with a map of the entries in the directory + */ + private static interface DirectoryNode extends Node { + void addChild(Path name, EntryNode node); + void removeChild(Path name); + EntryNode getChild(Path name); + } + + /** + * An implementation of a node that is an entry in a directory. + */ + private static class EntryNode implements Node { + private final long object; + private final Path name; + private final DirectoryNode parent; + + EntryNode(long object, Path name, DirectoryNode parent) { + this.object = object; + this.name = name; + this.parent = parent; + } + + @Override + public long object() { + return object; + } + + Path name() { + return name; + } + + DirectoryNode parent() { + return parent; + } + } + + // -- native methods -- + + private static native void init(); + + private static native int portCreate() throws UnixException; + + private static native void portAssociate(int port, int source, long object, int events) + throws UnixException; + + private static native void portDissociate(int port, int source, long object) + throws UnixException; + + private static native void portSend(int port, int events) + throws UnixException; + + private static native int portGetn(int port, long address, int max) + throws UnixException; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + init(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java new file mode 100644 index 00000000000..a8265dca7f6 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java @@ -0,0 +1,286 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.channels.*; +import java.io.FileDescriptor; +import java.util.Set; + +import sun.nio.ch.FileChannelImpl; +import sun.nio.ch.ThreadPool; +import sun.nio.ch.SimpleAsynchronousFileChannelImpl; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; + +import com.sun.nio.file.ExtendedOpenOption; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + +/** + * Factory for FileChannels and AsynchronousFileChannels + */ + +class UnixChannelFactory { + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + private UnixChannelFactory() { + } + + /** + * Represents the flags from a user-supplied set of open options. + */ + private static class Flags { + boolean read; + boolean write; + boolean append; + boolean truncateExisting; + boolean noFollowLinks; + boolean create; + boolean createNew; + boolean deleteOnClose; + boolean sync; + boolean dsync; + + static Flags toFlags(Set options) { + Flags flags = new Flags(); + for (OpenOption option: options) { + if (option instanceof StandardOpenOption) { + switch ((StandardOpenOption)option) { + case READ : flags.read = true; break; + case WRITE : flags.write = true; break; + case APPEND : flags.append = true; break; + case TRUNCATE_EXISTING : flags.truncateExisting = true; break; + case CREATE : flags.create = true; break; + case CREATE_NEW : flags.createNew = true; break; + case DELETE_ON_CLOSE : flags.deleteOnClose = true; break; + case SPARSE : /* ignore */ break; + case SYNC : flags.sync = true; break; + case DSYNC : flags.dsync = true; break; + default: throw new UnsupportedOperationException(); + } + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + flags.noFollowLinks = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException(); + } + return flags; + } + } + + + /** + * Constructs a file channel from an existing (open) file descriptor + */ + static FileChannel newFileChannel(int fd, boolean reading, boolean writing) { + FileDescriptor fdObj = new FileDescriptor(); + fdAccess.set(fdObj, fd); + return FileChannelImpl.open(fdObj, reading, writing, null); + } + + /** + * Constructs a file channel by opening a file using a dfd/path pair + */ + static FileChannel newFileChannel(int dfd, + UnixPath path, + String pathForPermissionCheck, + Set options, + int mode) + throws UnixException + { + Flags flags = Flags.toFlags(options); + + // default is reading; append => writing + if (!flags.read && !flags.write) { + if (flags.append) { + flags.write = true; + } else { + flags.read = true; + } + } + + // validation + if (flags.read && flags.append) + throw new IllegalArgumentException("READ + APPEND not allowed"); + if (flags.append && flags.truncateExisting) + throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); + + FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode); + return FileChannelImpl.open(fdObj, flags.read, flags.write, null); + } + + /** + * Constructs a file channel by opening the given file. + */ + static FileChannel newFileChannel(UnixPath path, + Set options, + int mode) + throws UnixException + { + return newFileChannel(-1, path, null, options, mode); + } + + /** + * Constructs an asynchronous file channel by opening the given file. + */ + static AsynchronousFileChannel newAsynchronousFileChannel(UnixPath path, + Set options, + int mode, + ThreadPool pool) + throws UnixException + { + Flags flags = Flags.toFlags(options); + + // default is reading + if (!flags.read && !flags.write) { + flags.read = true; + } + + // validation + if (flags.append) + throw new UnsupportedOperationException("APPEND not allowed"); + + // for now use simple implementation + FileDescriptor fdObj = open(-1, path, null, flags, mode); + return SimpleAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool); + } + + /** + * Opens file based on parameters and options, returning a FileDescriptor + * encapsulating the handle to the open file. + */ + static FileDescriptor open(int dfd, + UnixPath path, + String pathForPermissionCheck, + Flags flags, + int mode) + throws UnixException + { + // map to oflags + int oflags; + if (flags.read && flags.write) { + oflags = O_RDWR; + } else { + oflags = (flags.write) ? O_WRONLY : O_RDONLY; + } + if (flags.write) { + if (flags.truncateExisting) + oflags |= O_TRUNC; + if (flags.append) + oflags |= O_APPEND; + + // create flags + if (flags.createNew) { + byte[] pathForSysCall = path.asByteArray(); + + // throw exception if file name is "." to avoid confusing error + if ((pathForSysCall[pathForSysCall.length-1] == '.') && + (pathForSysCall.length == 1 || + (pathForSysCall[pathForSysCall.length-2] == '/'))) + { + throw new UnixException(EEXIST); + } + oflags |= (O_CREAT | O_EXCL); + } else { + if (flags.create) + oflags |= O_CREAT; + } + } + + // follow links by default + boolean followLinks = true; + if (!flags.createNew && (flags.noFollowLinks || flags.deleteOnClose)) { + followLinks = false; + oflags |= O_NOFOLLOW; + } + + if (flags.dsync) + oflags |= O_DSYNC; + if (flags.sync) + oflags |= O_SYNC; + + // permission check before we open the file + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (pathForPermissionCheck == null) + pathForPermissionCheck = path.getPathForPermissionCheck(); + if (flags.read) + sm.checkRead(pathForPermissionCheck); + if (flags.write) + sm.checkWrite(pathForPermissionCheck); + if (flags.deleteOnClose) + sm.checkDelete(pathForPermissionCheck); + } + + int fd; + try { + if (dfd >= 0) { + fd = openat(dfd, path.asByteArray(), oflags, mode); + } else { + fd = UnixNativeDispatcher.open(path, oflags, mode); + } + } catch (UnixException x) { + // Linux error can be EISDIR or EEXIST when file exists + if (flags.createNew && (x.errno() == EISDIR)) { + x.setError(EEXIST); + } + + // handle ELOOP to avoid confusing message + if (!followLinks && (x.errno() == ELOOP)) { + x = new UnixException(x.getMessage() + " (NOFOLLOW_LINKS specified)"); + } + + throw x; + } + + // unlink file immediately if delete on close. The spec is clear that + // an implementation cannot guarantee to unlink the correct file when + // replaced by an attacker after it is opened. + if (flags.deleteOnClose) { + try { + if (dfd >= 0) { + unlinkat(dfd, path.asByteArray(), 0); + } else { + unlink(path); + } + } catch (UnixException ignore) { + // best-effort + } + } + + // create java.io.FileDescriptor + FileDescriptor fdObj = new FileDescriptor(); + fdAccess.set(fdObj, fd); + return fdObj; + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java new file mode 100644 index 00000000000..808cc1e34dc --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java @@ -0,0 +1,608 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.ExecutionException; +import com.sun.nio.file.ExtendedCopyOption; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + + +/** + * Unix implementation of Path#copyTo and Path#moveTo methods. + */ + +class UnixCopyFile { + private UnixCopyFile() { } + + // The flags that control how a file is copied or moved + private static class Flags { + boolean replaceExisting; + boolean atomicMove; + boolean followLinks; + boolean interruptible; + + // the attributes to copy + boolean copyBasicAttributes; + boolean copyPosixAttributes; + boolean copyNonPosixAttributes; + + // flags that indicate if we should fail if attributes cannot be copied + boolean failIfUnableToCopyBasic; + boolean failIfUnableToCopyPosix; + boolean failIfUnableToCopyNonPosix; + + static Flags fromCopyOptions(CopyOption... options) { + Flags flags = new Flags(); + flags.followLinks = true; + for (CopyOption option: options) { + if (option == StandardCopyOption.REPLACE_EXISTING) { + flags.replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + flags.followLinks = false; + continue; + } + if (option == StandardCopyOption.COPY_ATTRIBUTES) { + // copy all attributes but only fail if basic attributes + // cannot be copied + flags.copyBasicAttributes = true; + flags.copyPosixAttributes = true; + flags.copyNonPosixAttributes = true; + flags.failIfUnableToCopyBasic = true; + continue; + } + if (option == ExtendedCopyOption.INTERRUPTIBLE) { + flags.interruptible = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + return flags; + } + + static Flags fromMoveOptions(CopyOption... options) { + Flags flags = new Flags(); + for (CopyOption option: options) { + if (option == StandardCopyOption.ATOMIC_MOVE) { + flags.atomicMove = true; + continue; + } + if (option == StandardCopyOption.REPLACE_EXISTING) { + flags.replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + // ignore + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + + // a move requires that all attributes be copied but only fail if + // the basic attributes cannot be copied + flags.copyBasicAttributes = true; + flags.copyPosixAttributes = true; + flags.copyNonPosixAttributes = true; + flags.failIfUnableToCopyBasic = true; + return flags; + } + } + + // copy directory from source to target + private static void copyDirectory(UnixPath source, + UnixFileAttributes attrs, + UnixPath target, + Flags flags) + throws IOException + { + try { + mkdir(target, attrs.mode()); + } catch (UnixException x) { + x.rethrowAsIOException(target); + } + + // no attributes to copy + if (!flags.copyBasicAttributes && + !flags.copyPosixAttributes && + !flags.copyNonPosixAttributes) return; + + // open target directory if possible (this can fail when copying a + // directory for which we don't have read access). + int dfd = -1; + try { + dfd = open(target, O_RDONLY, 0); + } catch (UnixException x) { + // access to target directory required to copy named attributes + if (flags.copyNonPosixAttributes && flags.failIfUnableToCopyNonPosix) { + try { rmdir(target); } catch (UnixException ignore) { } + x.rethrowAsIOException(target); + } + } + + boolean done = false; + try { + // copy owner/group/permissions + if (flags.copyPosixAttributes){ + try { + if (dfd >= 0) { + fchown(dfd, attrs.uid(), attrs.gid()); + fchmod(dfd, attrs.mode()); + } else { + chown(target, attrs.uid(), attrs.gid()); + chmod(target, attrs.mode()); + } + } catch (UnixException x) { + // unable to set owner/group + if (flags.failIfUnableToCopyPosix) + x.rethrowAsIOException(target); + } + } + // copy other attributes + if (flags.copyNonPosixAttributes && (dfd >= 0)) { + int sfd = -1; + try { + sfd = open(source, O_RDONLY, 0); + } catch (UnixException x) { + if (flags.failIfUnableToCopyNonPosix) + x.rethrowAsIOException(source); + } + if (sfd >= 0) { + source.getFileSystem().copyNonPosixAttributes(sfd, dfd); + close(sfd); + } + } + // copy time stamps last + if (flags.copyBasicAttributes) { + try { + if (dfd >= 0) { + futimes(dfd, attrs.lastAccessTime(), + attrs.lastModifiedTime()); + } else { + utimes(target, attrs.lastAccessTime(), + attrs.lastModifiedTime()); + } + } catch (UnixException x) { + // unable to set times + if (flags.failIfUnableToCopyBasic) + x.rethrowAsIOException(target); + } + } + done = true; + } finally { + if (dfd >= 0) + close(dfd); + if (!done) { + // rollback + try { rmdir(target); } catch (UnixException ignore) { } + } + } + } + + // copy regular file from source to target + private static void copyFile(UnixPath source, + UnixFileAttributes attrs, + UnixPath target, + Flags flags, + long addressToPollForCancel) + throws IOException + { + int fi = -1; + try { + fi = open(source, O_RDONLY, 0); + } catch (UnixException x) { + x.rethrowAsIOException(source); + } + + try { + // open new file + int fo = -1; + try { + fo = open(target, + (O_WRONLY | + O_CREAT | + O_TRUNC), + attrs.mode()); + } catch (UnixException x) { + x.rethrowAsIOException(target); + } + + // set to true when file and attributes copied + boolean complete = false; + try { + // transfer bytes to target file + try { + transfer(fo, fi, addressToPollForCancel); + } catch (UnixException x) { + x.rethrowAsIOException(source, target); + } + // copy owner/permissions + if (flags.copyPosixAttributes) { + try { + fchown(fo, attrs.uid(), attrs.gid()); + fchmod(fo, attrs.mode()); + } catch (UnixException x) { + if (flags.failIfUnableToCopyPosix) + x.rethrowAsIOException(target); + } + } + // copy non POSIX attributes (depends on file system) + if (flags.copyNonPosixAttributes) { + source.getFileSystem().copyNonPosixAttributes(fi, fo); + } + // copy time attributes + if (flags.copyBasicAttributes) { + try { + futimes(fo, attrs.lastAccessTime(), attrs.lastModifiedTime()); + } catch (UnixException x) { + if (flags.failIfUnableToCopyBasic) + x.rethrowAsIOException(target); + } + } + complete = true; + } finally { + close(fo); + + // copy of file or attributes failed so rollback + if (!complete) { + try { + unlink(target); + } catch (UnixException ignore) { } + } + } + } finally { + close(fi); + } + } + + // copy symbolic link from source to target + private static void copyLink(UnixPath source, + UnixFileAttributes attrs, + UnixPath target, + Flags flags) + throws IOException + { + byte[] linktarget = null; + try { + linktarget = readlink(source); + } catch (UnixException x) { + x.rethrowAsIOException(source); + } + try { + symlink(linktarget, target); + + if (flags.copyPosixAttributes) { + try { + lchown(target, attrs.uid(), attrs.gid()); + } catch (UnixException x) { + // ignore since link attributes not required to be copied + } + } + } catch (UnixException x) { + x.rethrowAsIOException(target); + } + } + + // copy special file from source to target + private static void copySpecial(UnixPath source, + UnixFileAttributes attrs, + UnixPath target, + Flags flags) + throws IOException + { + try { + mknod(target, attrs.mode(), attrs.rdev()); + } catch (UnixException x) { + x.rethrowAsIOException(target); + } + boolean done = false; + try { + if (flags.copyPosixAttributes) { + try { + chown(target, attrs.uid(), attrs.gid()); + chmod(target, attrs.mode()); + } catch (UnixException x) { + if (flags.failIfUnableToCopyPosix) + x.rethrowAsIOException(target); + } + } + if (flags.copyBasicAttributes) { + try { + utimes(target, attrs.lastAccessTime(), attrs.lastModifiedTime()); + } catch (UnixException x) { + if (flags.failIfUnableToCopyBasic) + x.rethrowAsIOException(target); + } + } + done = true; + } finally { + if (!done) { + try { unlink(target); } catch (UnixException ignore) { } + } + } + } + + // move file from source to target + static void move(UnixPath source, UnixPath target, CopyOption... options) + throws IOException + { + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + source.checkWrite(); + target.checkWrite(); + } + + // translate options into flags + Flags flags = Flags.fromMoveOptions(options); + + // handle atomic rename case + if (flags.atomicMove) { + try { + rename(source, target); + } catch (UnixException x) { + if (x.errno() == EXDEV) { + throw new AtomicMoveNotSupportedException( + source.getPathForExecptionMessage(), + target.getPathForExecptionMessage(), + x.errorString()); + } + x.rethrowAsIOException(source, target); + } + return; + } + + // move using rename or copy+delete + UnixFileAttributes sourceAttrs = null; + UnixFileAttributes targetAttrs = null; + + // get attributes of source file (don't follow links) + try { + sourceAttrs = UnixFileAttributes.get(source, false); + } catch (UnixException x) { + x.rethrowAsIOException(source); + } + + // get attributes of target file (don't follow links) + try { + targetAttrs = UnixFileAttributes.get(target, false); + } catch (UnixException x) { + // ignore + } + boolean targetExists = (targetAttrs != null); + + // if the target exists: + // 1. check if source and target are the same file + // 2. throw exception if REPLACE_EXISTING option is not set + // 3. delete target if REPLACE_EXISTING option set + if (targetExists) { + if (sourceAttrs.isSameFile(targetAttrs)) + return; // nothing to do as files are identical + if (!flags.replaceExisting) { + throw new FileAlreadyExistsException( + target.getPathForExecptionMessage()); + } + + // attempt to delete target + try { + if (targetAttrs.isDirectory()) { + rmdir(target); + } else { + unlink(target); + } + } catch (UnixException x) { + // target is non-empty directory that can't be replaced. + if (targetAttrs.isDirectory() && + (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) + { + throw new FileAlreadyExistsException( + source.getPathForExecptionMessage(), + target.getPathForExecptionMessage(), + x.getMessage()); + } + x.rethrowAsIOException(target); + } + } + + // first try rename + try { + rename(source, target); + return; + } catch (UnixException x) { + if (x.errno() != EXDEV && x.errno() != EISDIR) { + x.rethrowAsIOException(source, target); + } + } + + // copy source to target + if (sourceAttrs.isDirectory()) { + copyDirectory(source, sourceAttrs, target, flags); + } else { + if (sourceAttrs.isSymbolicLink()) { + copyLink(source, sourceAttrs, target, flags); + } else { + if (sourceAttrs.isDevice()) { + copySpecial(source, sourceAttrs, target, flags); + } else { + copyFile(source, sourceAttrs, target, flags, 0L); + } + } + } + + // delete source + try { + if (sourceAttrs.isDirectory()) { + rmdir(source); + } else { + unlink(source); + } + } catch (UnixException x) { + // file was copied but unable to unlink the source file so attempt + // to remove the target and throw a reasonable exception + try { + if (sourceAttrs.isDirectory()) { + rmdir(target); + } else { + unlink(target); + } + } catch (UnixException ignore) { } + + if (sourceAttrs.isDirectory() && + (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) + { + throw new DirectoryNotEmptyException( + source.getPathForExecptionMessage()); + } + x.rethrowAsIOException(source); + } + } + + // copy file from source to target + static void copy(final UnixPath source, + final UnixPath target, + CopyOption... options) throws IOException + { + // permission checks + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + source.checkRead(); + target.checkWrite(); + } + + // translate options into flags + final Flags flags = Flags.fromCopyOptions(options); + + UnixFileAttributes sourceAttrs = null; + UnixFileAttributes targetAttrs = null; + + // get attributes of source file + try { + sourceAttrs = UnixFileAttributes.get(source, flags.followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(source); + } + + // if source file is symbolic link then we must check LinkPermission + if (sm != null && sourceAttrs.isSymbolicLink()) { + sm.checkPermission(new LinkPermission("symbolic")); + } + + // get attributes of target file (don't follow links) + try { + targetAttrs = UnixFileAttributes.get(target, false); + } catch (UnixException x) { + // ignore + } + boolean targetExists = (targetAttrs != null); + + // if the target exists: + // 1. check if source and target are the same file + // 2. throw exception if REPLACE_EXISTING option is not set + // 3. try to unlink the target + if (targetExists) { + if (sourceAttrs.isSameFile(targetAttrs)) + return; // nothing to do as files are identical + if (!flags.replaceExisting) + throw new FileAlreadyExistsException( + target.getPathForExecptionMessage()); + try { + if (targetAttrs.isDirectory()) { + rmdir(target); + } else { + unlink(target); + } + } catch (UnixException x) { + // target is non-empty directory that can't be replaced. + if (targetAttrs.isDirectory() && + (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) + { + throw new FileAlreadyExistsException( + source.getPathForExecptionMessage(), + target.getPathForExecptionMessage(), + x.getMessage()); + } + x.rethrowAsIOException(target); + } + } + + // do the copy + if (sourceAttrs.isDirectory()) { + copyDirectory(source, sourceAttrs, target, flags); + return; + } + if (sourceAttrs.isSymbolicLink()) { + copyLink(source, sourceAttrs, target, flags); + return; + } + if (!flags.interruptible) { + // non-interruptible file copy + copyFile(source, sourceAttrs, target, flags, 0L); + return; + } + + // interruptible file copy + final UnixFileAttributes attrsToCopy = sourceAttrs; + Cancellable copyTask = new Cancellable() { + @Override public void implRun() throws IOException { + copyFile(source, attrsToCopy, target, flags, + addressToPollForCancel()); + } + }; + try { + Cancellable.runInterruptibly(copyTask); + } catch (ExecutionException e) { + Throwable t = e.getCause(); + if (t instanceof IOException) + throw (IOException)t; + throw new IOException(t); + } + } + + // -- native methods -- + + static native void transfer(int dst, int src, long addressToPollForCancel) + throws UnixException; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + } + +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java new file mode 100644 index 00000000000..a723d71adb2 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java @@ -0,0 +1,267 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.util.Iterator; +import java.util.ConcurrentModificationException; +import java.util.NoSuchElementException; +import java.util.concurrent.locks.*; +import java.io.IOException; +import static sun.nio.fs.UnixNativeDispatcher.*; + +/** + * Unix implementation of java.nio.file.DirectoryStream + */ + +class UnixDirectoryStream + implements DirectoryStream +{ + // path to directory when originally opened + private final UnixPath dir; + + // directory pointer (returned by opendir) + private final long dp; + + // filter (may be null) + private final DirectoryStream.Filter filter; + + // used to coorindate closing of directory stream + private final ReentrantReadWriteLock streamLock = + new ReentrantReadWriteLock(true); + + // indicates if directory stream is open (synchronize on closeLock) + private volatile boolean isClosed; + + // directory iterator + private Iterator iterator; + + /** + * Initializes a new instance + */ + UnixDirectoryStream(UnixPath dir, long dp, DirectoryStream.Filter filter) { + this.dir = dir; + this.dp = dp; + this.filter = filter; + } + + protected final UnixPath directory() { + return dir; + } + + protected final Lock readLock() { + return streamLock.readLock(); + } + + protected final Lock writeLock() { + return streamLock.writeLock(); + } + + protected final boolean isOpen() { + return !isClosed; + } + + protected final boolean closeImpl() throws IOException { + if (!isClosed) { + isClosed = true; + try { + closedir(dp); + } catch (UnixException x) { + throw new IOException(x.errorString()); + } + return true; + } else { + return false; + } + } + + @Override + public void close() + throws IOException + { + writeLock().lock(); + try { + closeImpl(); + } finally { + writeLock().unlock(); + } + } + + protected final Iterator iterator(DirectoryStream ds) { + if (isClosed) { + throw new IllegalStateException("Directory stream is closed"); + } + synchronized (this) { + if (iterator != null) + throw new IllegalStateException("Iterator already obtained"); + iterator = new UnixDirectoryIterator(ds); + return iterator; + } + } + + @Override + public Iterator iterator() { + return iterator(this); + } + + /** + * Iterator implementation + */ + private class UnixDirectoryIterator implements Iterator { + private final DirectoryStream stream; + + // true when at EOF + private boolean atEof; + + // next entry to return + private Path nextEntry; + + // previous entry returned by next method (needed by remove method) + private Path prevEntry; + + UnixDirectoryIterator(DirectoryStream stream) { + atEof = false; + this.stream = stream; + } + + // Return true if file name is "." or ".." + private boolean isSelfOrParent(byte[] nameAsBytes) { + if (nameAsBytes[0] == '.') { + if ((nameAsBytes.length == 1) || + (nameAsBytes.length == 2 && nameAsBytes[1] == '.')) { + return true; + } + } + return false; + } + + // Returns next entry (or null) + private Path readNextEntry() { + assert Thread.holdsLock(this); + + for (;;) { + byte[] nameAsBytes = null; + + // prevent close while reading + readLock().lock(); + try { + if (isClosed) + throwAsConcurrentModificationException(new + ClosedDirectoryStreamException()); + try { + nameAsBytes = readdir(dp); + } catch (UnixException x) { + try { + x.rethrowAsIOException(dir); + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); + } + } + } finally { + readLock().unlock(); + } + + // EOF + if (nameAsBytes == null) { + return null; + } + + // ignore "." and ".." + if (!isSelfOrParent(nameAsBytes)) { + Path entry = dir.resolve(nameAsBytes); + + // return entry if no filter or filter accepts it + if (filter.accept(entry)) { + return entry; + } + } + } + } + + @Override + public synchronized boolean hasNext() { + if (nextEntry == null && !atEof) { + nextEntry = readNextEntry(); + + // at EOF? + if (nextEntry == null) + atEof = true; + } + return nextEntry != null; + } + + @Override + public synchronized Path next() { + if (nextEntry == null) { + if (!atEof) { + nextEntry = readNextEntry(); + } + if (nextEntry == null) { + atEof = true; + throw new NoSuchElementException(); + } + } + prevEntry = nextEntry; + nextEntry = null; + return prevEntry; + } + + @Override + public void remove() { + if (isClosed) { + throw new ClosedDirectoryStreamException(); + } + Path entry; + synchronized (this) { + if (prevEntry == null) + throw new IllegalStateException("No previous entry to remove"); + entry = prevEntry; + prevEntry = null; + } + + // use (race-free) unlinkat if available + try { + if (stream instanceof UnixSecureDirectoryStream) { + ((UnixSecureDirectoryStream)stream) + .implDelete(entry.getName(), false, 0); + } else { + entry.delete(true); + } + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); + } catch (SecurityException se) { + throwAsConcurrentModificationException(se); + } + } + } + + private static void throwAsConcurrentModificationException(Throwable t) { + ConcurrentModificationException cme = new ConcurrentModificationException(); + cme.initCause(t); + throw cme; + } + +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixException.java b/jdk/src/solaris/classes/sun/nio/fs/UnixException.java new file mode 100644 index 00000000000..3a9967540ae --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixException.java @@ -0,0 +1,113 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; + +/** + * Internal exception thrown by native methods when error detected. + */ + +class UnixException extends Exception { + static final long serialVersionUID = 7227016794320723218L; + + private int errno; + private String msg; + + UnixException(int errno) { + this.errno = errno; + this.msg = null; + } + + UnixException(String msg) { + this.errno = 0; + this.msg = msg; + } + + int errno() { + return errno; + } + + void setError(int errno) { + this.errno = errno; + this.msg = null; + } + + String errorString() { + if (msg != null) { + return msg; + } else { + return new String(UnixNativeDispatcher.strerror(errno())); + } + } + + @Override + public String getMessage() { + return errorString(); + } + + /** + * Map well known errors to specific exceptions where possible; otherwise + * return more general FileSystemException. + */ + private IOException translateToIOException(String file, String other) { + // created with message rather than errno + if (msg != null) + return new IOException(msg); + + // handle specific cases + if (errno() == UnixConstants.EACCES) + return new AccessDeniedException(file, other, null); + if (errno() == UnixConstants.ENOENT) + return new NoSuchFileException(file, other, null); + if (errno() == UnixConstants.EEXIST) + return new FileAlreadyExistsException(file, other, null); + + // fallback to the more general exception + return new FileSystemException(file, other, errorString()); + } + + void rethrowAsIOException(String file) throws IOException { + IOException x = translateToIOException(file, null); + throw x; + } + + void rethrowAsIOException(UnixPath file, UnixPath other) throws IOException { + String a = (file == null) ? null : file.getPathForExecptionMessage(); + String b = (other == null) ? null : other.getPathForExecptionMessage(); + IOException x = translateToIOException(a, b); + throw x; + } + + void rethrowAsIOException(UnixPath file) throws IOException { + rethrowAsIOException(file, null); + } + + IOException asIOException(UnixPath file) { + return translateToIOException(file.getPathForExecptionMessage(), null); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java new file mode 100644 index 00000000000..7bbf925b734 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -0,0 +1,392 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.io.IOException; + +import static sun.nio.fs.UnixNativeDispatcher.*; + +class UnixFileAttributeViews { + + static class Basic extends AbstractBasicFileAttributeView { + protected final UnixPath file; + protected final boolean followLinks; + + Basic(UnixPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + @Override + public BasicFileAttributes readAttributes() throws IOException { + file.checkRead(); + try { + UnixFileAttributes attrs = + UnixFileAttributes.get(file, followLinks); + return attrs.asBasicFileAttributes(); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } + @Override + public void setTimes(Long lastModifiedTime, + Long lastAccessTime, + Long createTime, + TimeUnit unit) throws IOException + { + // null => don't change + if (lastModifiedTime == null && lastAccessTime == null) { + // no effect + return; + } + + file.checkWrite(); + + int fd = file.openForAttributeAccess(followLinks); + try { + UnixFileAttributes attrs = null; + + // if not changing both attributes then need existing attributes + if (lastModifiedTime == null || lastAccessTime == null) { + try { + attrs = UnixFileAttributes.get(fd); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } + + // modified time = existing, now, or new value + long modTime; + if (lastModifiedTime == null) { + modTime = attrs.lastModifiedTime(); + } else { + if (lastModifiedTime >= 0L) { + modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); + } else { + if (lastModifiedTime != -1L) + throw new IllegalArgumentException(); + modTime = System.currentTimeMillis(); + } + } + + // access time = existing, now, or new value + long accTime; + if (lastAccessTime == null) { + accTime = attrs.lastAccessTime(); + } else { + if (lastAccessTime >= 0L) { + accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); + } else { + if (lastAccessTime != -1L) + throw new IllegalArgumentException(); + accTime = System.currentTimeMillis(); + } + } + + try { + futimes(fd, accTime, modTime); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } finally { + close(fd); + } + } + } + + private static class Posix extends Basic implements PosixFileAttributeView { + private static final String PERMISSIONS_NAME = "permissions"; + private static final String OWNER_NAME = "owner"; + private static final String GROUP_NAME = "group"; + + Posix(UnixPath file, boolean followLinks) { + super(file, followLinks); + } + + final void checkReadExtended() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + file.checkRead(); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + } + + final void checkWriteExtended() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + file.checkWrite(); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + } + + @Override + public String name() { + return "posix"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(PERMISSIONS_NAME)) + return readAttributes().permissions(); + if (attribute.equals(OWNER_NAME)) + return readAttributes().owner(); + if (attribute.equals(GROUP_NAME)) + return readAttributes().group(); + return super.getAttribute(attribute); + } + + @Override + @SuppressWarnings("unchecked") + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(PERMISSIONS_NAME)) { + setPermissions((Set)value); + return; + } + if (attribute.equals(OWNER_NAME)) { + setOwner((UserPrincipal)value); + return; + } + if (attribute.equals(GROUP_NAME)) { + setGroup((GroupPrincipal)value); + return; + } + super.setAttribute(attribute, value); + } + + /** + * Invoked by readAttributes or sub-classes to add all matching posix + * attributes to the builder + */ + final void addPosixAttributesToBuilder(PosixFileAttributes attrs, + AttributesBuilder builder) + { + if (builder.match(PERMISSIONS_NAME)) + builder.add(PERMISSIONS_NAME, attrs.permissions()); + if (builder.match(OWNER_NAME)) + builder.add(OWNER_NAME, attrs.owner()); + if (builder.match(GROUP_NAME)) + builder.add(GROUP_NAME, attrs.group()); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + PosixFileAttributes attrs = readAttributes(); + addBasicAttributesToBuilder(attrs, builder); + addPosixAttributesToBuilder(attrs, builder); + return builder.unmodifiableMap(); + } + + @Override + public UnixFileAttributes readAttributes() throws IOException { + checkReadExtended(); + try { + return UnixFileAttributes.get(file, followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } + + // chmod + final void setMode(int mode) throws IOException { + checkWriteExtended(); + try { + if (followLinks) { + chmod(file, mode); + } else { + int fd = file.openForAttributeAccess(false); + try { + fchmod(fd, mode); + } finally { + close(fd); + } + } + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } + + // chown + final void setOwners(int uid, int gid) throws IOException { + checkWriteExtended(); + try { + if (followLinks) { + chown(file, uid, gid); + } else { + lchown(file, uid, gid); + } + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } + + @Override + public void setPermissions(Set perms) + throws IOException + { + setMode(UnixFileModeAttribute.toUnixMode(perms)); + } + + @Override + public void setOwner(UserPrincipal owner) + throws IOException + { + if (owner == null) + throw new NullPointerException("'owner' is null"); + if (!(owner instanceof UnixUserPrincipals.User)) + throw new ProviderMismatchException(); + if (owner instanceof UnixUserPrincipals.Group) + throw new IOException("'owner' parameter can't be a group"); + int uid = ((UnixUserPrincipals.User)owner).uid(); + setOwners(uid, -1); + } + + @Override + public UserPrincipal getOwner() throws IOException { + return readAttributes().owner(); + } + + @Override + public void setGroup(GroupPrincipal group) + throws IOException + { + if (group == null) + throw new NullPointerException("'owner' is null"); + if (!(group instanceof UnixUserPrincipals.Group)) + throw new ProviderMismatchException(); + int gid = ((UnixUserPrincipals.Group)group).gid(); + setOwners(-1, gid); + } + } + + private static class Unix extends Posix { + private static final String MODE_NAME = "mode"; + private static final String INO_NAME = "ino"; + private static final String DEV_NAME = "dev"; + private static final String RDEV_NAME = "rdev"; + private static final String UID_NAME = "uid"; + private static final String GID_NAME = "gid"; + private static final String CTIME_NAME = "ctime"; + + Unix(UnixPath file, boolean followLinks) { + super(file, followLinks); + } + + @Override + public String name() { + return "unix"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(MODE_NAME)) + return readAttributes().mode(); + if (attribute.equals(INO_NAME)) + return readAttributes().ino(); + if (attribute.equals(DEV_NAME)) + return readAttributes().dev(); + if (attribute.equals(RDEV_NAME)) + return readAttributes().rdev(); + if (attribute.equals(UID_NAME)) + return readAttributes().uid(); + if (attribute.equals(GID_NAME)) + return readAttributes().gid(); + if (attribute.equals(CTIME_NAME)) + return readAttributes().ctime(); + return super.getAttribute(attribute); + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(MODE_NAME)) { + setMode((Integer)value); + return; + } + if (attribute.equals(UID_NAME)) { + setOwners((Integer)value, -1); + return; + } + if (attribute.equals(GID_NAME)) { + setOwners(-1, (Integer)value); + return; + } + super.setAttribute(attribute, value); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + UnixFileAttributes attrs = readAttributes(); + addBasicAttributesToBuilder(attrs, builder); + addPosixAttributesToBuilder(attrs, builder); + if (builder.match(MODE_NAME)) + builder.add(MODE_NAME, attrs.mode()); + if (builder.match(INO_NAME)) + builder.add(INO_NAME, attrs.ino()); + if (builder.match(DEV_NAME)) + builder.add(DEV_NAME, attrs.dev()); + if (builder.match(RDEV_NAME)) + builder.add(RDEV_NAME, attrs.rdev()); + if (builder.match(UID_NAME)) + builder.add(UID_NAME, attrs.uid()); + if (builder.match(GID_NAME)) + builder.add(GID_NAME, attrs.gid()); + if (builder.match(CTIME_NAME)) + builder.add(CTIME_NAME, attrs.ctime()); + return builder.unmodifiableMap(); + } + } + + static BasicFileAttributeView createBasicView(UnixPath file, boolean followLinks) { + return new Basic(file, followLinks); + } + + static PosixFileAttributeView createPosixView(UnixPath file, boolean followLinks) { + return new Posix(file, followLinks); + } + + static PosixFileAttributeView createUnixView(UnixPath file, boolean followLinks) { + return new Unix(file, followLinks); + } + + static FileOwnerAttributeView createOwnerView(UnixPath file, boolean followLinks) { + return new FileOwnerAttributeViewImpl(createPosixView(file, followLinks)); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java new file mode 100644 index 00000000000..c1882d7536b --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java @@ -0,0 +1,307 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.util.concurrent.TimeUnit; +import java.util.Set; +import java.util.HashSet; + +/** + * Unix implementation of PosixFileAttributes. + */ + +class UnixFileAttributes + implements PosixFileAttributes +{ + private int st_mode; + private long st_ino; + private long st_dev; + private long st_rdev; + private int st_nlink; + private int st_uid; + private int st_gid; + private long st_size; + private long st_atime; + private long st_mtime; + private long st_ctime; + + // created lazily + private volatile UserPrincipal owner; + private volatile GroupPrincipal group; + private volatile UnixFileKey key; + + private UnixFileAttributes() { + } + + // get the UnixFileAttributes for a given file + static UnixFileAttributes get(UnixPath path, boolean followLinks) + throws UnixException + { + UnixFileAttributes attrs = new UnixFileAttributes(); + if (followLinks) { + UnixNativeDispatcher.stat(path, attrs); + } else { + UnixNativeDispatcher.lstat(path, attrs); + } + return attrs; + } + + // get the UnixFileAttributes for an open file + static UnixFileAttributes get(int fd) throws UnixException { + UnixFileAttributes attrs = new UnixFileAttributes(); + UnixNativeDispatcher.fstat(fd, attrs); + return attrs; + } + + // get the UnixFileAttributes for a given file, relative to open directory + static UnixFileAttributes get(int dfd, UnixPath path, boolean followLinks) + throws UnixException + { + UnixFileAttributes attrs = new UnixFileAttributes(); + int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW; + UnixNativeDispatcher.fstatat(dfd, path.asByteArray(), flag, attrs); + return attrs; + } + + // package-private + boolean isSameFile(UnixFileAttributes attrs) { + return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev)); + } + + // package-private + int mode() { return st_mode; } + long ino() { return st_ino; } + long dev() { return st_dev; } + long rdev() { return st_rdev; } + int uid() { return st_uid; } + int gid() { return st_gid; } + long ctime() { return st_ctime; } + + boolean isDevice() { + int type = st_mode & UnixConstants.S_IFMT; + return (type == UnixConstants.S_IFCHR || + type == UnixConstants.S_IFBLK || + type == UnixConstants.S_IFIFO); + } + + @Override + public long lastModifiedTime() { + return st_mtime; + } + + @Override + public long lastAccessTime() { + return st_atime; + } + + @Override + public long creationTime() { + return -1L; + } + + @Override + public TimeUnit resolution() { + return TimeUnit.MILLISECONDS; + } + + @Override + public boolean isRegularFile() { + return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG); + } + + @Override + public boolean isDirectory() { + return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR); + } + + @Override + public boolean isSymbolicLink() { + return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFLNK); + } + + @Override + public boolean isOther() { + int type = st_mode & UnixConstants.S_IFMT; + return (type != UnixConstants.S_IFREG && + type != UnixConstants.S_IFDIR && + type != UnixConstants.S_IFLNK); + } + + @Override + public long size() { + return st_size; + } + + @Override + public int linkCount() { + return st_nlink; + } + + @Override + public UnixFileKey fileKey() { + if (key == null) { + synchronized (this) { + if (key == null) { + key = new UnixFileKey(st_dev, st_ino); + } + } + } + return key; + } + + @Override + public UserPrincipal owner() { + if (owner == null) { + synchronized (this) { + if (owner == null) { + owner = UnixUserPrincipals.fromUid(st_uid); + } + } + } + return owner; + } + + @Override + public GroupPrincipal group() { + if (group == null) { + synchronized (this) { + if (group == null) { + group = UnixUserPrincipals.fromGid(st_gid); + } + } + } + return group; + } + + @Override + public Set permissions() { + int bits = (st_mode & UnixConstants.S_IAMB); + HashSet perms = new HashSet(); + + if ((bits & UnixConstants.S_IRUSR) > 0) + perms.add(PosixFilePermission.OWNER_READ); + if ((bits & UnixConstants.S_IWUSR) > 0) + perms.add(PosixFilePermission.OWNER_WRITE); + if ((bits & UnixConstants.S_IXUSR) > 0) + perms.add(PosixFilePermission.OWNER_EXECUTE); + + if ((bits & UnixConstants.S_IRGRP) > 0) + perms.add(PosixFilePermission.GROUP_READ); + if ((bits & UnixConstants.S_IWGRP) > 0) + perms.add(PosixFilePermission.GROUP_WRITE); + if ((bits & UnixConstants.S_IXGRP) > 0) + perms.add(PosixFilePermission.GROUP_EXECUTE); + + if ((bits & UnixConstants.S_IROTH) > 0) + perms.add(PosixFilePermission.OTHERS_READ); + if ((bits & UnixConstants.S_IWOTH) > 0) + perms.add(PosixFilePermission.OTHERS_WRITE); + if ((bits & UnixConstants.S_IXOTH) > 0) + perms.add(PosixFilePermission.OTHERS_EXECUTE); + + return perms; + } + + // wrap this object with BasicFileAttributes object to prevent leaking of + // user information + BasicFileAttributes asBasicFileAttributes() { + return UnixAsBasicFileAttributes.wrap(this); + } + + // unwrap BasicFileAttributes to get the underlying UnixFileAttributes + // object. Returns null is not wrapped. + static UnixFileAttributes toUnixFileAttributes(BasicFileAttributes attrs) { + if (attrs instanceof UnixFileAttributes) + return (UnixFileAttributes)attrs; + if (attrs instanceof UnixAsBasicFileAttributes) { + return ((UnixAsBasicFileAttributes)attrs).unwrap(); + } + return null; + } + + // wrap a UnixFileAttributes object as a BasicFileAttributes + private static class UnixAsBasicFileAttributes implements BasicFileAttributes { + private final UnixFileAttributes attrs; + + private UnixAsBasicFileAttributes(UnixFileAttributes attrs) { + this.attrs = attrs; + } + + static UnixAsBasicFileAttributes wrap(UnixFileAttributes attrs) { + return new UnixAsBasicFileAttributes(attrs); + } + + UnixFileAttributes unwrap() { + return attrs; + } + + @Override + public long lastModifiedTime() { + return attrs.lastModifiedTime(); + } + @Override + public long lastAccessTime() { + return attrs.lastAccessTime(); + } + @Override + public long creationTime() { + return attrs.creationTime(); + } + @Override + public TimeUnit resolution() { + return attrs.resolution(); + } + @Override + public boolean isRegularFile() { + return attrs.isRegularFile(); + } + @Override + public boolean isDirectory() { + return attrs.isDirectory(); + } + @Override + public boolean isSymbolicLink() { + return attrs.isSymbolicLink(); + } + @Override + public boolean isOther() { + return attrs.isOther(); + } + @Override + public long size() { + return attrs.size(); + } + @Override + public int linkCount() { + return attrs.linkCount(); + } + @Override + public Object fileKey() { + return attrs.fileKey(); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java new file mode 100644 index 00000000000..4ab3aec6c30 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileKey.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Container for device/inode to uniquely identify file. + */ + +class UnixFileKey { + private final long st_dev; + private final long st_ino; + + UnixFileKey(long st_dev, long st_ino) { + this.st_dev = st_dev; + this.st_ino = st_ino; + } + + @Override + public int hashCode() { + return (int)(st_dev ^ (st_dev >>> 32)) + + (int)(st_ino ^ (st_ino >>> 32)); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (!(obj instanceof UnixFileKey)) + return false; + UnixFileKey other = (UnixFileKey)obj; + return (this.st_dev == other.st_dev) && (this.st_ino == other.st_ino); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java new file mode 100644 index 00000000000..67ea59e943d --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileModeAttribute.java @@ -0,0 +1,84 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.util.*; + +class UnixFileModeAttribute { + static final int ALL_PERMISSIONS = + UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR | + UnixConstants.S_IRGRP | UnixConstants.S_IWGRP | UnixConstants.S_IXGRP | + UnixConstants.S_IROTH | UnixConstants.S_IWOTH | UnixConstants. S_IXOTH; + + static final int ALL_READWRITE = + UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | + UnixConstants.S_IRGRP | UnixConstants.S_IWGRP | + UnixConstants.S_IROTH | UnixConstants.S_IWOTH; + + static final int TEMPFILE_PERMISSIONS = + UnixConstants.S_IRUSR | UnixConstants.S_IWUSR | UnixConstants.S_IXUSR; + + private Set perms; + + UnixFileModeAttribute() { + perms = Collections.emptySet(); + } + + static int toUnixMode(Set perms) { + int mode = 0; + for (PosixFilePermission perm: perms) { + if (perm == null) + throw new NullPointerException(); + switch (perm) { + case OWNER_READ : mode |= UnixConstants.S_IRUSR; break; + case OWNER_WRITE : mode |= UnixConstants.S_IWUSR; break; + case OWNER_EXECUTE : mode |= UnixConstants.S_IXUSR; break; + case GROUP_READ : mode |= UnixConstants.S_IRGRP; break; + case GROUP_WRITE : mode |= UnixConstants.S_IWGRP; break; + case GROUP_EXECUTE : mode |= UnixConstants.S_IXGRP; break; + case OTHERS_READ : mode |= UnixConstants.S_IROTH; break; + case OTHERS_WRITE : mode |= UnixConstants.S_IWOTH; break; + case OTHERS_EXECUTE : mode |= UnixConstants.S_IXOTH; break; + } + } + return mode; + } + + @SuppressWarnings("unchecked") + static int toUnixMode(int defaultMode, FileAttribute... attrs) { + int mode = defaultMode; + for (FileAttribute attr: attrs) { + String name = attr.name(); + if (!name.equals("posix:permissions") && !name.equals("unix:permissions")) { + throw new UnsupportedOperationException("'" + attr.name() + + "' not supported as initial attribute"); + } + mode = toUnixMode((Set)attr.value()); + } + return mode; + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java new file mode 100644 index 00000000000..483a4ea4825 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java @@ -0,0 +1,290 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.channels.*; +import java.util.*; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Base implementation of FileStore for Unix/like implementations. + */ + +abstract class UnixFileStore + extends FileStore +{ + // original path of file that identified file system + private final UnixPath file; + + // device ID + private final long dev; + + // entry in the mount tab + private final UnixMountEntry entry; + + // return the device ID where the given file resides + private static long devFor(UnixPath file) throws IOException { + try { + return UnixFileAttributes.get(file, true).dev(); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return 0L; // keep compiler happy + } + } + + UnixFileStore(UnixPath file) throws IOException { + this.file = file; + this.dev = devFor(file); + this.entry = findMountEntry(); + } + + UnixFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException { + this.file = new UnixPath(fs, entry.dir()); + this.dev = (entry.dev() == 0L) ? devFor(this.file) : entry.dev(); + this.entry = entry; + } + + /** + * Find the mount entry for the file store + */ + abstract UnixMountEntry findMountEntry() throws IOException; + + /** + * Returns true if this file store represents a loopback file system that + * will have the same device ID as undelrying file system. + */ + abstract boolean isLoopback(); + + UnixPath file() { + return file; + } + + long dev() { + return dev; + } + + UnixMountEntry entry() { + return entry; + } + + @Override + public String name() { + return entry.name(); + } + + @Override + public String type() { + return entry.fstype(); + } + + @Override + public boolean isReadOnly() { + return entry.isReadOnly(); + } + + @Override + @SuppressWarnings("unchecked") + public V getFileStoreAttributeView(Class viewType) + { + if (viewType == FileStoreSpaceAttributeView.class) + return (V) new UnixFileStoreSpaceAttributeView(this); + return (V) null; + } + + @Override + public FileStoreAttributeView getFileStoreAttributeView(String name) { + if (name.equals("space")) + return new UnixFileStoreSpaceAttributeView(this); + return null; + } + + @Override + public boolean supportsFileAttributeView(Class type) { + if (type == BasicFileAttributeView.class) + return true; + if (type == PosixFileAttributeView.class || + type == FileOwnerAttributeView.class) + { + // lookup fstypes.properties + FeatureStatus status = checkIfFeaturePresent("posix"); + if (status == FeatureStatus.NOT_PRESENT) + return false; + return true; + } + return false; + } + + @Override + public boolean supportsFileAttributeView(String name) { + if (name.equals("basic") || name.equals("unix")) + return true; + if (name.equals("posix")) + return supportsFileAttributeView(PosixFileAttributeView.class); + if (name.equals("owner")) + return supportsFileAttributeView(FileOwnerAttributeView.class); + return false; + } + + @Override + public boolean equals(Object ob) { + if (ob == this) + return true; + if (!(ob instanceof UnixFileStore)) + return false; + UnixFileStore other = (UnixFileStore)ob; + if (dev != other.dev) + return false; + // deviceIDs are equal but they may not be equal if one or both of + // them is a loopback file system + boolean thisIsLoopback = isLoopback(); + if (thisIsLoopback != other.isLoopback()) + return false; // one, but not both, are lofs + if (!thisIsLoopback) + return true; // neither is lofs + // both are lofs so compare mount points + return Arrays.equals(this.entry.dir(), other.entry.dir()); + } + + @Override + public int hashCode() { + return (int)(dev ^ (dev >>> 32)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(new String(entry.dir())); + sb.append(" ("); + sb.append(entry.name()); + sb.append(")"); + return sb.toString(); + } + + private static class UnixFileStoreSpaceAttributeView + extends AbstractFileStoreSpaceAttributeView + { + private final UnixFileStore fs; + + UnixFileStoreSpaceAttributeView(UnixFileStore fs) { + this.fs = fs; + } + + @Override + public FileStoreSpaceAttributes readAttributes() + throws IOException + { + UnixPath file = fs.file(); + final UnixFileStoreAttributes attrs; + try { + attrs = UnixFileStoreAttributes.get(file); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compile happy + } + + return new FileStoreSpaceAttributes() { + @Override + public long totalSpace() { + return attrs.blockSize() * attrs.totalBlocks(); + } + @Override + public long usableSpace() { + return attrs.blockSize() * attrs.availableBlocks(); + } + @Override + public long unallocatedSpace() { + return attrs.blockSize() * attrs.freeBlocks(); + } + }; + } + } + + // -- fstypes.properties -- + + private static final Object loadLock = new Object(); + private static volatile Properties props; + + enum FeatureStatus { + PRESENT, + NOT_PRESENT, + UNKNOWN; + } + + /** + * Returns status to indicate if file system supports a given feature + */ + FeatureStatus checkIfFeaturePresent(String feature) { + if (props == null) { + synchronized (loadLock) { + if (props == null) { + props = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public Properties run() { + return loadProperties(); + }}); + } + } + } + + String value = props.getProperty(type()); + if (value != null) { + String[] values = value.split("\\s"); + for (String s: values) { + s = s.trim().toLowerCase(); + if (s.equals(feature)) { + return FeatureStatus.PRESENT; + } + if (s.startsWith("no")) { + s = s.substring(2); + if (s.equals(feature)) { + return FeatureStatus.NOT_PRESENT; + } + } + } + } + return FeatureStatus.UNKNOWN; + } + + private static Properties loadProperties() { + Properties result = new Properties(); + String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties"; + FileRef file = Paths.get(fstypes); + try { + ReadableByteChannel rbc = file.newByteChannel(); + try { + result.load(Channels.newReader(rbc, "UTF-8")); + } finally { + rbc.close(); + } + } catch (IOException x) { + } + return result; + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java new file mode 100644 index 00000000000..f2cbd17cc1a --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStoreAttributes.java @@ -0,0 +1,59 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +class UnixFileStoreAttributes { + private long f_frsize; // block size + private long f_blocks; // total + private long f_bfree; // free + private long f_bavail; // usable + + private UnixFileStoreAttributes() { + } + + static UnixFileStoreAttributes get(UnixPath path) throws UnixException { + UnixFileStoreAttributes attrs = new UnixFileStoreAttributes(); + UnixNativeDispatcher.statvfs(path, attrs); + return attrs; + } + + long blockSize() { + return f_frsize; + } + + long totalBlocks() { + return f_blocks; + } + + long freeBlocks() { + return f_bfree; + } + + long availableBlocks() { + return f_bavail; + } + +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java new file mode 100644 index 00000000000..6e46b2647d9 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java @@ -0,0 +1,380 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.*; +import java.io.IOException; +import java.util.*; +import java.util.regex.Pattern; +import java.security.AccessController; +import sun.security.action.GetPropertyAction; + +/** + * Base implementation of FileSystem for Unix-like implementations. + */ + +abstract class UnixFileSystem + extends FileSystem +{ + private final UnixFileSystemProvider provider; + private final byte[] defaultDirectory; + private final boolean needToResolveAgainstDefaultDirectory; + private final UnixPath rootDirectory; + + // package-private + UnixFileSystem(UnixFileSystemProvider provider, String dir) { + this.provider = provider; + this.defaultDirectory = UnixPath.normalizeAndCheck(dir).getBytes(); + if (this.defaultDirectory[0] != '/') { + throw new RuntimeException("default directory must be absolute"); + } + + // if process-wide chdir is allowed or default directory is not the + // process working directory then paths must be resolved against the + // default directory. + String propValue = AccessController.doPrivileged( + new GetPropertyAction("sun.nio.fs.chdirAllowed", "false")); + boolean chdirAllowed = (propValue.length() == 0) ? + true : Boolean.valueOf(propValue); + if (chdirAllowed) { + this.needToResolveAgainstDefaultDirectory = true; + } else { + byte[] cwd = UnixNativeDispatcher.getcwd(); + boolean defaultIsCwd = (cwd.length == defaultDirectory.length); + if (defaultIsCwd) { + for (int i=0; i getRootDirectories() { + final List allowedList = + Collections.unmodifiableList(Arrays.asList((Path)rootDirectory)); + return new Iterable() { + public Iterator iterator() { + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkRead(rootDirectory.toString()); + return allowedList.iterator(); + } catch (SecurityException x) { + List disallowed = Collections.emptyList(); + return disallowed.iterator(); + } + } + }; + } + + /** + * Returns object to iterate over entries in mounttab or equivalent + */ + abstract Iterable getMountEntries(); + + /** + * Returns a FileStore to represent the file system where the given file + * reside. + */ + abstract FileStore getFileStore(UnixPath path) throws IOException; + + /** + * Returns a FileStore to represent the file system for the given mount + * mount. + */ + abstract FileStore getFileStore(UnixMountEntry entry) throws IOException; + + /** + * Iterator returned by getFileStores method. + */ + private class FileStoreIterator implements Iterator { + private final Iterator entries; + private FileStore next; + + FileStoreIterator() { + this.entries = getMountEntries().iterator(); + } + + private FileStore readNext() { + assert Thread.holdsLock(this); + for (;;) { + if (!entries.hasNext()) + return null; + UnixMountEntry entry = entries.next(); + + // skip entries with the "ignore" option + if (entry.isIgnored()) + continue; + + // check permission to read mount point + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkRead(new String(entry.dir())); + } catch (SecurityException x) { + continue; + } + } + try { + return getFileStore(entry); + } catch (IOException ignore) { + // ignore as per spec + } + } + } + + @Override + public synchronized boolean hasNext() { + if (next != null) + return true; + next = readNext(); + return next != null; + } + + @Override + public synchronized FileStore next() { + if (next == null) + next = readNext(); + if (next == null) { + throw new NoSuchElementException(); + } else { + FileStore result = next; + next = null; + return result; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public final Iterable getFileStores() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + } catch (SecurityException se) { + return Collections.emptyList(); + } + } + return new Iterable() { + public Iterator iterator() { + return new FileStoreIterator(); + } + }; + } + + @Override + public final UnixPath getPath(String path) { + return new UnixPath(this, path); + } + + @Override + public PathMatcher getPathMatcher(String syntaxAndInput) { + int pos = syntaxAndInput.indexOf(':'); + if (pos <= 0 || pos == syntaxAndInput.length()) + throw new IllegalArgumentException(); + String syntax = syntaxAndInput.substring(0, pos); + String input = syntaxAndInput.substring(pos+1); + + String expr; + if (syntax.equals(GLOB_SYNTAX)) { + expr = Globs.toUnixRegexPattern(input); + } else { + if (syntax.equals(REGEX_SYNTAX)) { + expr = input; + } else { + throw new UnsupportedOperationException("Syntax '" + syntax + + "' not recognized"); + } + } + + // return matcher + final Pattern pattern = Pattern.compile(expr); + return new PathMatcher() { + @Override + public boolean matches(Path path) { + return pattern.matcher(path.toString()).matches(); + } + }; + } + private static final String GLOB_SYNTAX = "glob"; + private static final String REGEX_SYNTAX = "regex"; + + protected boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption option: options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + + @SuppressWarnings("unchecked") + protected V newFileAttributeView(Class view, + UnixPath file, + LinkOption... options) + { + if (view == null) + throw new NullPointerException(); + boolean followLinks = followLinks(options); + Class c = view; + if (c == BasicFileAttributeView.class) + return (V) UnixFileAttributeViews.createBasicView(file, followLinks); + if (c == PosixFileAttributeView.class) + return (V) UnixFileAttributeViews.createPosixView(file, followLinks); + if (c == FileOwnerAttributeView.class) + return (V) UnixFileAttributeViews.createOwnerView(file, followLinks); + return (V) null; + } + + static List standardFileAttributeViews() { + return Arrays.asList("basic", "posix", "unix", "owner"); + } + + protected FileAttributeView newFileAttributeView(String name, + UnixPath file, + LinkOption... options) + { + boolean followLinks = followLinks(options); + if (name.equals("basic")) + return UnixFileAttributeViews.createBasicView(file, followLinks); + if (name.equals("posix")) + return UnixFileAttributeViews.createPosixView(file, followLinks); + if (name.equals("unix")) + return UnixFileAttributeViews.createUnixView(file, followLinks); + if (name.equals("owner")) + return UnixFileAttributeViews.createOwnerView(file, followLinks); + return null; + } + + @Override + public final UserPrincipalLookupService getUserPrincipalLookupService() { + return theLookupService; + } + + private static final UserPrincipalLookupService theLookupService = + new UserPrincipalLookupService() { + @Override + public UserPrincipal lookupPrincipalByName(String name) + throws IOException + { + return UnixUserPrincipals.lookupUser(name); + } + + @Override + public GroupPrincipal lookupPrincipalByGroupName(String group) + throws IOException + { + return UnixUserPrincipals.lookupGroup(group); + } + }; +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java new file mode 100644 index 00000000000..878fe25c5e4 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -0,0 +1,139 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.FileSystemProvider; +import java.nio.channels.*; +import java.net.URI; +import java.util.concurrent.ExecutorService; +import java.io.IOException; +import java.util.*; + +import sun.nio.ch.ThreadPool; + +/** + * Base implementation of FileSystemProvider + */ + +public abstract class UnixFileSystemProvider + extends FileSystemProvider +{ + private static final String USER_DIR = "user.dir"; + private final UnixFileSystem theFileSystem; + + public UnixFileSystemProvider() { + String userDir = System.getProperty(USER_DIR); + theFileSystem = newFileSystem(userDir); + } + + /** + * Constructs a new file system using the given default directory. + */ + abstract UnixFileSystem newFileSystem(String dir); + + @Override + public final String getScheme() { + return "file"; + } + + private void checkUri(URI uri) { + if (!uri.getScheme().equalsIgnoreCase(getScheme())) + throw new IllegalArgumentException("URI does not match this provider"); + if (uri.getAuthority() != null) + throw new IllegalArgumentException("Authority component present"); + if (uri.getPath() == null) + throw new IllegalArgumentException("Path component is undefined"); + if (!uri.getPath().equals("/")) + throw new IllegalArgumentException("Path component should be '/'"); + if (uri.getQuery() != null) + throw new IllegalArgumentException("Query component present"); + if (uri.getFragment() != null) + throw new IllegalArgumentException("Fragment component present"); + } + + @Override + public final FileSystem newFileSystem(URI uri, Map env) { + checkUri(uri); + throw new FileSystemAlreadyExistsException(); + } + + @Override + public final FileSystem getFileSystem(URI uri) { + checkUri(uri); + return theFileSystem; + } + + @Override + public Path getPath(URI uri) { + return UnixUriUtils.fromUri(theFileSystem, uri); + } + + private UnixPath checkPath(Path obj) { + if (obj == null) + throw new NullPointerException(); + if (!(obj instanceof UnixPath)) + throw new ProviderMismatchException(); + return (UnixPath)obj; + } + + @Override + public final FileChannel newFileChannel(Path obj, + Set options, + FileAttribute... attrs) + throws IOException + { + UnixPath file = checkPath(obj); + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + try { + return UnixChannelFactory.newFileChannel(file, options, mode); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; + } + } + + @Override + public final AsynchronousFileChannel newAsynchronousFileChannel(Path obj, + Set options, + ExecutorService executor, + FileAttribute... attrs) throws IOException + { + UnixPath file = checkPath(obj); + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + ThreadPool pool = (executor == null) ? null : ThreadPool.wrap(executor, 0); + try { + return UnixChannelFactory + .newAsynchronousFileChannel(file, options, mode, pool); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java b/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java new file mode 100644 index 00000000000..c4769e7a7d8 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixMountEntry.java @@ -0,0 +1,85 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Represents an entry in the mount table. + */ + +class UnixMountEntry { + private byte[] name; // file system name + private byte[] dir; // directory (mount point) + private byte[] fstype; // ufs, nfs, ... + private byte[] opts; // mount options + private long dev; // device ID + + private volatile String fstypeAsString; + private volatile String optionsAsString; + + UnixMountEntry() { + } + + String name() { + return new String(name); + } + + String fstype() { + if (fstypeAsString == null) + fstypeAsString = new String(fstype); + return fstypeAsString; + } + + byte[] dir() { + return dir; + } + + long dev() { + return dev; + } + + /** + * Tells whether the mount entry has the given option. + */ + boolean hasOption(String requested) { + if (optionsAsString == null) + optionsAsString = new String(opts); + for (String opt: optionsAsString.split("\\,", 0)) { + if (opt.equals(requested)) + return true; + } + return false; + } + + // generic option + boolean isIgnored() { + return hasOption("ignore"); + } + + // generic option + boolean isReadOnly() { + return hasOption("ro"); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java new file mode 100644 index 00000000000..29140e3ec31 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -0,0 +1,556 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Unix system and library calls. + */ + +class UnixNativeDispatcher { + protected UnixNativeDispatcher() { } + + // returns a NativeBuffer containing the given path + private static NativeBuffer copyToNativeBuffer(UnixPath path) { + byte[] cstr = path.getByteArrayForSysCalls(); + int size = cstr.length + 1; + NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size); + if (buffer == null) { + buffer = NativeBuffers.allocNativeBuffer(size); + } else { + // buffer already contains the path + if (buffer.owner() == path) + return buffer; + } + NativeBuffers.copyCStringToNativeBuffer(cstr, buffer); + buffer.setOwner(path); + return buffer; + } + + /** + * char *getcwd(char *buf, size_t size); + */ + static native byte[] getcwd(); + + /** + * int dup(int filedes) + */ + static native int dup(int filedes) throws UnixException; + + /** + * int open(const char* path, int oflag, mode_t mode) + */ + static int open(UnixPath path, int flags, int mode) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + return open0(buffer.address(), flags, mode); + } finally { + buffer.release(); + } + } + private static native int open0(long pathAddress, int flags, int mode) + throws UnixException; + + /** + * int openat(int dfd, const char* path, int oflag, mode_t mode) + */ + static int openat(int dfd, byte[] path, int flags, int mode) throws UnixException { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); + try { + return openat0(dfd, buffer.address(), flags, mode); + } finally { + buffer.release(); + } + } + private static native int openat0(int dfd, long pathAddress, int flags, int mode) + throws UnixException; + + /** + * close(int filedes) + */ + static native void close(int fd); + + /** + * FILE* fopen(const char *filename, const char* mode); + */ + static long fopen(UnixPath filename, String mode) throws UnixException { + NativeBuffer pathBuffer = copyToNativeBuffer(filename); + NativeBuffer modeBuffer = NativeBuffers.asNativeBuffer(mode.getBytes()); + try { + return fopen0(pathBuffer.address(), modeBuffer.address()); + } finally { + modeBuffer.release(); + pathBuffer.release(); + } + } + private static native long fopen0(long pathAddress, long modeAddress) + throws UnixException; + + /** + * fclose(FILE* stream) + */ + static native void fclose(long stream) throws UnixException; + + /** + * link(const char* existing, const char* new) + */ + static void link(UnixPath existing, UnixPath newfile) throws UnixException { + NativeBuffer existingBuffer = copyToNativeBuffer(existing); + NativeBuffer newBuffer = copyToNativeBuffer(newfile); + try { + link0(existingBuffer.address(), newBuffer.address()); + } finally { + newBuffer.release(); + existingBuffer.release(); + } + } + private static native void link0(long existingAddress, long newAddress) + throws UnixException; + + /** + * unlink(const char* path) + */ + static void unlink(UnixPath path) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + unlink0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native void unlink0(long pathAddress) throws UnixException; + + /** + * unlinkat(int dfd, const char* path, int flag) + */ + static void unlinkat(int dfd, byte[] path, int flag) throws UnixException { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); + try { + unlinkat0(dfd, buffer.address(), flag); + } finally { + buffer.release(); + } + } + private static native void unlinkat0(int dfd, long pathAddress, int flag) + throws UnixException; + + /** + * mknod(const char* path, mode_t mode, dev_t dev) + */ + static void mknod(UnixPath path, int mode, long dev) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + mknod0(buffer.address(), mode, dev); + } finally { + buffer.release(); + } + } + private static native void mknod0(long pathAddress, int mode, long dev) + throws UnixException; + + /** + * rename(const char* old, const char* new) + */ + static void rename(UnixPath from, UnixPath to) throws UnixException { + NativeBuffer fromBuffer = copyToNativeBuffer(from); + NativeBuffer toBuffer = copyToNativeBuffer(to); + try { + rename0(fromBuffer.address(), toBuffer.address()); + } finally { + toBuffer.release(); + fromBuffer.release(); + } + } + private static native void rename0(long fromAddress, long toAddress) + throws UnixException; + + /** + * renameat(int fromfd, const char* old, int tofd, const char* new) + */ + static void renameat(int fromfd, byte[] from, int tofd, byte[] to) throws UnixException { + NativeBuffer fromBuffer = NativeBuffers.asNativeBuffer(from); + NativeBuffer toBuffer = NativeBuffers.asNativeBuffer(to); + try { + renameat0(fromfd, fromBuffer.address(), tofd, toBuffer.address()); + } finally { + toBuffer.release(); + fromBuffer.release(); + } + } + private static native void renameat0(int fromfd, long fromAddress, int tofd, long toAddress) + throws UnixException; + + /** + * mkdir(const char* path, mode_t mode) + */ + static void mkdir(UnixPath path, int mode) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + mkdir0(buffer.address(), mode); + } finally { + buffer.release(); + } + } + private static native void mkdir0(long pathAddress, int mode) throws UnixException; + + /** + * rmdir(const char* path) + */ + static void rmdir(UnixPath path) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + rmdir0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native void rmdir0(long pathAddress) throws UnixException; + + /** + * readlink(const char* path, char* buf, size_t bufsize) + * + * @return link target + */ + static byte[] readlink(UnixPath path) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + return readlink0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native byte[] readlink0(long pathAddress) throws UnixException; + + /** + * realpath(const char* path, char* resolved_name) + * + * @return resolved path + */ + static byte[] realpath(UnixPath path) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + return realpath0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native byte[] realpath0(long pathAddress) throws UnixException; + + /** + * symlink(const char* name1, const char* name2) + */ + static void symlink(byte[] name1, UnixPath name2) throws UnixException { + NativeBuffer targetBuffer = NativeBuffers.asNativeBuffer(name1); + NativeBuffer linkBuffer = copyToNativeBuffer(name2); + try { + symlink0(targetBuffer.address(), linkBuffer.address()); + } finally { + linkBuffer.release(); + targetBuffer.release(); + } + } + private static native void symlink0(long name1, long name2) + throws UnixException; + + /** + * stat(const char* path, struct stat* buf) + */ + static void stat(UnixPath path, UnixFileAttributes attrs) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + stat0(buffer.address(), attrs); + } finally { + buffer.release(); + } + } + private static native void stat0(long pathAddress, UnixFileAttributes attrs) + throws UnixException; + + /** + * lstat(const char* path, struct stat* buf) + */ + static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + lstat0(buffer.address(), attrs); + } finally { + buffer.release(); + } + } + private static native void lstat0(long pathAddress, UnixFileAttributes attrs) + throws UnixException; + + /** + * fstat(int filedes, struct stat* buf) + */ + static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException; + + /** + * fstatat(int filedes,const char* path, struct stat* buf, int flag) + */ + static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs) + throws UnixException + { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(path); + try { + fstatat0(dfd, buffer.address(), flag, attrs); + } finally { + buffer.release(); + } + } + private static native void fstatat0(int dfd, long pathAddress, int flag, + UnixFileAttributes attrs) throws UnixException; + + /** + * chown(const char* path, uid_t owner, gid_t group) + */ + static void chown(UnixPath path, int uid, int gid) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + chown0(buffer.address(), uid, gid); + } finally { + buffer.release(); + } + } + private static native void chown0(long pathAddress, int uid, int gid) + throws UnixException; + + /** + * lchown(const char* path, uid_t owner, gid_t group) + */ + static void lchown(UnixPath path, int uid, int gid) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + lchown0(buffer.address(), uid, gid); + } finally { + buffer.release(); + } + } + private static native void lchown0(long pathAddress, int uid, int gid) + throws UnixException; + + /** + * fchown(int filedes, uid_t owner, gid_t group) + */ + static native void fchown(int fd, int uid, int gid) throws UnixException; + + /** + * chmod(const char* path, mode_t mode) + */ + static void chmod(UnixPath path, int mode) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + chmod0(buffer.address(), mode); + } finally { + buffer.release(); + } + } + private static native void chmod0(long pathAddress, int mode) + throws UnixException; + + /** + * fchmod(int fildes, mode_t mode) + */ + static native void fchmod(int fd, int mode) throws UnixException; + + /** + * utimes(conar char* path, const struct timeval times[2]) + */ + static void utimes(UnixPath path, long times0, long times1) + throws UnixException + { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + utimes0(buffer.address(), times0, times1); + } finally { + buffer.release(); + } + } + private static native void utimes0(long pathAddress, long times0, long times1) + throws UnixException; + + /** + * futimes(int fildes,, const struct timeval times[2]) + */ + static native void futimes(int fd, long times0, long times1) throws UnixException; + + /** + * DIR *opendir(const char* dirname) + */ + static long opendir(UnixPath path) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + return opendir0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native long opendir0(long pathAddress) throws UnixException; + + /** + * DIR* fdopendir(int filedes) + */ + static native long fdopendir(int dfd) throws UnixException; + + + /** + * closedir(DIR* dirp) + */ + static native void closedir(long dir) throws UnixException; + + /** + * struct dirent* readdir(DIR *dirp) + * + * @return dirent->d_name + */ + static native byte[] readdir(long dir) throws UnixException; + + /** + * size_t read(int fildes, void* buf, size_t nbyte) + */ + static native int read(int fildes, long buf, int nbyte) throws UnixException; + + /** + * size_t writeint fildes, void* buf, size_t nbyte) + */ + static native int write(int fildes, long buf, int nbyte) throws UnixException; + + /** + * access(const char* path, int amode); + */ + static void access(UnixPath path, int amode) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + access0(buffer.address(), amode); + } finally { + buffer.release(); + } + } + private static native void access0(long pathAddress, int amode) throws UnixException; + + /** + * struct passwd *getpwuid(uid_t uid); + * + * @return passwd->pw_name + */ + static native byte[] getpwuid(int uid) throws UnixException; + + /** + * struct group *getgrgid(gid_t gid); + * + * @return group->gr_name + */ + static native byte[] getgrgid(int gid) throws UnixException; + + /** + * struct passwd *getpwnam(const char *name); + * + * @return passwd->pw_uid + */ + static int getpwnam(String name) throws UnixException { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes()); + try { + return getpwnam0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native int getpwnam0(long nameAddress) throws UnixException; + + /** + * struct group *getgrnam(const char *name); + * + * @return group->gr_name + */ + static int getgrnam(String name) throws UnixException { + NativeBuffer buffer = NativeBuffers.asNativeBuffer(name.getBytes()); + try { + return getgrnam0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native int getgrnam0(long nameAddress) throws UnixException; + + /** + * int getextmntent(FILE *fp, struct extmnttab *mp, int len); + */ + static native int getextmntent(long fp, UnixMountEntry entry) throws UnixException; + + /** + * statvfs(const char* path, struct statvfs *buf) + */ + static void statvfs(UnixPath path, UnixFileStoreAttributes attrs) + throws UnixException + { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + statvfs0(buffer.address(), attrs); + } finally { + buffer.release(); + } + } + private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs) + throws UnixException; + + /** + * long int pathconf(const char *path, int name); + */ + static long pathconf(UnixPath path, int name) throws UnixException { + NativeBuffer buffer = copyToNativeBuffer(path); + try { + return pathconf0(buffer.address(), name); + } finally { + buffer.release(); + } + } + private static native long pathconf0(long pathAddress, int name) + throws UnixException; + + /** + * long fpathconf(int fildes, int name); + */ + static native long fpathconf(int filedes, int name) throws UnixException; + + /** + * char* strerror(int errnum) + */ + static native byte[] strerror(int errnum); + + // initialize field IDs + private static native void initIDs(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("nio"); + return null; + }}); + initIDs(); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java new file mode 100644 index 00000000000..c1330f005ce --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -0,0 +1,1228 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.AbstractPath; +import java.nio.charset.*; +import java.nio.channels.*; +import java.security.AccessController; +import java.io.*; +import java.net.URI; +import java.util.*; +import java.lang.ref.SoftReference; +import sun.security.util.SecurityConstants; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + +/** + * Solaris/Linux implementation of java.nio.file.Path + */ + +class UnixPath + extends AbstractPath +{ + private static ThreadLocal> encoder = + new ThreadLocal>(); + + // FIXME - eliminate this reference to reduce space + private final UnixFileSystem fs; + + // internal representation + private final byte[] path; + + // String representation (created lazily) + private volatile String stringValue; + + // cached hashcode (created lazily, no need to be volatile) + private int hash; + + // array of offsets of elements in path (created lazily) + private volatile int[] offsets; + + // file permissions (created lazily) + private volatile FilePermission[] perms; + + UnixPath(UnixFileSystem fs, byte[] path) { + this.fs = fs; + this.path = path; + } + + UnixPath(UnixFileSystem fs, String input) { + // removes redundant slashes and checks for invalid characters + this(fs, encode(normalizeAndCheck(input))); + } + + // package-private + // removes redundant slashes and check input for invalid characters + static String normalizeAndCheck(String input) { + int n = input.length(); + if (n == 0) + throw new InvalidPathException(input, "Path is empty"); + char prevChar = 0; + for (int i=0; i < n; i++) { + char c = input.charAt(i); + if (c == '\u0000') + throw new InvalidPathException(input, "Nul character not allowed"); + if ((c == '/') && (prevChar == '/')) + return normalize(input, n, i - 1); + prevChar = c; + } + if (prevChar == '/') + return normalize(input, n, n - 1); + return input; + } + + private static String normalize(String input, int len, int off) { + if (len == 0) + return input; + int n = len; + while ((n > 0) && (input.charAt(n - 1) == '/')) n--; + if (n == 0) + return "/"; + StringBuilder sb = new StringBuilder(input.length()); + if (off > 0) + sb.append(input.substring(0, off)); + char prevChar = 0; + for (int i=off; i < n; i++) { + char c = input.charAt(i); + if ((c == '/') && (prevChar == '/')) + continue; + sb.append(c); + prevChar = c; + } + return sb.toString(); + } + + // encodes the given path-string into a sequence of bytes + private static byte[] encode(String input) { + SoftReference ref = encoder.get(); + CharsetEncoder ce = (ref != null) ? ref.get() : null; + if (ce == null) { + ce = Charset.defaultCharset().newEncoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT); + encoder.set(new SoftReference(ce)); + } + + char[] ca = input.toCharArray(); + + // size output buffer for worse-case size + byte[] ba = new byte[(int)(ca.length * (double)ce.maxBytesPerChar())]; + + // encode + ByteBuffer bb = ByteBuffer.wrap(ba); + CharBuffer cb = CharBuffer.wrap(ca); + ce.reset(); + CoderResult cr = ce.encode(cb, bb, true); + boolean error; + if (!cr.isUnderflow()) { + error = true; + } else { + cr = ce.flush(bb); + error = !cr.isUnderflow(); + } + if (error) { + throw new InvalidPathException(input, + "Malformed input or input contains unmappable chacraters"); + } + + // trim result to actual length if required + int len = bb.position(); + if (len != ba.length) + ba = Arrays.copyOf(ba, len); + + return ba; + } + + // package-private + byte[] asByteArray() { + return path; + } + + // use this path when making system/library calls + byte[] getByteArrayForSysCalls() { + // resolve against default directory if required (chdir allowed or + // file system default directory is not working directory) + if (getFileSystem().needToResolveAgainstDefaultDirectory()) { + return resolve(getFileSystem().defaultDirectory(), path); + } else { + return path; + } + } + + // use this message when throwing exceptions + String getPathForExecptionMessage() { + return toString(); + } + + // use this path for permission checks + String getPathForPermissionCheck() { + if (getFileSystem().needToResolveAgainstDefaultDirectory()) { + return new String(getByteArrayForSysCalls()); + } else { + return toString(); + } + } + + // Checks that the given file is a UnixPath + private UnixPath checkPath(FileRef obj) { + if (obj == null) + throw new NullPointerException(); + if (!(obj instanceof UnixPath)) + throw new ProviderMismatchException(); + return (UnixPath)obj; + } + + // create offset list if not already created + private void initOffsets() { + if (offsets == null) { + int count, index; + + // count names + count = 0; + index = 0; + while (index < path.length) { + byte c = path[index++]; + if (c != '/') { + count++; + while (index < path.length && path[index] != '/') + index++; + } + } + + // populate offsets + int[] result = new int[count]; + count = 0; + index = 0; + while (index < path.length) { + byte c = path[index]; + if (c == '/') { + index++; + } else { + result[count++] = index++; + while (index < path.length && path[index] != '/') + index++; + } + } + synchronized (this) { + if (offsets == null) + offsets = result; + } + } + } + + @Override + public UnixFileSystem getFileSystem() { + return fs; + } + + @Override + public UnixPath getRoot() { + if (path[0] == '/') { + return getFileSystem().rootDirectory(); + } else { + return null; + } + } + + @Override + public UnixPath getName() { + initOffsets(); + + int count = offsets.length; + if (count == 0) + return null; // no elements so no name + + if (count == 1 && path[0] != '/') + return this; + + int lastOffset = offsets[count-1]; + int len = path.length - lastOffset; + byte[] result = new byte[len]; + System.arraycopy(path, lastOffset, result, 0, len); + return new UnixPath(getFileSystem(), result); + } + + @Override + public UnixPath getParent() { + initOffsets(); + + int count = offsets.length; + if (count == 0) { + // no elements so no parent + return null; + } + int len = offsets[count-1] - 1; + if (len <= 0) { + // parent is root only (may be null) + return getRoot(); + } + byte[] result = new byte[len]; + System.arraycopy(path, 0, result, 0, len); + return new UnixPath(getFileSystem(), result); + } + + @Override + public int getNameCount() { + initOffsets(); + return offsets.length; + } + + @Override + public UnixPath getName(int index) { + initOffsets(); + if (index < 0) + throw new IllegalArgumentException(); + if (index >= offsets.length) + throw new IllegalArgumentException(); + + int begin = offsets[index]; + int len; + if (index == (offsets.length-1)) { + len = path.length - begin; + } else { + len = offsets[index+1] - begin - 1; + } + + // construct result + byte[] result = new byte[len]; + System.arraycopy(path, begin, result, 0, len); + return new UnixPath(getFileSystem(), result); + } + + @Override + public UnixPath subpath(int beginIndex, int endIndex) { + initOffsets(); + + if (beginIndex < 0) + throw new IllegalArgumentException(); + if (beginIndex >= offsets.length) + throw new IllegalArgumentException(); + if (endIndex > offsets.length) + throw new IllegalArgumentException(); + if (beginIndex >= endIndex) { + throw new IllegalArgumentException(); + } + + // starting offset and length + int begin = offsets[beginIndex]; + int len; + if (endIndex == offsets.length) { + len = path.length - begin; + } else { + len = offsets[endIndex] - begin - 1; + } + + // construct result + byte[] result = new byte[len]; + System.arraycopy(path, begin, result, 0, len); + return new UnixPath(getFileSystem(), result); + } + + @Override + public boolean isAbsolute() { + return (path[0] == '/'); + } + + // Resolve child against given base + private static byte[] resolve(byte[] base, byte[] child) { + if (child[0] == '/') + return child; + byte[] result; + if (base.length == 1 && base[0] == '/') { + result = new byte[child.length + 1]; + result[0] = '/'; + System.arraycopy(child, 0, result, 1, child.length); + } else { + result = new byte[base.length + 1 + child.length]; + System.arraycopy(base, 0, result, 0, base.length); + result[base.length] = '/'; + System.arraycopy(child, 0, result, base.length+1, child.length); + } + return result; + } + + @Override + public UnixPath resolve(Path obj) { + if (obj == null) + return this; + byte[] other = checkPath(obj).path; + if (other[0] == '/') + return ((UnixPath)obj); + byte[] result = resolve(path, other); + return new UnixPath(getFileSystem(), result); + } + + @Override + public UnixPath resolve(String other) { + return resolve(new UnixPath(getFileSystem(), other)); + } + + UnixPath resolve(byte[] other) { + return resolve(new UnixPath(getFileSystem(), other)); + } + + @Override + public UnixPath relativize(Path obj) { + UnixPath other = checkPath(obj); + if (other.equals(this)) + return null; + + // can only relativize paths of the same type + if (this.isAbsolute() != other.isAbsolute()) + throw new IllegalArgumentException("'other' is different type of Path"); + + int bn = this.getNameCount(); + int cn = other.getNameCount(); + + // skip matching names + int n = (bn > cn) ? cn : bn; + int i = 0; + while (i < n) { + if (!this.getName(i).equals(other.getName(i))) + break; + i++; + } + + int dotdots = bn - i; + if (i < cn) { + // remaining name components in other + UnixPath remainder = other.subpath(i, cn); + if (dotdots == 0) + return remainder; + + // result is a "../" for each remaining name in base + // followed by the remaining names in other + byte[] result = new byte[dotdots*3 + remainder.path.length]; + int pos = 0; + while (dotdots > 0) { + result[pos++] = (byte)'.'; + result[pos++] = (byte)'.'; + result[pos++] = (byte)'/'; + dotdots--; + } + System.arraycopy(remainder.path, 0, result, pos, remainder.path.length); + return new UnixPath(getFileSystem(), result); + } else { + // no remaining names in other so result is simply a sequence of ".." + byte[] result = new byte[dotdots*3 - 1]; + int pos = 0; + while (dotdots > 0) { + result[pos++] = (byte)'.'; + result[pos++] = (byte)'.'; + // no tailing slash at the end + if (dotdots > 1) + result[pos++] = (byte)'/'; + dotdots--; + } + return new UnixPath(getFileSystem(), result); + } + } + + @Override + public Path normalize() { + final int count = getNameCount(); + if (count == 0) + return this; + + boolean[] ignore = new boolean[count]; // true => ignore name + int[] size = new int[count]; // length of name + int remaining = count; // number of names remaining + boolean hasDotDot = false; // has at least one .. + boolean isAbsolute = path[0] == '/'; + + // first pass: + // 1. compute length of names + // 2. mark all occurences of "." to ignore + // 3. and look for any occurences of ".." + for (int i=0; i= 0) { + // name//.. found so mark name and ".." to be + // ignored + ignore[prevName] = true; + ignore[i] = true; + remaining = remaining - 2; + prevName = -1; + } else { + // Case: //.. so mark ".." as ignored + if (isAbsolute) { + boolean hasPrevious = false; + for (int j=0; j remaining); + } + + // no redundant names + if (remaining == count) + return this; + + // corner case - all names removed + if (remaining == 0) { + return isAbsolute ? getFileSystem().rootDirectory() : null; + } + + // compute length of result + int len = remaining - 1; + if (isAbsolute) + len++; + + for (int i=0; i 0) { + result[pos++] = '/'; + } + } + } + return new UnixPath(getFileSystem(), result); + } + + @Override + public boolean startsWith(Path other) { + UnixPath that = checkPath(other); + + // other path is longer + if (that.path.length > path.length) + return false; + + int thisOffsetCount = getNameCount(); + int thatOffsetCount = that.getNameCount(); + + // other path has no name elements + if (thatOffsetCount == 0 && this.isAbsolute()) + return true; + + // given path has more elements that this path + if (thatOffsetCount > thisOffsetCount) + return false; + + // same number of elements so must be exact match + if ((thatOffsetCount == thisOffsetCount) && + (path.length != that.path.length)) { + return false; + } + + // check offsets of elements match + for (int i=0; i path.length) + return false; + + // other path is absolute so this path must be absolute + if (that.isAbsolute() && !this.isAbsolute()) + return false; + + int thisOffsetCount = getNameCount(); + int thatOffsetCount = that.getNameCount(); + + // given path has more elements that this path + if (thatOffsetCount > thisOffsetCount) { + return false; + } else { + // same number of elements + if (thatOffsetCount == thisOffsetCount) { + if (thisOffsetCount == 0) + return true; + int expectedLen = path.length; + if (this.isAbsolute() && !that.isAbsolute()) + expectedLen--; + if (that.path.length != expectedLen) + return false; + } else { + // this path has more elements so given path must be relative + if (that.isAbsolute()) + return false; + } + } + + // compare bytes + int thisPos = offsets[thisOffsetCount - thatOffsetCount]; + int thatPos = that.offsets[0]; + while (thatPos < that.path.length) { + if (this.path[thisPos++] != that.path[thatPos++]) + return false; + } + + return true; + } + + @Override + public int compareTo(Path other) { + int len1 = path.length; + int len2 = ((UnixPath) other).path.length; + + int n = Math.min(len1, len2); + byte v1[] = path; + byte v2[] = ((UnixPath) other).path; + + int k = 0; + while (k < n) { + int c1 = v1[k] & 0xff; + int c2 = v2[k] & 0xff; + if (c1 != c2) { + return c1 - c2; + } + k++; + } + return len1 - len2; + } + + @Override + public boolean equals(Object ob) { + if ((ob != null) && (ob instanceof UnixPath)) { + return compareTo((Path)ob) == 0; + } + return false; + } + + @Override + public int hashCode() { + // OK if two or more threads compute hash + int h = hash; + if (h == 0) { + for (int i = 0; i< path.length; i++) { + h = 31*h + (path[i] & 0xff); + } + hash = h; + } + return h; + } + + @Override + public String toString() { + // OK if two or more threads create a String + if (stringValue == null) + stringValue = new String(path); // platform encoding + return stringValue; + } + + @Override + public Iterator iterator() { + initOffsets(); + return new Iterator() { + int i = 0; + @Override + public boolean hasNext() { + return (i < offsets.length); + } + @Override + public Path next() { + if (i < offsets.length) { + Path result = getName(i); + i++; + return result; + } else { + throw new NoSuchElementException(); + } + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + // -- file operations -- + + // package-private + int openForAttributeAccess(boolean followLinks) throws IOException { + int flags = O_RDONLY; + if (!followLinks) + flags |= O_NOFOLLOW; + try { + return open(this, flags, 0); + } catch (UnixException x) { + // HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380) + if (getFileSystem().isSolaris() && x.errno() == EINVAL) + x.setError(ELOOP); + + if (x.errno() == ELOOP) + throw new FileSystemException(getPathForExecptionMessage(), null, + x.getMessage() + " or unable to access attributes of symbolic link"); + + x.rethrowAsIOException(this); + return -1; // keep compile happy + } + } + + // create file permissions used for read and write checks + private void checkReadOrWrite(boolean checkRead) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) + return; + if (perms == null) { + synchronized (this) { + if (perms == null) { + FilePermission[] p = new FilePermission[2]; + String pathForPermCheck = getPathForPermissionCheck(); + p[0] = new FilePermission(pathForPermCheck, + SecurityConstants.FILE_READ_ACTION); + p[1] = new FilePermission(pathForPermCheck, + SecurityConstants.FILE_WRITE_ACTION); + perms = p; + } + } + } + if (checkRead) { + sm.checkPermission(perms[0]); + } else { + sm.checkPermission(perms[1]); + } + } + + void checkRead() { + checkReadOrWrite(true); + } + + void checkWrite() { + checkReadOrWrite(false); + } + + void checkDelete() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // permission not cached + sm.checkDelete(getPathForPermissionCheck()); + } + } + + @Override + public FileStore getFileStore() + throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + checkRead(); + } + return getFileSystem().getFileStore(this); + } + + @Override + public void checkAccess(AccessMode... modes) throws IOException { + boolean e = false; + boolean r = false; + boolean w = false; + boolean x = false; + + if (modes.length == 0) { + e = true; + } else { + for (AccessMode mode: modes) { + switch (mode) { + case READ : r = true; break; + case WRITE : w = true; break; + case EXECUTE : x = true; break; + default: throw new AssertionError("Should not get here"); + } + } + } + + int mode = 0; + if (e || r) { + checkRead(); + mode |= (r) ? R_OK : F_OK; + } + if (w) { + checkWrite(); + mode |= W_OK; + } + if (x) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // not cached + sm.checkExec(getPathForPermissionCheck()); + } + mode |= X_OK; + } + try { + access(this, mode); + } catch (UnixException exc) { + exc.rethrowAsIOException(this); + } + } + + @Override + public void delete(boolean failIfNotExists) throws IOException { + checkDelete(); + + // need file attributes to know if file is directory + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(this, false); + if (attrs.isDirectory()) { + rmdir(this); + } else { + unlink(this); + } + } catch (UnixException x) { + // no-op if file does not exist + if (!failIfNotExists && x.errno() == ENOENT) + return; + + // DirectoryNotEmptyException if not empty + if (attrs != null && attrs.isDirectory() && + (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) + throw new DirectoryNotEmptyException(getPathForExecptionMessage()); + + x.rethrowAsIOException(this); + } + } + + @Override + public DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) + throws IOException + { + if (filter == null) + throw new NullPointerException(); + checkRead(); + + // can't return SecureDirectoryStream on older kernels. + if (!getFileSystem().supportsSecureDirectoryStreams()) { + try { + long ptr = opendir(this); + return new UnixDirectoryStream(this, ptr, filter); + } catch (UnixException x) { + if (x.errno() == UnixConstants.ENOTDIR) + throw new NotDirectoryException(getPathForExecptionMessage()); + x.rethrowAsIOException(this); + } + } + + // open directory and dup file descriptor for use by + // opendir/readdir/closedir + int dfd1 = -1; + int dfd2 = -1; + long dp = 0L; + try { + dfd1 = open(this, O_RDONLY, 0); + dfd2 = dup(dfd1); + dp = fdopendir(dfd1); + } catch (UnixException x) { + if (dfd1 != -1) + close(dfd1); + if (dfd2 != -1) + close(dfd2); + if (x.errno() == UnixConstants.ENOTDIR) + throw new NotDirectoryException(getPathForExecptionMessage()); + x.rethrowAsIOException(this); + } + return new UnixSecureDirectoryStream(this, dp, dfd2, filter); + } + + // invoked by AbstractPath#copyTo + @Override + public void implCopyTo(Path obj, CopyOption... options) + throws IOException + { + UnixPath target = (UnixPath)obj; + UnixCopyFile.copy(this, target, options); + } + + @Override + public void implMoveTo(Path obj, CopyOption... options) + throws IOException + { + UnixPath target = (UnixPath)obj; + UnixCopyFile.move(this, target, options); + } + + @Override + @SuppressWarnings("unchecked") + public V + getFileAttributeView(Class type, LinkOption... options) + { + FileAttributeView view = getFileSystem() + .newFileAttributeView(type, this, options); + if (view == null) + return null; + return (V) view; + } + + @Override + public FileAttributeView getFileAttributeView(String name, LinkOption... options) { + return getFileSystem().newFileAttributeView(name, this, options); + } + + @Override + public Path createDirectory(FileAttribute... attrs) + throws IOException + { + checkWrite(); + + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs); + try { + mkdir(this, mode); + } catch (UnixException x) { + x.rethrowAsIOException(this); + } + return this; + } + + @Override + public InputStream newInputStream()throws IOException { + try { + Set options = Collections.emptySet(); + FileChannel fc = UnixChannelFactory.newFileChannel(this, options, 0); + return Channels.newInputStream(fc); + } catch (UnixException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } + } + + @Override + public SeekableByteChannel newByteChannel(Set options, + FileAttribute... attrs) + throws IOException + { + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + try { + return UnixChannelFactory.newFileChannel(this, options, mode); + } catch (UnixException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } + } + + @Override + public OutputStream newOutputStream(Set options, + FileAttribute... attrs) + throws IOException + { + // need to copy options to add WRITE + Set opts = new HashSet(options); + if (opts.contains(StandardOpenOption.READ)) + throw new IllegalArgumentException("READ not allowed"); + opts.add(StandardOpenOption.WRITE); + + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + try { + FileChannel fc = UnixChannelFactory.newFileChannel(this, opts, mode); + return Channels.newOutputStream(fc); + } catch (UnixException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } + } + + @Override + public boolean isSameFile(FileRef obj) throws IOException { + if (this.equals(obj)) + return true; + if (!(obj instanceof UnixPath)) // includes null check + return false; + UnixPath other = (UnixPath)obj; + + // check security manager access to both files + this.checkRead(); + other.checkRead(); + + UnixFileAttributes thisAttrs; + UnixFileAttributes otherAttrs; + try { + thisAttrs = UnixFileAttributes.get(this, true); + } catch (UnixException x) { + x.rethrowAsIOException(this); + return false; // keep compiler happy + } + try { + otherAttrs = UnixFileAttributes.get(other, true); + } catch (UnixException x) { + x.rethrowAsIOException(other); + return false; // keep compiler happy + } + return thisAttrs.isSameFile(otherAttrs); + } + + @Override + public Path createSymbolicLink(Path obj, FileAttribute... attrs) + throws IOException + { + UnixPath target = checkPath(obj); + + // no attributes supported when creating links + if (attrs.length > 0) { + UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE + throw new UnsupportedOperationException("Initial file attributes" + + "not supported when creating symbolic link"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("symbolic")); + checkWrite(); + } + + // create link + try { + symlink(target.asByteArray(), this); + } catch (UnixException x) { + x.rethrowAsIOException(this); + } + + return this; + } + + @Override + public Path createLink(Path obj) throws IOException { + UnixPath existing = checkPath(obj); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("hard")); + this.checkWrite(); + existing.checkWrite(); + } + try { + link(existing, this); + } catch (UnixException x) { + x.rethrowAsIOException(this, existing); + } + return this; + } + + @Override + public Path readSymbolicLink() throws IOException { + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + FilePermission perm = new FilePermission(getPathForPermissionCheck(), + SecurityConstants.FILE_READLINK_ACTION); + AccessController.checkPermission(perm); + } + try { + byte[] target = readlink(this); + return new UnixPath(getFileSystem(), target); + } catch (UnixException x) { + if (x.errno() == UnixConstants.EINVAL) + throw new NotLinkException(getPathForExecptionMessage()); + x.rethrowAsIOException(this); + return null; // keep compiler happy + } + } + + @Override + public UnixPath toAbsolutePath() { + if (isAbsolute()) { + return this; + } + // The path is relative so need to resolve against default directory, + // taking care not to reveal the user.dir + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPropertyAccess("user.dir"); + } + return new UnixPath(getFileSystem(), + resolve(getFileSystem().defaultDirectory(), path)); + } + + @Override + public UnixPath toRealPath(boolean resolveLinks) throws IOException { + checkRead(); + + UnixPath absolute = toAbsolutePath(); + + // if resolveLinks is true then use realpath + if (resolveLinks) { + try { + byte[] rp = realpath(absolute); + return new UnixPath(getFileSystem(), rp); + } catch (UnixException x) { + x.rethrowAsIOException(this); + } + } + + // if resolveLinks is false then eliminate "." and also ".." + // where the previous element is not a link. + UnixPath root = getFileSystem().rootDirectory(); + UnixPath result = root; + for (int i=0; i[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + if (watcher == null) + throw new NullPointerException(); + if (!(watcher instanceof AbstractWatchService)) + throw new ProviderMismatchException(); + checkRead(); + return ((AbstractWatchService)watcher).register(this, events, modifiers); + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java new file mode 100644 index 00000000000..e5894878709 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java @@ -0,0 +1,643 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.channels.SeekableByteChannel; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.io.IOException; + +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; + +/** + * Unix implementation of SecureDirectoryStream. + */ + +class UnixSecureDirectoryStream + extends SecureDirectoryStream +{ + private final UnixDirectoryStream ds; + private final int dfd; + + UnixSecureDirectoryStream(UnixPath dir, + long dp, + int dfd, + DirectoryStream.Filter filter) + { + this.ds = new UnixDirectoryStream(dir, dp, filter); + this.dfd = dfd; + } + + @Override + public void close() + throws IOException + { + ds.writeLock().lock(); + try { + if (ds.closeImpl()) { + UnixNativeDispatcher.close(dfd); + } + } finally { + ds.writeLock().unlock(); + } + } + + @Override + public Iterator iterator() { + return ds.iterator(this); + } + + private UnixPath getName(Path obj) { + if (obj == null) + throw new NullPointerException(); + if (!(obj instanceof UnixPath)) + throw new ProviderMismatchException(); + return (UnixPath)obj; + } + + /** + * Opens sub-directory in this directory + */ + @Override + public SecureDirectoryStream newDirectoryStream(Path obj, + boolean followLinks, + DirectoryStream.Filter filter) + throws IOException + { + UnixPath file = getName(obj); + UnixPath child = ds.directory().resolve(file); + + // permission check using name resolved against original path of directory + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + child.checkRead(); + } + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + // open directory and create new secure directory stream + int newdfd1 = -1; + int newdfd2 = -1; + long ptr = 0L; + try { + int flags = O_RDONLY; + if (!followLinks) + flags |= O_NOFOLLOW; + newdfd1 = openat(dfd, file.asByteArray(), flags , 0); + newdfd2 = dup(newdfd1); + ptr = fdopendir(newdfd1); + } catch (UnixException x) { + if (newdfd1 != -1) + UnixNativeDispatcher.close(newdfd1); + if (newdfd2 != -1) + UnixNativeDispatcher.close(newdfd2); + if (x.errno() == UnixConstants.ENOTDIR) + throw new NotDirectoryException(file.toString()); + x.rethrowAsIOException(file); + } + return new UnixSecureDirectoryStream(child, ptr, newdfd2, filter); + } finally { + ds.readLock().unlock(); + } + } + + /** + * Opens file in this directory + */ + @Override + public SeekableByteChannel newByteChannel(Path obj, + Set options, + FileAttribute... attrs) + throws IOException + { + UnixPath file = getName(obj); + + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + + // path for permission check + String pathToCheck = ds.directory().resolve(file).getPathForPermissionCheck(); + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + try { + return UnixChannelFactory.newFileChannel(dfd, file, pathToCheck, options, mode); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } finally { + ds.readLock().unlock(); + } + } + + /** + * Deletes file/directory in this directory. Works in a race-free manner + * when invoked with flags. + */ + void implDelete(Path obj, boolean haveFlags, int flags) + throws IOException + { + UnixPath file = getName(obj); + + // permission check using name resolved against original path of directory + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ds.directory().resolve(file).checkDelete(); + } + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + if (!haveFlags) { + // need file attribute to know if file is directory. This creates + // a race in that the file may be replaced by a directory or a + // directory replaced by a file between the time we query the + // file type and unlink it. + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(dfd, file, false); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + flags = (attrs.isDirectory()) ? AT_REMOVEDIR : 0; + } + + try { + unlinkat(dfd, file.asByteArray(), flags); + } catch (UnixException x) { + if ((flags & AT_REMOVEDIR) != 0) { + if (x.errno() == EEXIST || x.errno() == ENOTEMPTY) { + throw new DirectoryNotEmptyException(null); + } + } + x.rethrowAsIOException(file); + } + } finally { + ds.readLock().unlock(); + } + } + + @Override + public void deleteFile(Path file) throws IOException { + implDelete(file, true, 0); + } + + @Override + public void deleteDirectory(Path dir) throws IOException { + implDelete(dir, true, AT_REMOVEDIR); + } + + /** + * Rename/move file in this directory to another (open) directory + */ + @Override + public void move(Path fromObj, SecureDirectoryStream dir, Path toObj) + throws IOException + { + UnixPath from = getName(fromObj); + UnixPath to = getName(toObj); + if (dir == null) + throw new NullPointerException(); + if (!(dir instanceof UnixSecureDirectoryStream)) + throw new ProviderMismatchException(); + UnixSecureDirectoryStream that = (UnixSecureDirectoryStream)dir; + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + this.ds.directory().resolve(from).checkWrite(); + that.ds.directory().resolve(to).checkWrite(); + } + + // lock ordering doesn't matter + this.ds.readLock().lock(); + try { + that.ds.readLock().lock(); + try { + if (!this.ds.isOpen() || !that.ds.isOpen()) + throw new ClosedDirectoryStreamException(); + try { + renameat(this.dfd, from.asByteArray(), that.dfd, to.asByteArray()); + } catch (UnixException x) { + if (x.errno() == EXDEV) { + throw new AtomicMoveNotSupportedException( + from.toString(), to.toString(), x.errorString()); + } + x.rethrowAsIOException(from, to); + } + } finally { + that.ds.readLock().unlock(); + } + } finally { + this.ds.readLock().unlock(); + } + } + + @SuppressWarnings("unchecked") + private V getFileAttributeViewImpl(UnixPath file, + Class type, + boolean followLinks) + { + if (type == null) + throw new NullPointerException(); + Class c = type; + if (c == BasicFileAttributeView.class) { + return (V) new BasicFileAttributeViewImpl(file, followLinks); + } + if (c == PosixFileAttributeView.class || c == FileOwnerAttributeView.class) { + return (V) new PosixFileAttributeViewImpl(file, followLinks); + } + // TBD - should also support AclFileAttributeView + return (V) null; + } + + /** + * Returns file attribute view bound to this directory + */ + @Override + public V getFileAttributeView(Class type) { + return getFileAttributeViewImpl(null, type, false); + } + + /** + * Returns file attribute view bound to dfd/filename. + */ + @Override + public V getFileAttributeView(Path obj, + Class type, + LinkOption... options) + { + UnixPath file = getName(obj); + boolean followLinks = file.getFileSystem().followLinks(options); + return getFileAttributeViewImpl(file, type, followLinks); + } + + /** + * A BasicFileAttributeView implementation that using a dfd/name pair. + */ + private class BasicFileAttributeViewImpl + extends AbstractBasicFileAttributeView + { + final UnixPath file; + final boolean followLinks; + + // set to true when binding to another object + volatile boolean forwarding; + + BasicFileAttributeViewImpl(UnixPath file, boolean followLinks) + { + this.file = file; + this.followLinks = followLinks; + } + + int open() throws IOException { + int oflags = O_RDONLY; + if (!followLinks) + oflags |= O_NOFOLLOW; + try { + return openat(dfd, file.asByteArray(), oflags, 0); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return -1; // keep compiler happy + } + } + + private void checkWriteAccess() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + ds.directory().resolve(file).checkWrite(); + } + } + + @Override + public String name() { + return "basic"; + } + + @Override + public BasicFileAttributes readAttributes() throws IOException { + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (file == null) { + ds.directory().checkRead(); + } else { + ds.directory().resolve(file).checkRead(); + } + } + try { + UnixFileAttributes attrs = (file == null) ? + UnixFileAttributes.get(dfd) : + UnixFileAttributes.get(dfd, file, followLinks); + + // SECURITY: must return as BasicFileAttribute + return attrs.asBasicFileAttributes(); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } finally { + ds.readLock().unlock(); + } + } + + @Override + public void setTimes(Long lastModifiedTime, + Long lastAccessTime, + Long createTime, // ignore + TimeUnit unit) + throws IOException + { + // no effect + if (lastModifiedTime == null && lastAccessTime == null) { + return; + } + + checkWriteAccess(); + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + int fd = (file == null) ? dfd : open(); + try { + UnixFileAttributes attrs = null; + + // if not changing both attributes then need existing attributes + if (lastModifiedTime == null || lastAccessTime == null) { + try { + attrs = UnixFileAttributes.get(fd); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } + + // modified time = existing, now, or new value + long modTime; + if (lastModifiedTime == null) { + modTime = attrs.lastModifiedTime(); + } else { + if (lastModifiedTime >= 0L) { + modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); + } else { + if (lastModifiedTime != -1L) + throw new IllegalArgumentException(); + modTime = System.currentTimeMillis(); + } + } + + // access time = existing, now, or new value + long accTime; + if (lastAccessTime == null) { + accTime = attrs.lastAccessTime(); + } else { + if (lastAccessTime >= 0L) { + accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); + } else { + if (lastAccessTime != -1L) + throw new IllegalArgumentException(); + accTime = System.currentTimeMillis(); + } + } + + try { + futimes(fd, accTime, modTime); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } + } finally { + if (file != null) + UnixNativeDispatcher.close(fd); + } + } finally { + ds.readLock().unlock(); + } + } + } + + /** + * A PosixFileAttributeView implementation that using a dfd/name pair. + */ + private class PosixFileAttributeViewImpl + extends BasicFileAttributeViewImpl implements PosixFileAttributeView + { + private static final String PERMISSIONS_NAME = "permissions"; + private static final String OWNER_NAME = "owner"; + private static final String GROUP_NAME = "group"; + + PosixFileAttributeViewImpl(UnixPath file, boolean followLinks) { + super(file, followLinks); + } + + private void checkWriteAndUserAccess() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + super.checkWriteAccess(); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + } + + @Override + public String name() { + return "posix"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(PERMISSIONS_NAME)) + return readAttributes().permissions(); + if (attribute.equals(OWNER_NAME)) + return readAttributes().owner(); + if (attribute.equals(GROUP_NAME)) + return readAttributes().group(); + return super.getAttribute(attribute); + } + + @Override + @SuppressWarnings("unchecked") + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(PERMISSIONS_NAME)) { + setPermissions((Set)value); + return; + } + if (attribute.equals(OWNER_NAME)) { + setOwner((UserPrincipal)value); + return; + } + if (attribute.equals(GROUP_NAME)) { + setGroup((GroupPrincipal)value); + return; + } + super.setAttribute(attribute, value); + } + + final void addPosixAttributesToBuilder(PosixFileAttributes attrs, + AttributesBuilder builder) + { + if (builder.match(PERMISSIONS_NAME)) + builder.add(PERMISSIONS_NAME, attrs.permissions()); + if (builder.match(OWNER_NAME)) + builder.add(OWNER_NAME, attrs.owner()); + if (builder.match(GROUP_NAME)) + builder.add(GROUP_NAME, attrs.group()); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + PosixFileAttributes attrs = readAttributes(); + addBasicAttributesToBuilder(attrs, builder); + addPosixAttributesToBuilder(attrs, builder); + return builder.unmodifiableMap(); + } + + @Override + public PosixFileAttributes readAttributes() throws IOException { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (file == null) + ds.directory().checkRead(); + else + ds.directory().resolve(file).checkRead(); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + try { + UnixFileAttributes attrs = (file == null) ? + UnixFileAttributes.get(dfd) : + UnixFileAttributes.get(dfd, file, followLinks); + return attrs; + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } finally { + ds.readLock().unlock(); + } + } + + @Override + public void setPermissions(Set perms) + throws IOException + { + // permission check + checkWriteAndUserAccess(); + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + int fd = (file == null) ? dfd : open(); + try { + fchmod(fd, UnixFileModeAttribute.toUnixMode(perms)); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } finally { + if (file != null && fd >= 0) + UnixNativeDispatcher.close(fd); + } + } finally { + ds.readLock().unlock(); + } + } + + private void setOwners(int uid, int gid) throws IOException { + // permission check + checkWriteAndUserAccess(); + + ds.readLock().lock(); + try { + if (!ds.isOpen()) + throw new ClosedDirectoryStreamException(); + + int fd = (file == null) ? dfd : open(); + try { + fchown(fd, uid, gid); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } finally { + if (file != null && fd >= 0) + UnixNativeDispatcher.close(fd); + } + } finally { + ds.readLock().unlock(); + } + } + + @Override + public UserPrincipal getOwner() throws IOException { + return readAttributes().owner(); + } + + @Override + public void setOwner(UserPrincipal owner) + throws IOException + { + if (!(owner instanceof UnixUserPrincipals.User)) + throw new ProviderMismatchException(); + if (owner instanceof UnixUserPrincipals.Group) + throw new IOException("'owner' parameter can't be a group"); + int uid = ((UnixUserPrincipals.User)owner).uid(); + setOwners(uid, -1); + } + + @Override + public void setGroup(GroupPrincipal group) + throws IOException + { + if (!(group instanceof UnixUserPrincipals.Group)) + throw new ProviderMismatchException(); + int gid = ((UnixUserPrincipals.Group)group).gid(); + setOwners(-1, gid); + } + } +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java b/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java new file mode 100644 index 00000000000..bf3c78d6352 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java @@ -0,0 +1,216 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Unix specific Path <--> URI conversion + */ + +class UnixUriUtils { + private UnixUriUtils() { } + + /** + * Converts URI to Path + */ + static UnixPath fromUri(UnixFileSystem fs, URI uri) { + if (!uri.isAbsolute()) + throw new IllegalArgumentException("URI is not absolute"); + if (uri.isOpaque()) + throw new IllegalArgumentException("URI is not hierarchical"); + String scheme = uri.getScheme(); + if ((scheme == null) || !scheme.equalsIgnoreCase("file")) + throw new IllegalArgumentException("URI scheme is not \"file\""); + if (uri.getAuthority() != null) + throw new IllegalArgumentException("URI has an authority component"); + if (uri.getFragment() != null) + throw new IllegalArgumentException("URI has a fragment component"); + if (uri.getQuery() != null) + throw new IllegalArgumentException("URI has a query component"); + + String path = uri.getPath(); + if (path.equals("")) + throw new IllegalArgumentException("URI path component is empty"); + if (path.endsWith("/") && (path.length() > 1)) { + // "/foo/" --> "/foo", but "/" --> "/" + path = path.substring(0, path.length() - 1); + } + + // preserve bytes + byte[] result = new byte[path.length()]; + for (int i=0; i> 4) & 0x0f]); + sb.append(hexDigits[(c >> 0) & 0x0f]); + } + } + + // trailing slash if directory + if (sb.charAt(sb.length()-1) != '/') { + try { + if (UnixFileAttributes.get(up, true).isDirectory()) + sb.append('/'); + } catch (UnixException x) { + // ignore + } + } + + try { + return new URI(sb.toString()); + } catch (URISyntaxException x) { + throw new AssertionError(x); // should not happen + } + } + + // The following is copied from java.net.URI + + // Compute the low-order mask for the characters in the given string + private static long lowMask(String chars) { + int n = chars.length(); + long m = 0; + for (int i = 0; i < n; i++) { + char c = chars.charAt(i); + if (c < 64) + m |= (1L << c); + } + return m; + } + + // Compute the high-order mask for the characters in the given string + private static long highMask(String chars) { + int n = chars.length(); + long m = 0; + for (int i = 0; i < n; i++) { + char c = chars.charAt(i); + if ((c >= 64) && (c < 128)) + m |= (1L << (c - 64)); + } + return m; + } + + // Compute a low-order mask for the characters + // between first and last, inclusive + private static long lowMask(char first, char last) { + long m = 0; + int f = Math.max(Math.min(first, 63), 0); + int l = Math.max(Math.min(last, 63), 0); + for (int i = f; i <= l; i++) + m |= 1L << i; + return m; + } + + // Compute a high-order mask for the characters + // between first and last, inclusive + private static long highMask(char first, char last) { + long m = 0; + int f = Math.max(Math.min(first, 127), 64) - 64; + int l = Math.max(Math.min(last, 127), 64) - 64; + for (int i = f; i <= l; i++) + m |= 1L << i; + return m; + } + + // Tell whether the given character is permitted by the given mask pair + private static boolean match(char c, long lowMask, long highMask) { + if (c < 64) + return ((1L << c) & lowMask) != 0; + if (c < 128) + return ((1L << (c - 64)) & highMask) != 0; + return false; + } + + // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | + // "8" | "9" + private static final long L_DIGIT = lowMask('0', '9'); + private static final long H_DIGIT = 0L; + + // upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | + // "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | + // "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" + private static final long L_UPALPHA = 0L; + private static final long H_UPALPHA = highMask('A', 'Z'); + + // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | + // "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | + // "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" + private static final long L_LOWALPHA = 0L; + private static final long H_LOWALPHA = highMask('a', 'z'); + + // alpha = lowalpha | upalpha + private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA; + private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA; + + // alphanum = alpha | digit + private static final long L_ALPHANUM = L_DIGIT | L_ALPHA; + private static final long H_ALPHANUM = H_DIGIT | H_ALPHA; + + // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | + // "(" | ")" + private static final long L_MARK = lowMask("-_.!~*'()"); + private static final long H_MARK = highMask("-_.!~*'()"); + + // unreserved = alphanum | mark + private static final long L_UNRESERVED = L_ALPHANUM | L_MARK; + private static final long H_UNRESERVED = H_ALPHANUM | H_MARK; + + // pchar = unreserved | escaped | + // ":" | "@" | "&" | "=" | "+" | "$" | "," + private static final long L_PCHAR + = L_UNRESERVED | lowMask(":@&=+$,"); + private static final long H_PCHAR + = H_UNRESERVED | highMask(":@&=+$,"); + + // All valid path characters + private static final long L_PATH = L_PCHAR | lowMask(";/"); + private static final long H_PATH = H_PCHAR | highMask(";/"); + + private final static char[] hexDigits = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; +} diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java b/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java new file mode 100644 index 00000000000..88dfe9c4d90 --- /dev/null +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixUserPrincipals.java @@ -0,0 +1,175 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.io.IOException; +import static sun.nio.fs.UnixNativeDispatcher.*; + +/** + * Unix implementation of java.nio.file.attribute.UserPrincipal + */ + +class UnixUserPrincipals { + private static User createSpecial(String name) { return new User(-1, name); } + + static final User SPECIAL_OWNER = createSpecial("OWNER@"); + static final User SPECIAL_GROUP = createSpecial("GROUP@"); + static final User SPECIAL_EVERYONE = createSpecial("EVERYONE@"); + + static class User implements UserPrincipal { + private final int id; // uid or gid + private final boolean isGroup; + private final String name; + + private User(int id, boolean isGroup, String name) { + this.id = id; + this.isGroup = isGroup; + this.name = name; + } + + User(int id, String name) { + this(id, false, name); + } + + int uid() { + if (isGroup) + throw new AssertionError(); + return id; + } + + int gid() { + if (isGroup) + return id; + throw new AssertionError(); + } + + boolean isSpecial() { + return id == -1; + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (!(obj instanceof User)) + return false; + User other = (User)obj; + if ((this.id != other.id) || + (this.isGroup != other.isGroup)) { + return false; + } + // specials + if (this.id == -1 && other.id == -1) + return this.name.equals(other.name); + + return true; + } + + @Override + public int hashCode() { + return (id != -1) ? id : name.hashCode(); + } + } + + static class Group extends User implements GroupPrincipal { + Group(int id, String name) { + super(id, true, name); + } + } + + // return UserPrincipal representing given uid + static User fromUid(int uid) { + String name = null; + try { + name = new String(getpwuid(uid)); + } catch (UnixException x) { + name = Integer.toString(uid); + } + return new User(uid, name); + } + + // return GroupPrincipal representing given gid + static Group fromGid(int gid) { + String name = null; + try { + name = new String(getgrgid(gid)); + } catch (UnixException x) { + name = Integer.toString(gid); + } + return new Group(gid, name); + } + + // lookup user or group name + private static int lookupName(String name, boolean isGroup) + throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("lookupUserInformation")); + } + int id = -1; + try { + id = (isGroup) ? getgrnam(name) : getpwnam(name); + } catch (UnixException x) { + throw new IOException(name + ": " + x.errorString()); + } + if (id == -1) + throw new UserPrincipalNotFoundException(name); + return id; + + } + + // lookup user name + static UserPrincipal lookupUser(String name) throws IOException { + if (name.equals(SPECIAL_OWNER.getName())) + return SPECIAL_OWNER; + if (name.equals(SPECIAL_GROUP.getName())) + return SPECIAL_GROUP; + if (name.equals(SPECIAL_EVERYONE.getName())) + return SPECIAL_EVERYONE; + int uid = lookupName(name, false); + return new User(uid, name); + } + + // lookup group name + static GroupPrincipal lookupGroup(String group) + throws IOException + { + int gid = lookupName(group, true); + return new Group(gid, group); + } +} diff --git a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c index 8390a2baad5..9cfe22a1f16 100644 --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c @@ -259,6 +259,12 @@ Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env, } } +static int +isAsciiDigit(char c) +{ + return c >= '0' && c <= '9'; +} + static int closeDescriptors(void) { @@ -284,7 +290,7 @@ closeDescriptors(void) */ while ((dirp = readdir64(dp)) != NULL) { int fd; - if (isdigit(dirp->d_name[0]) && + if (isAsciiDigit(dirp->d_name[0]) && (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) close(fd); } diff --git a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c index a41aa96e10f..9e3cca486db 100644 --- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c @@ -165,16 +165,18 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); CHECK_NULL_RETURN(hostname, NULL); +#ifdef __solaris__ /* * Workaround for Solaris bug 4160367 - if a hostname contains a * white space then 0.0.0.0 is returned */ - if (isspace(hostname[0])) { + if (isspace((unsigned char)hostname[0])) { JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", (char *)hostname); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } +#endif /* Try once, with our static buffer. */ #ifdef __GLIBC__ @@ -325,7 +327,8 @@ static jboolean ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout, struct sockaddr_in* netif, jint ttl) { jint size; - jint n, len, hlen1, icmplen; + jint n, hlen1, icmplen; + socklen_t len; char sendbuf[1500]; char recvbuf[1500]; struct icmp *icmp; diff --git a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c index 181307fcba8..5ecedbc6c4f 100644 --- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c @@ -196,16 +196,18 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_UNSPEC; +#ifdef __solaris__ /* * Workaround for Solaris bug 4160367 - if a hostname contains a * white space then 0.0.0.0 is returned */ - if (isspace(hostname[0])) { + if (isspace((unsigned char)hostname[0])) { JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", (char *)hostname); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } +#endif error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); @@ -455,7 +457,8 @@ static jboolean ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout, struct sockaddr_in6* netif, jint ttl) { jint size; - jint n, len; + jint n; + socklen_t len; char sendbuf[1500]; unsigned char recvbuf[1500]; struct icmp6_hdr *icmp6; diff --git a/jdk/src/solaris/native/java/net/NetworkInterface.c b/jdk/src/solaris/native/java/net/NetworkInterface.c index 14273f5c132..a741f86ad2f 100644 --- a/jdk/src/solaris/native/java/net/NetworkInterface.c +++ b/jdk/src/solaris/native/java/net/NetworkInterface.c @@ -969,13 +969,39 @@ netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family, // Got access to parent, so create it if necessary. strcpy(vname, name); *unit = '\0'; - } - else { + } else { +#if defined(__solaris__) && defined(AF_INET6) + struct lifreq lifr; + memset((char *) &lifr, 0, sizeof(lifr)); + strcpy(lifr.lifr_name, vname); + + /* Try with an IPv6 socket in case the interface has only IPv6 + * addresses assigned to it */ + close(sock); + sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); + + if (sock < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Socket creation failed"); + return ifs; /* return untouched list */ + } + + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) { + // Got access to parent, so create it if necessary. + strcpy(vname, name); + *unit = '\0'; + } else { + // failed to access parent interface do not create parent. + // We are a virtual interface with no parent. + isVirtual = 1; + vname[0] = 0; + } +#else // failed to access parent interface do not create parent. // We are a virtual interface with no parent. isVirtual = 1; - vname[0] = 0; +#endif } } close(sock); diff --git a/jdk/src/solaris/native/sun/awt/awt_Robot.c b/jdk/src/solaris/native/sun/awt/awt_Robot.c index 07c053bce28..6fce85dc7bc 100644 --- a/jdk/src/solaris/native/sun/awt/awt_Robot.c +++ b/jdk/src/solaris/native/sun/awt/awt_Robot.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,7 @@ extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; // 2 would be more correct, however that's how Robot originally worked // and tests start to fail if this value is changed static int32_t num_buttons = 3; +static jint * masks; static int32_t isXTestAvailable() { int32_t major_opcode, first_event, first_error; @@ -208,6 +209,26 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls) { int32_t xtestAvailable; +// this should be called from XRobotPeer constructor + jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent"); + jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I"); + jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID); + jsize len = (*env)->GetArrayLength(env, obj); + jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE); + + masks = (jint *)malloc(sizeof(jint)*len); + if (masks == (jint *) NULL) { + JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL); + goto finally; + } + + int i; + for (i = 0; i < len; i++) { + masks[i] = tmp[i]; + } + (*env)->ReleaseIntArrayElements(env, obj, tmp, 0); + (*env)->DeleteLocalRef(env, obj); + DTRACE_PRINTLN("RobotPeer: setup()"); AWT_LOCK(); @@ -221,10 +242,17 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls) { } getNumButtons(); - + finally: AWT_UNLOCK(); } +JNIEXPORT jint JNICALL +Java_sun_awt_X11_XRobotPeer_getNumberOfButtonsImpl(JNIEnv *env, + jclass cls) { + // At the moment this routine being called we already should have an initialized num_buttons variable. + return num_buttons; +} + JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, jclass cls, @@ -348,52 +376,65 @@ Java_sun_awt_X11_XRobotPeer_mouseMoveImpl (JNIEnv *env, AWT_UNLOCK(); } +/* + * Function joining the code of mousePressImpl and mouseReleaseImpl + */ +void mouseAction(JNIEnv *env, + jclass cls, + jint buttonMask, + Bool isMousePress) +{ + AWT_LOCK(); + + DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask); + DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress); + + if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK ) + { + XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime); + } + if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) && + (num_buttons >= 2)) { + XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime); + } + if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) && + (num_buttons >= 3)) { + XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime); + } + + if (num_buttons > 3){ + int32_t i; + int32_t button = 0; + for (i = 3; i +1 + // users wants to affect 4 or 5 button but they are assigned + // to the wheel so => we have to shift it to the right by 2. + button = i + 3; + XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime); + } + } + } + + XSync(awt_display, False); + AWT_UNLOCK(); +} + JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_mousePressImpl (JNIEnv *env, jclass cls, jint buttonMask) { - AWT_LOCK(); - - DTRACE_PRINTLN1("RobotPeer: mousePressImpl(%i)", buttonMask); - - if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK) { - XTestFakeButtonEvent(awt_display, 1, True, CurrentTime); - } - if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK) && - (num_buttons >= 2)) { - XTestFakeButtonEvent(awt_display, 2, True, CurrentTime); - } - if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK) && - (num_buttons >= 3)) { - XTestFakeButtonEvent(awt_display, 3, True, CurrentTime); - } - XSync(awt_display, False); - - AWT_UNLOCK(); + mouseAction(env, cls, buttonMask, True); } JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl (JNIEnv *env, jclass cls, jint buttonMask) { - AWT_LOCK(); - - DTRACE_PRINTLN1("RobotPeer: mouseReleaseImpl(%i)", buttonMask); - - if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK) { - XTestFakeButtonEvent(awt_display, 1, False, CurrentTime); - } - if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK) && - (num_buttons >= 2)) { - XTestFakeButtonEvent(awt_display, 2, False, CurrentTime); - } - if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK) && - (num_buttons >= 3)) { - XTestFakeButtonEvent(awt_display, 3, False, CurrentTime); - } - XSync(awt_display, False); - - AWT_UNLOCK(); + mouseAction(env, cls, buttonMask, False); } JNIEXPORT void JNICALL diff --git a/jdk/src/solaris/native/sun/nio/ch/EPoll.c b/jdk/src/solaris/native/sun/nio/ch/EPoll.c new file mode 100644 index 00000000000..fc9cab72cc2 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/ch/EPoll.c @@ -0,0 +1,151 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" +#include "nio_util.h" + +#include "sun_nio_ch_EPoll.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* epoll_wait(2) man page */ + +typedef union epoll_data { + void *ptr; + int fd; + __uint32_t u32; + __uint64_t u64; +} epoll_data_t; + +struct epoll_event { + __uint32_t events; /* Epoll events */ + epoll_data_t data; /* User data variable */ +} __attribute__ ((__packed__)); + +#ifdef __cplusplus +} +#endif + +/* + * epoll event notification is new in 2.6 kernel. As the offical build + * platform for the JDK is on a 2.4-based distribution then we must + * obtain the addresses of the epoll functions dynamically. + */ +typedef int (*epoll_create_t)(int size); +typedef int (*epoll_ctl_t) (int epfd, int op, int fd, struct epoll_event *event); +typedef int (*epoll_wait_t) (int epfd, struct epoll_event *events, int maxevents, int timeout); + +static epoll_create_t epoll_create_func; +static epoll_ctl_t epoll_ctl_func; +static epoll_wait_t epoll_wait_func; + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPoll_init(JNIEnv *env, jclass this) +{ + epoll_create_func = (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create"); + epoll_ctl_func = (epoll_ctl_t) dlsym(RTLD_DEFAULT, "epoll_ctl"); + epoll_wait_func = (epoll_wait_t) dlsym(RTLD_DEFAULT, "epoll_wait"); + + if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) || + (epoll_wait_func == NULL)) { + JNU_ThrowInternalError(env, "unable to get address of epoll functions, pre-2.6 kernel?"); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass this) +{ + return sizeof(struct epoll_event); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass this) +{ + return offsetof(struct epoll_event, events); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass this) +{ + return offsetof(struct epoll_event, data); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) { + /* + * epoll_create expects a size as a hint to the kernel about how to + * dimension internal structures. We can't predict the size in advance. + */ + int epfd = (*epoll_create_func)(256); + if (epfd < 0) { + JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed"); + } + return epfd; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd, + jint opcode, jint fd, jint events) +{ + struct epoll_event event; + int res; + + event.events = events; + event.data.fd = fd; + + RESTARTABLE((*epoll_ctl_func)(epfd, (int)opcode, (int)fd, &event), res); + + return (res == 0) ? 0 : errno; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_EPoll_epollWait(JNIEnv *env, jclass c, + jint epfd, jlong address, jint numfds) +{ + struct epoll_event *events = jlong_to_ptr(address); + int res; + + RESTARTABLE((*epoll_wait_func)(epfd, events, numfds, -1), res); + if (res < 0) { + JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed"); + } + return res; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPoll_close0(JNIEnv *env, jclass c, jint epfd) { + int res; + RESTARTABLE(close(epfd), res); +} diff --git a/jdk/src/solaris/native/sun/nio/ch/EPollPort.c b/jdk/src/solaris/native/sun/nio/ch/EPollPort.c new file mode 100644 index 00000000000..8d34dd8dd4b --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/ch/EPollPort.c @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" +#include "nio_util.h" + +#include "sun_nio_ch_EPollPort.h" + +#include +#include +#include + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) { + int sp[2]; + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) { + JNU_ThrowIOExceptionWithLastError(env, "socketpair failed"); + } else { + jint res[2]; + res[0] = (jint)sp[0]; + res[1] = (jint)sp[1]; + (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPollPort_interrupt(JNIEnv *env, jclass c, jint fd) { + int res; + int buf[1]; + buf[0] = 1; + RESTARTABLE(write(fd, buf, 1), res); + if (res < 0) { + JNU_ThrowIOExceptionWithLastError(env, "write failed"); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPollPort_drain1(JNIEnv *env, jclass cl, jint fd) { + int res; + char buf[1]; + RESTARTABLE(read(fd, buf, 1), res); + if (res < 0) { + JNU_ThrowIOExceptionWithLastError(env, "drain1 failed"); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint fd) { + int res; + RESTARTABLE(close(fd), res); +} diff --git a/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c index b42c899e521..7b37e6168b8 100644 --- a/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ #include #include "sun_nio_ch_FileChannelImpl.h" #include "java_lang_Integer.h" -#include "java_lang_Long.h" #include "nio.h" #include "nio_util.h" #include @@ -145,32 +144,6 @@ Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, } -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_truncate0(JNIEnv *env, jobject this, - jobject fdo, jlong size) -{ - return handle(env, - ftruncate64(fdval(env, fdo), size), - "Truncation failed"); -} - - -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_force0(JNIEnv *env, jobject this, - jobject fdo, jboolean md) -{ - jint fd = fdval(env, fdo); - int result = 0; - - if (md == JNI_FALSE) { - result = fdatasync(fd); - } else { - result = fsync(fd); - } - return handle(env, result, "Force failed"); -} - - JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, jobject fdo, jlong offset) @@ -187,17 +160,6 @@ Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, } -JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileChannelImpl_size0(JNIEnv *env, jobject this, jobject fdo) -{ - struct stat64 fbuf; - - if (fstat64(fdval(env, fdo), &fbuf) < 0) - return handle(env, -1, "Size failed"); - return fbuf.st_size; -} - - JNIEXPORT void JNICALL Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) { @@ -280,65 +242,3 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, } #endif } - -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_lock0(JNIEnv *env, jobject this, jobject fdo, - jboolean block, jlong pos, jlong size, - jboolean shared) -{ - jint fd = fdval(env, fdo); - jint lockResult = 0; - int cmd = 0; - struct flock64 fl; - - fl.l_whence = SEEK_SET; - if (size == (jlong)java_lang_Long_MAX_VALUE) { - fl.l_len = (off64_t)0; - } else { - fl.l_len = (off64_t)size; - } - fl.l_start = (off64_t)pos; - if (shared == JNI_TRUE) { - fl.l_type = F_RDLCK; - } else { - fl.l_type = F_WRLCK; - } - if (block == JNI_TRUE) { - cmd = F_SETLKW64; - } else { - cmd = F_SETLK64; - } - lockResult = fcntl(fd, cmd, &fl); - if (lockResult < 0) { - if ((cmd == F_SETLK64) && (errno == EAGAIN)) - return sun_nio_ch_FileChannelImpl_NO_LOCK; - if (errno == EINTR) - return sun_nio_ch_FileChannelImpl_INTERRUPTED; - JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); - } - return 0; -} - - -JNIEXPORT void JNICALL -Java_sun_nio_ch_FileChannelImpl_release0(JNIEnv *env, jobject this, - jobject fdo, jlong pos, jlong size) -{ - jint fd = fdval(env, fdo); - jint lockResult = 0; - struct flock64 fl; - int cmd = F_SETLK64; - - fl.l_whence = SEEK_SET; - if (size == (jlong)java_lang_Long_MAX_VALUE) { - fl.l_len = (off64_t)0; - } else { - fl.l_len = (off64_t)size; - } - fl.l_start = (off64_t)pos; - fl.l_type = F_UNLCK; - lockResult = fcntl(fd, cmd, &fl); - if (lockResult < 0) { - JNU_ThrowIOExceptionWithLastError(env, "Release failed"); - } -} diff --git a/jdk/src/solaris/native/sun/nio/ch/FileDispatcher.c b/jdk/src/solaris/native/sun/nio/ch/FileDispatcherImpl.c similarity index 50% rename from jdk/src/solaris/native/sun/nio/ch/FileDispatcher.c rename to jdk/src/solaris/native/sun/nio/ch/FileDispatcherImpl.c index fd3c0e3d6ee..ed658893338 100644 --- a/jdk/src/solaris/native/sun/nio/ch/FileDispatcher.c +++ b/jdk/src/solaris/native/sun/nio/ch/FileDispatcherImpl.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,13 @@ #include "jni_util.h" #include "jvm.h" #include "jlong.h" -#include "sun_nio_ch_FileDispatcher.h" +#include "sun_nio_ch_FileDispatcherImpl.h" +#include "java_lang_Long.h" #include #include #include #include +#include "nio.h" #include "nio_util.h" @@ -40,7 +42,7 @@ static int preCloseFD = -1; /* File descriptor to which we dup other fd's JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_init(JNIEnv *env, jclass cl) +Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl) { int sp[2]; if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) { @@ -52,7 +54,7 @@ Java_sun_nio_ch_FileDispatcher_init(JNIEnv *env, jclass cl) } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_read0(JNIEnv *env, jclass clazz, +Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); @@ -62,7 +64,7 @@ Java_sun_nio_ch_FileDispatcher_read0(JNIEnv *env, jclass clazz, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_pread0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { jint fd = fdval(env, fdo); @@ -72,7 +74,7 @@ Java_sun_nio_ch_FileDispatcher_pread0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileDispatcher_readv0(JNIEnv *env, jclass clazz, +Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); @@ -84,7 +86,7 @@ Java_sun_nio_ch_FileDispatcher_readv0(JNIEnv *env, jclass clazz, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_write0(JNIEnv *env, jclass clazz, +Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); @@ -94,7 +96,7 @@ Java_sun_nio_ch_FileDispatcher_write0(JNIEnv *env, jclass clazz, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { jint fd = fdval(env, fdo); @@ -104,7 +106,7 @@ Java_sun_nio_ch_FileDispatcher_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileDispatcher_writev0(JNIEnv *env, jclass clazz, +Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { jint fd = fdval(env, fdo); @@ -115,6 +117,113 @@ Java_sun_nio_ch_FileDispatcher_writev0(JNIEnv *env, jclass clazz, return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE); } +static jlong +handle(JNIEnv *env, jlong rv, char *msg) +{ + if (rv >= 0) + return rv; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, msg); + return IOS_THROWN; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, + jobject fdo, jboolean md) +{ + jint fd = fdval(env, fdo); + int result = 0; + + if (md == JNI_FALSE) { + result = fdatasync(fd); + } else { + result = fsync(fd); + } + return handle(env, result, "Force failed"); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, + jobject fdo, jlong size) +{ + return handle(env, + ftruncate64(fdval(env, fdo), size), + "Truncation failed"); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) +{ + struct stat64 fbuf; + + if (fstat64(fdval(env, fdo), &fbuf) < 0) + return handle(env, -1, "Size failed"); + return fbuf.st_size; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, + jboolean block, jlong pos, jlong size, + jboolean shared) +{ + jint fd = fdval(env, fdo); + jint lockResult = 0; + int cmd = 0; + struct flock64 fl; + + fl.l_whence = SEEK_SET; + if (size == (jlong)java_lang_Long_MAX_VALUE) { + fl.l_len = (off64_t)0; + } else { + fl.l_len = (off64_t)size; + } + fl.l_start = (off64_t)pos; + if (shared == JNI_TRUE) { + fl.l_type = F_RDLCK; + } else { + fl.l_type = F_WRLCK; + } + if (block == JNI_TRUE) { + cmd = F_SETLKW64; + } else { + cmd = F_SETLK64; + } + lockResult = fcntl(fd, cmd, &fl); + if (lockResult < 0) { + if ((cmd == F_SETLK64) && (errno == EAGAIN)) + return sun_nio_ch_FileDispatcherImpl_NO_LOCK; + if (errno == EINTR) + return sun_nio_ch_FileDispatcherImpl_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); + } + return 0; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, + jobject fdo, jlong pos, jlong size) +{ + jint fd = fdval(env, fdo); + jint lockResult = 0; + struct flock64 fl; + int cmd = F_SETLK64; + + fl.l_whence = SEEK_SET; + if (size == (jlong)java_lang_Long_MAX_VALUE) { + fl.l_len = (off64_t)0; + } else { + fl.l_len = (off64_t)size; + } + fl.l_start = (off64_t)pos; + fl.l_type = F_UNLCK; + lockResult = fcntl(fd, cmd, &fl); + if (lockResult < 0) { + JNU_ThrowIOExceptionWithLastError(env, "Release failed"); + } +} + + static void closeFileDescriptor(JNIEnv *env, int fd) { if (fd != -1) { int result = close(fd); @@ -124,14 +233,14 @@ static void closeFileDescriptor(JNIEnv *env, int fd) { } JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_close0(JNIEnv *env, jclass clazz, jobject fdo) +Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) { jint fd = fdval(env, fdo); closeFileDescriptor(env, fd); } JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_preClose0(JNIEnv *env, jclass clazz, jobject fdo) +Java_sun_nio_ch_FileDispatcherImpl_preClose0(JNIEnv *env, jclass clazz, jobject fdo) { jint fd = fdval(env, fdo); if (preCloseFD >= 0) { @@ -141,7 +250,7 @@ Java_sun_nio_ch_FileDispatcher_preClose0(JNIEnv *env, jclass clazz, jobject fdo) } JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_closeIntFD(JNIEnv *env, jclass clazz, jint fd) +Java_sun_nio_ch_FileDispatcherImpl_closeIntFD(JNIEnv *env, jclass clazz, jint fd) { closeFileDescriptor(env, fd); } diff --git a/jdk/src/solaris/native/sun/nio/ch/SocketDispatcher.c b/jdk/src/solaris/native/sun/nio/ch/SocketDispatcher.c index 1524326b6b0..812ff4bedd8 100644 --- a/jdk/src/solaris/native/sun/nio/ch/SocketDispatcher.c +++ b/jdk/src/solaris/native/sun/nio/ch/SocketDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "jni_util.h" #include "jvm.h" #include "jlong.h" -#include "sun_nio_ch_FileDispatcher.h" /* this is a fake c file to make the build happy since there is no real SocketDispatcher.c file on Solaris but there is on windows. */ diff --git a/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c b/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c new file mode 100644 index 00000000000..649475946ab --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c @@ -0,0 +1,120 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" +#include "nio_util.h" + +#include +#include +#include +#include // Solaris 10 + +#include "sun_nio_ch_SolarisEventPort.h" + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_init(JNIEnv *env, jclass clazz) +{ +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_SolarisEventPort_portCreate + (JNIEnv* env, jclass clazz) +{ + int port = port_create(); + if (port == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_create"); + } + return (jint)port; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_portClose + (JNIEnv* env, jclass clazz, jint port) +{ + int res; + RESTARTABLE(close(port), res); +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_portAssociate + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events) +{ + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + + if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_associate"); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_portDissociate + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress) +{ + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + + if (port_dissociate((int)port, (int)source, object) == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_dissociate"); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_portSend(JNIEnv* env, jclass clazz, + jint port, jint events) +{ + if (port_send((int)port, (int)events, NULL) == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_send"); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_SolarisEventPort_portGet(JNIEnv* env, jclass clazz, + jint port, jlong eventAddress) +{ + int res; + port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress); + + RESTARTABLE(port_get((int)port, ev, NULL), res); + if (res == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_get"); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_SolarisEventPort_portGetn(JNIEnv* env, jclass clazz, + jint port, jlong arrayAddress, jint max) +{ + int res; + uint_t n = 1; + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress); + + RESTARTABLE(port_getn((int)port, list, (uint_t)max, &n, NULL), res); + if (res == -1) { + JNU_ThrowIOExceptionWithLastError(env, "port_getn"); + } + return (jint)n; +} diff --git a/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c new file mode 100644 index 00000000000..9c92cc2ad51 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "sun_nio_ch_UnixAsynchronousServerSocketChannelImpl.h" + +extern void Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv* env, + jclass c); + +extern jint Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv* env, + jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa); + +JNIEXPORT void JNICALL +Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env, + jclass c) +{ + Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(env, c); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env, + jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa) +{ + return Java_sun_nio_ch_ServerSocketChannelImpl_accept0(env, this, + ssfdo, newfdo, isaa); +} diff --git a/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c new file mode 100644 index 00000000000..461d97f405c --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c @@ -0,0 +1,53 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "net_util.h" +#include "jlong.h" +#include "sun_nio_ch_UnixAsynchronousSocketChannelImpl.h" +#include "nio_util.h" +#include "nio.h" + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect(JNIEnv *env, + jobject this, int fd) +{ + int error = 0; + int n = sizeof(error); + int result; + + result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n); + if (result < 0) { + JNU_ThrowIOExceptionWithLastError(env, "getsockopt"); + } else { + if (error) + handleSocketError(env, error); + } +} diff --git a/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c b/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c new file mode 100644 index 00000000000..0a169a94d89 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c @@ -0,0 +1,205 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include +#include + +#ifdef __solaris__ +#include +#endif + +#ifdef __linux__ +#include +#endif + +/* Definitions for GIO */ + +#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type" + +typedef void* gpointer; +typedef struct _GFile GFile; +typedef struct _GFileInfo GFileInfo; +typedef struct _GCancellable GCancellable; +typedef struct _GError GError; + +typedef enum { + G_FILE_QUERY_INFO_NONE = 0 +} GFileQueryInfoFlags; + +typedef void (*g_type_init_func)(void); +typedef void (*g_object_unref_func)(gpointer object); +typedef GFile* (*g_file_new_for_path_func)(const char* path); +typedef GFileInfo* (*g_file_query_info_func)(GFile *file, + const char *attributes, GFileQueryInfoFlags flags, + GCancellable *cancellable, GError **error); +typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info); + +static g_type_init_func g_type_init; +static g_object_unref_func g_object_unref; +static g_file_new_for_path_func g_file_new_for_path; +static g_file_query_info_func g_file_query_info; +static g_file_info_get_content_type_func g_file_info_get_content_type; + + +/* Definitions for GNOME VFS */ + +typedef int gboolean; + +typedef gboolean (*gnome_vfs_init_function)(void); +typedef const char* (*gnome_vfs_mime_type_from_name_function) + (const char* filename); + +static gnome_vfs_init_function gnome_vfs_init; +static gnome_vfs_mime_type_from_name_function gnome_vfs_mime_type_from_name; + + +#include "sun_nio_fs_GnomeFileTypeDetector.h" + + +JNIEXPORT jboolean JNICALL +Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio + (JNIEnv* env, jclass this) +{ + void* gio_handle; + + gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY); + if (gio_handle == NULL) { + gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY); + if (gio_handle == NULL) { + return JNI_FALSE; + } + } + + g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init"); + (*g_type_init)(); + + g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref"); + + g_file_new_for_path = + (g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path"); + + g_file_query_info = + (g_file_query_info_func)dlsym(gio_handle, "g_file_query_info"); + + g_file_info_get_content_type = (g_file_info_get_content_type_func) + dlsym(gio_handle, "g_file_info_get_content_type"); + + + if (g_type_init == NULL || + g_object_unref == NULL || + g_file_new_for_path == NULL || + g_file_query_info == NULL || + g_file_info_get_content_type == NULL) + { + dlclose(gio_handle); + return JNI_FALSE; + } + + (*g_type_init)(); + return JNI_TRUE; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio + (JNIEnv* env, jclass this, jlong pathAddress) +{ + char* path = (char*)jlong_to_ptr(pathAddress); + GFile* gfile; + GFileInfo* gfileinfo; + jbyteArray result = NULL; + + gfile = (*g_file_new_for_path)(path); + gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (gfileinfo != NULL) { + const char* mime = (*g_file_info_get_content_type)(gfileinfo); + if (mime != NULL) { + jsize len = strlen(mime); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime); + } + } + (*g_object_unref)(gfileinfo); + } + (*g_object_unref)(gfile); + + return result; +} + +JNIEXPORT jboolean JNICALL +Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs + (JNIEnv* env, jclass this) +{ + void* vfs_handle; + + vfs_handle = dlopen("libgnomevfs-2.so", RTLD_LAZY); + if (vfs_handle == NULL) { + vfs_handle = dlopen("libgnomevfs-2.so.0", RTLD_LAZY); + } + if (vfs_handle == NULL) { + return JNI_FALSE; + } + + gnome_vfs_init = (gnome_vfs_init_function)dlsym(vfs_handle, "gnome_vfs_init"); + gnome_vfs_mime_type_from_name = (gnome_vfs_mime_type_from_name_function) + dlsym(vfs_handle, "gnome_vfs_mime_type_from_name"); + + if (gnome_vfs_init == NULL || + gnome_vfs_mime_type_from_name == NULL) + { + dlclose(vfs_handle); + return JNI_FALSE; + } + + (*gnome_vfs_init)(); + return JNI_TRUE; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs + (JNIEnv* env, jclass this, jlong pathAddress) +{ + char* path = (char*)jlong_to_ptr(pathAddress); + const char* mime = (*gnome_vfs_mime_type_from_name)(path); + + if (mime == NULL) { + return NULL; + } else { + jbyteArray result; + jsize len = strlen(mime); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime); + } + return result; + } +} diff --git a/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c b/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c new file mode 100644 index 00000000000..8e4fa669611 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c @@ -0,0 +1,160 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include +#include +#include + +#include "sun_nio_fs_LinuxNativeDispatcher.h" + +typedef size_t fgetxattr_func(int fd, const char* name, void* value, size_t size); +typedef int fsetxattr_func(int fd, const char* name, void* value, size_t size, int flags); +typedef int fremovexattr_func(int fd, const char* name); +typedef int flistxattr_func(int fd, char* list, size_t size); + +fgetxattr_func* my_fgetxattr_func = NULL; +fsetxattr_func* my_fsetxattr_func = NULL; +fremovexattr_func* my_fremovexattr_func = NULL; +flistxattr_func* my_flistxattr_func = NULL; + +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_init(JNIEnv *env, jclass clazz) +{ + my_fgetxattr_func = (fgetxattr_func*)dlsym(RTLD_DEFAULT, "fgetxattr"); + my_fsetxattr_func = (fsetxattr_func*)dlsym(RTLD_DEFAULT, "fsetxattr"); + my_fremovexattr_func = (fremovexattr_func*)dlsym(RTLD_DEFAULT, "fremovexattr"); + my_flistxattr_func = (flistxattr_func*)dlsym(RTLD_DEFAULT, "flistxattr"); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress, jlong valueAddress, jint valueLen) +{ + size_t res = -1; + const char* name = jlong_to_ptr(nameAddress); + void* value = jlong_to_ptr(valueAddress); + + if (my_fgetxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*my_fgetxattr_func)(fd, name, value, valueLen); + } + if (res == (size_t)-1) + throwUnixException(env, errno); + return (jint)res; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress, jlong valueAddress, jint valueLen) +{ + int res = -1; + const char* name = jlong_to_ptr(nameAddress); + void* value = jlong_to_ptr(valueAddress); + + if (my_fsetxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*my_fsetxattr_func)(fd, name, value, valueLen, 0); + } + if (res == -1) + throwUnixException(env, errno); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress) +{ + int res = -1; + const char* name = jlong_to_ptr(nameAddress); + + if (my_fremovexattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*my_fremovexattr_func)(fd, name); + } + if (res == -1) + throwUnixException(env, errno); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz, + jint fd, jlong listAddress, jint size) +{ + size_t res = -1; + char* list = jlong_to_ptr(listAddress); + + if (my_flistxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*my_flistxattr_func)(fd, list, (size_t)size); + } + if (res == (size_t)-1) + throwUnixException(env, errno); + return (jint)res; +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong pathAddress, + jlong modeAddress) +{ + FILE* fp = NULL; + const char* path = (const char*)jlong_to_ptr(pathAddress); + const char* mode = (const char*)jlong_to_ptr(modeAddress); + + do { + fp = setmntent(path, mode); + } while (fp == NULL && errno == EINTR); + if (fp == NULL) { + throwUnixException(env, errno); + } + return ptr_to_jlong(fp); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxNativeDispatcher_endmntent(JNIEnv* env, jclass this, jlong stream) +{ + FILE* fp = jlong_to_ptr(stream); + /* FIXME - man page doesn't explain how errors are returned */ + endmntent(fp); +} diff --git a/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c b/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c new file mode 100644 index 00000000000..74a15407916 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c @@ -0,0 +1,195 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include +#include +#include +#include + +#include "sun_nio_fs_LinuxWatchService.h" + +/* inotify.h may not be available at build time */ +#ifdef __cplusplus +extern "C" { +#endif +struct inotify_event +{ + int wd; + uint32_t mask; + uint32_t cookie; + uint32_t len; + char name __flexarr; +}; +#ifdef __cplusplus +} +#endif + +typedef int inotify_init_func(void); +typedef int inotify_add_watch_func(int fd, const char* path, uint32_t mask); +typedef int inotify_rm_watch_func(int fd, uint32_t wd); + +inotify_init_func* my_inotify_init_func = NULL; +inotify_add_watch_func* my_inotify_add_watch_func = NULL; +inotify_rm_watch_func* my_inotify_rm_watch_func = NULL; + +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxWatchService_init(JNIEnv *env, jclass clazz) +{ + my_inotify_init_func = (inotify_init_func*) + dlsym(RTLD_DEFAULT, "inotify_init"); + my_inotify_add_watch_func = + (inotify_add_watch_func*) dlsym(RTLD_DEFAULT, "inotify_add_watch"); + my_inotify_rm_watch_func = + (inotify_rm_watch_func*) dlsym(RTLD_DEFAULT, "inotify_rm_watch"); + + if ((my_inotify_init_func == NULL) || (my_inotify_add_watch_func == NULL) || + (my_inotify_rm_watch_func == NULL)) { + JNU_ThrowInternalError(env, "unable to get address of inotify functions"); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxWatchService_eventSize(JNIEnv *env, jclass clazz) +{ + return (jint)sizeof(struct inotify_event); +} + +JNIEXPORT jintArray JNICALL +Java_sun_nio_fs_LinuxWatchService_eventOffsets(JNIEnv *env, jclass clazz) +{ + jintArray result = (*env)->NewIntArray(env, 5); + if (result != NULL) { + jint arr[5]; + arr[0] = (jint)offsetof(struct inotify_event, wd); + arr[1] = (jint)offsetof(struct inotify_event, mask); + arr[2] = (jint)offsetof(struct inotify_event, cookie); + arr[3] = (jint)offsetof(struct inotify_event, len); + arr[4] = (jint)offsetof(struct inotify_event, name); + (*env)->SetIntArrayRegion(env, result, 0, 5, arr); + } + return result; +} + + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxWatchService_inotifyInit + (JNIEnv* env, jclass clazz) +{ + int ifd = (*my_inotify_init_func)(); + if (ifd == -1) { + throwUnixException(env, errno); + } + return (jint)ifd; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch + (JNIEnv* env, jclass clazz, jint fd, jlong address, jint mask) +{ + int wfd = -1; + const char* path = (const char*)jlong_to_ptr(address); + + wfd = (*my_inotify_add_watch_func)((int)fd, path, mask); + if (wfd == -1) { + throwUnixException(env, errno); + } + return (jint)wfd; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch + (JNIEnv* env, jclass clazz, jint fd, jint wd) +{ + int err = (*my_inotify_rm_watch_func)((int)fd, (int)wd); + if (err == -1) + throwUnixException(env, errno); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxWatchService_configureBlocking + (JNIEnv* env, jclass clazz, jint fd, jboolean blocking) +{ + int flags = fcntl(fd, F_GETFL); + + if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + else if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_LinuxWatchService_socketpair + (JNIEnv* env, jclass clazz, jintArray sv) +{ + int sp[2]; + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) { + throwUnixException(env, errno); + } else { + jint res[2]; + res[0] = (jint)sp[0]; + res[1] = (jint)sp[1]; + (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]); + } + +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_LinuxWatchService_poll + (JNIEnv* env, jclass clazz, jint fd1, jint fd2) +{ + struct pollfd ufds[2]; + int n; + + ufds[0].fd = fd1; + ufds[0].events = POLLIN; + ufds[1].fd = fd2; + ufds[1].events = POLLIN; + + n = poll(&ufds[0], 2, -1); + if (n == -1) { + if (errno == EINTR) { + n = 0; + } else { + throwUnixException(env, errno); + } + } + return (jint)n; + + +} diff --git a/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c b/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c new file mode 100644 index 00000000000..a57009c67bc --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/SolarisNativeDispatcher.c @@ -0,0 +1,61 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include +#include + +#include "sun_nio_fs_SolarisNativeDispatcher.h" + +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) { +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd, + jint cmd, jint nentries, jlong address) +{ + void* aclbufp = jlong_to_ptr(address); + int n = -1; + + n = facl((int)fd, (int)cmd, (int)nentries, aclbufp); + if (n == -1) { + throwUnixException(env, errno); + } + return (jint)n; +} diff --git a/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c b/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c new file mode 100644 index 00000000000..776227f9955 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/SolarisWatchService.c @@ -0,0 +1,104 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jvm.h" +#include "jlong.h" + +#include +#include +#include +#include // Solaris 10 + +#include "sun_nio_fs_SolarisWatchService.h" + +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz) +{ +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_SolarisWatchService_portCreate + (JNIEnv* env, jclass clazz) +{ + int port = port_create(); + if (port == -1) { + throwUnixException(env, errno); + } + return (jint)port; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_SolarisWatchService_portAssociate + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events) +{ + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + + if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_SolarisWatchService_portDissociate + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress) +{ + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + + if (port_dissociate((int)port, (int)source, object) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz, + jint port, jint events) +{ + if (port_send((int)port, (int)events, NULL) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz, + jint port, jlong arrayAddress, jint max) +{ + uint_t n = 1; + port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress); + + if (port_getn((int)port, list, (uint_t)max, &n, NULL) == -1) { + throwUnixException(env, errno); + } + return (jint)n; +} diff --git a/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c b/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c new file mode 100644 index 00000000000..526ccba9668 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c @@ -0,0 +1,85 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" + +#include +#include + +#include "sun_nio_fs_UnixCopyFile.h" + +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +/** + * Transfer all bytes from src to dst via user-space buffers + */ +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixCopyFile_transfer + (JNIEnv* env, jclass this, jint dst, jint src, jlong cancelAddress) +{ + char buf[8192]; + volatile jint* cancel = (jint*)jlong_to_ptr(cancelAddress); + + for (;;) { + ssize_t n, pos, len; + RESTARTABLE(read((int)src, &buf, sizeof(buf)), n); + if (n <= 0) { + if (n < 0) + throwUnixException(env, errno); + return; + } + if (cancel != NULL && *cancel != 0) { + throwUnixException(env, ECANCELED); + return; + } + pos = 0; + len = n; + do { + char* bufp = buf; + bufp += pos; + RESTARTABLE(write((int)dst, bufp, len), n); + if (n == -1) { + throwUnixException(env, errno); + return; + } + pos += n; + len -= n; + } while (len > 0); + } +} diff --git a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c new file mode 100644 index 00000000000..13a1a3a215f --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c @@ -0,0 +1,1080 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __solaris__ +#include +#include +#include +#endif + +#ifdef __linux__ +#include +#include +#endif + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" + +#include "sun_nio_fs_UnixNativeDispatcher.h" + +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + +static jfieldID attrs_st_mode; +static jfieldID attrs_st_ino; +static jfieldID attrs_st_dev; +static jfieldID attrs_st_rdev; +static jfieldID attrs_st_nlink; +static jfieldID attrs_st_uid; +static jfieldID attrs_st_gid; +static jfieldID attrs_st_size; +static jfieldID attrs_st_atime; +static jfieldID attrs_st_mtime; +static jfieldID attrs_st_ctime; + +static jfieldID attrs_f_frsize; +static jfieldID attrs_f_blocks; +static jfieldID attrs_f_bfree; +static jfieldID attrs_f_bavail; + +static jfieldID entry_name; +static jfieldID entry_dir; +static jfieldID entry_fstype; +static jfieldID entry_options; +static jfieldID entry_dev; + +/** + * System calls that may not be available at build time. + */ +typedef int openat64_func(int, const char *, int, ...); +typedef int fstatat64_func(int, const char *, struct stat64 *, int); +typedef int unlinkat_func(int, const char*, int); +typedef int renameat_func(int, const char*, int, const char*); +typedef int futimesat_func(int, const char *, const struct timeval *); +typedef DIR* fdopendir_func(int); + +static openat64_func* my_openat64_func = NULL; +static fstatat64_func* my_fstatat64_func = NULL; +static unlinkat_func* my_unlinkat_func = NULL; +static renameat_func* my_renameat_func = NULL; +static futimesat_func* my_futimesat_func = NULL; +static fdopendir_func* my_fdopendir_func = NULL; + +/** + * fstatat missing from glibc on Linux. Temporary workaround + * for x86/x64. + */ +#if defined(__linux__) && defined(__i386) +#define FSTATAT64_SYSCALL_AVAILABLE +static int fstatat64_wrapper(int dfd, const char *path, + struct stat64 *statbuf, int flag) +{ + #ifndef __NR_fstatat64 + #define __NR_fstatat64 300 + #endif + return syscall(__NR_fstatat64, dfd, path, statbuf, flag); +} +#endif + +#if defined(__linux__) && defined(__x86_64__) +#define FSTATAT64_SYSCALL_AVAILABLE +static int fstatat64_wrapper(int dfd, const char *path, + struct stat64 *statbuf, int flag) +{ + #ifndef __NR_newfstatat + #define __NR_newfstatat 262 + #endif + return syscall(__NR_newfstatat, dfd, path, statbuf, flag); +} +#endif + +/** + * Call this to throw an internal UnixException when a system/library + * call fails + */ +static void throwUnixException(JNIEnv* env, int errnum) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException", + "(I)V", errnum); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +/** + * Initialize jfieldIDs + */ +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_initIDs(JNIEnv* env, jclass this) +{ + jclass clazz; + + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileAttributes"); + if (clazz == NULL) { + return; + } + attrs_st_mode = (*env)->GetFieldID(env, clazz, "st_mode", "I"); + attrs_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J"); + attrs_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J"); + attrs_st_rdev = (*env)->GetFieldID(env, clazz, "st_rdev", "J"); + attrs_st_nlink = (*env)->GetFieldID(env, clazz, "st_nlink", "I"); + attrs_st_uid = (*env)->GetFieldID(env, clazz, "st_uid", "I"); + attrs_st_gid = (*env)->GetFieldID(env, clazz, "st_gid", "I"); + attrs_st_size = (*env)->GetFieldID(env, clazz, "st_size", "J"); + attrs_st_atime = (*env)->GetFieldID(env, clazz, "st_atime", "J"); + attrs_st_mtime = (*env)->GetFieldID(env, clazz, "st_mtime", "J"); + attrs_st_ctime = (*env)->GetFieldID(env, clazz, "st_ctime", "J"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixFileStoreAttributes"); + if (clazz == NULL) { + return; + } + attrs_f_frsize = (*env)->GetFieldID(env, clazz, "f_frsize", "J"); + attrs_f_blocks = (*env)->GetFieldID(env, clazz, "f_blocks", "J"); + attrs_f_bfree = (*env)->GetFieldID(env, clazz, "f_bfree", "J"); + attrs_f_bavail = (*env)->GetFieldID(env, clazz, "f_bavail", "J"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); + if (clazz == NULL) { + return; + } + entry_name = (*env)->GetFieldID(env, clazz, "name", "[B"); + entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B"); + entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B"); + entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B"); + entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J"); + + /* system calls that might not be available at build time */ + +#if defined(__solaris__) && defined(_LP64) + /* Solaris 64-bit does not have openat64/fstatat64 */ + my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat"); + my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat"); +#else + my_openat64_func = (openat64_func*) dlsym(RTLD_DEFAULT, "openat64"); + my_fstatat64_func = (fstatat64_func*) dlsym(RTLD_DEFAULT, "fstatat64"); +#endif + my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat"); + my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat"); + my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat"); + my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir"); + +#if defined(FSTATAT64_SYSCALL_AVAILABLE) + /* fstatat64 missing from glibc */ + if (my_fstatat64_func == NULL) + my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper; +#endif +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getcwd(JNIEnv* env, jclass this) { + jbyteArray result = NULL; + char buf[PATH_MAX+1]; + + /* EINTR not listed as a possible error */ + char* cwd = getcwd(buf, sizeof(buf)); + if (cwd == NULL) { + throwUnixException(env, errno); + } else { + jsize len = (jsize)strlen(buf); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)buf); + } + } + return result; +} + +JNIEXPORT jbyteArray +Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error) +{ + char* msg; + jsize len; + jbyteArray bytes; + + msg = strerror((int)error); + len = strlen(msg); + bytes = (*env)->NewByteArray(env, len); + if (bytes != NULL) { + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg); + } + return bytes; +} + +JNIEXPORT jint +Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) { + + int res = -1; + + RESTARTABLE(dup((int)fd), res); + if (fd == -1) { + throwUnixException(env, errno); + } + return (jint)res; +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fopen0(JNIEnv* env, jclass this, + jlong pathAddress, jlong modeAddress) +{ + FILE* fp = NULL; + const char* path = (const char*)jlong_to_ptr(pathAddress); + const char* mode = (const char*)jlong_to_ptr(modeAddress); + + do { + fp = fopen(path, mode); + } while (fp == NULL && errno == EINTR); + + if (fp == NULL) { + throwUnixException(env, errno); + } + + return ptr_to_jlong(fp); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fclose(JNIEnv* env, jclass this, jlong stream) +{ + int res; + FILE* fp = jlong_to_ptr(stream); + + do { + res = fclose(fp); + } while (res == EOF && errno == EINTR); + if (res == EOF) { + throwUnixException(env, errno); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this, + jlong pathAddress, jint oflags, jint mode) +{ + jint fd; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(open64(path, (int)oflags, (mode_t)mode), fd); + if (fd == -1) { + throwUnixException(env, errno); + } + return fd; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_openat0(JNIEnv* env, jclass this, jint dfd, + jlong pathAddress, jint oflags, jint mode) +{ + jint fd; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + if (my_openat64_func == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return -1; + } + + RESTARTABLE((*my_openat64_func)(dfd, path, (int)oflags, (mode_t)mode), fd); + if (fd == -1) { + throwUnixException(env, errno); + } + return fd; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_close(JNIEnv* env, jclass this, jint fd) { + int err; + /* TDB - need to decide if EIO and other errors should cause exception */ + RESTARTABLE(close((int)fd), err); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_read(JNIEnv* env, jclass this, jint fd, + jlong address, jint nbytes) +{ + ssize_t n; + void* bufp = jlong_to_ptr(address); + RESTARTABLE(read((int)fd, bufp, (size_t)nbytes), n); + if (n == -1) { + throwUnixException(env, errno); + } + return (jint)n; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_write(JNIEnv* env, jclass this, jint fd, + jlong address, jint nbytes) +{ + ssize_t n; + void* bufp = jlong_to_ptr(address); + RESTARTABLE(write((int)fd, bufp, (size_t)nbytes), n); + if (n == -1) { + throwUnixException(env, errno); + } + return (jint)n; +} + +/** + * Copy stat64 members into sun.nio.fs.UnixFileAttributes + */ +static void prepAttributes(JNIEnv* env, struct stat64* buf, jobject attrs) { + (*env)->SetIntField(env, attrs, attrs_st_mode, (jint)buf->st_mode); + (*env)->SetLongField(env, attrs, attrs_st_ino, (jlong)buf->st_ino); + (*env)->SetLongField(env, attrs, attrs_st_dev, (jlong)buf->st_dev); + (*env)->SetLongField(env, attrs, attrs_st_rdev, (jlong)buf->st_rdev); + (*env)->SetIntField(env, attrs, attrs_st_nlink, (jint)buf->st_nlink); + (*env)->SetIntField(env, attrs, attrs_st_uid, (jint)buf->st_uid); + (*env)->SetIntField(env, attrs, attrs_st_gid, (jint)buf->st_gid); + (*env)->SetLongField(env, attrs, attrs_st_size, (jlong)buf->st_size); + (*env)->SetLongField(env, attrs, attrs_st_atime, (jlong)buf->st_atime * 1000); + (*env)->SetLongField(env, attrs, attrs_st_mtime, (jlong)buf->st_mtime * 1000); + (*env)->SetLongField(env, attrs, attrs_st_ctime, (jlong)buf->st_ctime * 1000); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_stat0(JNIEnv* env, jclass this, + jlong pathAddress, jobject attrs) +{ + int err; + struct stat64 buf; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(stat64(path, &buf), err); + if (err == -1) { + throwUnixException(env, errno); + } else { + prepAttributes(env, &buf, attrs); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_lstat0(JNIEnv* env, jclass this, + jlong pathAddress, jobject attrs) +{ + int err; + struct stat64 buf; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(lstat64(path, &buf), err); + if (err == -1) { + throwUnixException(env, errno); + } else { + prepAttributes(env, &buf, attrs); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fstat(JNIEnv* env, jclass this, jint fd, + jobject attrs) +{ + int err; + struct stat64 buf; + + RESTARTABLE(fstat64((int)fd, &buf), err); + if (err == -1) { + throwUnixException(env, errno); + } else { + prepAttributes(env, &buf, attrs); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fstatat0(JNIEnv* env, jclass this, jint dfd, + jlong pathAddress, jint flag, jobject attrs) +{ + int err; + struct stat64 buf; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + if (my_fstatat64_func == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return; + } + RESTARTABLE((*my_fstatat64_func)((int)dfd, path, &buf, (int)flag), err); + if (err == -1) { + throwUnixException(env, errno); + } else { + prepAttributes(env, &buf, attrs); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_chmod0(JNIEnv* env, jclass this, + jlong pathAddress, jint mode) +{ + int err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(chmod(path, (mode_t)mode), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fchmod(JNIEnv* env, jclass this, jint filedes, + jint mode) +{ + int err; + + RESTARTABLE(fchmod((int)filedes, (mode_t)mode), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_chown0(JNIEnv* env, jclass this, + jlong pathAddress, jint uid, jint gid) +{ + int err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(chown(path, (uid_t)uid, (gid_t)gid), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_lchown0(JNIEnv* env, jclass this, jlong pathAddress, jint uid, jint gid) +{ + int err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(lchown(path, (uid_t)uid, (gid_t)gid), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fchown(JNIEnv* env, jclass this, jint filedes, jint uid, jint gid) +{ + int err; + + RESTARTABLE(fchown(filedes, (uid_t)uid, (gid_t)gid), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_utimes0(JNIEnv* env, jclass this, + jlong pathAddress, jlong accessTime, jlong modificationTime) +{ + int err; + struct timeval times[2]; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + times[0].tv_sec = accessTime / 1000; + times[0].tv_usec = (accessTime % 1000) * 1000; + + times[1].tv_sec = modificationTime / 1000; + times[1].tv_usec = (modificationTime % 1000) * 1000; + + RESTARTABLE(utimes(path, ×[0]), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_futimes(JNIEnv* env, jclass this, jint filedes, + jlong accessTime, jlong modificationTime) +{ + struct timeval times[2]; + int err = 0; + + times[0].tv_sec = accessTime / 1000; + times[0].tv_usec = (accessTime % 1000) * 1000; + + times[1].tv_sec = modificationTime / 1000; + times[1].tv_usec = (modificationTime % 1000) * 1000; + + if (my_futimesat_func != NULL) { + RESTARTABLE((*my_futimesat_func)(filedes, NULL, ×[0]), err); + if (err == -1) { + throwUnixException(env, errno); + } + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this, + jlong pathAddress) +{ + DIR* dir; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + dir = opendir(path); + if (dir == NULL) { + throwUnixException(env, errno); + } + return ptr_to_jlong(dir); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd) { + DIR* dir; + + if (my_fdopendir_func == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return (jlong)-1; + } + + /* EINTR not listed as a possible error */ + dir = (*my_fdopendir_func)((int)dfd); + if (dir == NULL) { + throwUnixException(env, errno); + } + return ptr_to_jlong(dir); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) { + int err; + DIR* dirp = jlong_to_ptr(dir); + + RESTARTABLE(closedir(dirp), err); + if (errno == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_readdir(JNIEnv* env, jclass this, jlong value) { + char entry[sizeof(struct dirent64) + PATH_MAX + 1]; + struct dirent64* ptr = (struct dirent64*)&entry; + struct dirent64* result; + int res; + DIR* dirp = jlong_to_ptr(value); + + /* EINTR not listed as a possible error */ + /* TDB: reentrant version probably not required here */ + res = readdir64_r(dirp, ptr, &result); + if (res != 0) { + throwUnixException(env, res); + return NULL; + } else { + if (result == NULL) { + return NULL; + } else { + jsize len = strlen(ptr->d_name); + jbyteArray bytes = (*env)->NewByteArray(env, len); + if (bytes != NULL) { + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)(ptr->d_name)); + } + return bytes; + } + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_mkdir0(JNIEnv* env, jclass this, + jlong pathAddress, jint mode) +{ + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + if (mkdir(path, (mode_t)mode) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_rmdir0(JNIEnv* env, jclass this, + jlong pathAddress) +{ + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + if (rmdir(path) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_link0(JNIEnv* env, jclass this, + jlong existingAddress, jlong newAddress) +{ + int err; + const char* existing = (const char*)jlong_to_ptr(existingAddress); + const char* newname = (const char*)jlong_to_ptr(newAddress); + + RESTARTABLE(link(existing, newname), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_unlink0(JNIEnv* env, jclass this, + jlong pathAddress) +{ + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + if (unlink(path) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0(JNIEnv* env, jclass this, jint dfd, + jlong pathAddress, jint flags) +{ + const char* path = (const char*)jlong_to_ptr(pathAddress); + + if (my_unlinkat_func == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return; + } + + /* EINTR not listed as a possible error */ + if ((*my_unlinkat_func)((int)dfd, path, (int)flags) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_rename0(JNIEnv* env, jclass this, + jlong fromAddress, jlong toAddress) +{ + const char* from = (const char*)jlong_to_ptr(fromAddress); + const char* to = (const char*)jlong_to_ptr(toAddress); + + /* EINTR not listed as a possible error */ + if (rename(from, to) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_renameat0(JNIEnv* env, jclass this, + jint fromfd, jlong fromAddress, jint tofd, jlong toAddress) +{ + const char* from = (const char*)jlong_to_ptr(fromAddress); + const char* to = (const char*)jlong_to_ptr(toAddress); + + if (my_renameat_func == NULL) { + JNU_ThrowInternalError(env, "should not reach here"); + return; + } + + /* EINTR not listed as a possible error */ + if ((*my_renameat_func)((int)fromfd, from, (int)tofd, to) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_symlink0(JNIEnv* env, jclass this, + jlong targetAddress, jlong linkAddress) +{ + const char* target = (const char*)jlong_to_ptr(targetAddress); + const char* link = (const char*)jlong_to_ptr(linkAddress); + + /* EINTR not listed as a possible error */ + if (symlink(target, link) == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_readlink0(JNIEnv* env, jclass this, + jlong pathAddress) +{ + jbyteArray result = NULL; + char target[PATH_MAX+1]; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + int n = readlink(path, target, sizeof(target)); + if (n == -1) { + throwUnixException(env, errno); + } else { + jsize len; + if (n == sizeof(target)) { + n--; + } + target[n] = '\0'; + len = (jsize)strlen(target); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)target); + } + } + return result; +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_realpath0(JNIEnv* env, jclass this, + jlong pathAddress) +{ + jbyteArray result = NULL; + char resolved[PATH_MAX+1]; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + /* EINTR not listed as a possible error */ + if (realpath(path, resolved) == NULL) { + throwUnixException(env, errno); + } else { + jsize len = (jsize)strlen(resolved); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)resolved); + } + } + return result; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this, + jlong pathAddress, jint amode) +{ + int err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(access(path, (int)amode), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this, + jlong pathAddress, jobject attrs) +{ + int err; + struct statvfs64 buf; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + + RESTARTABLE(statvfs64(path, &buf), err); + if (err == -1) { + throwUnixException(env, errno); + } else { + (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize)); + (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks)); + (*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree)); + (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail)); + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_pathconf0(JNIEnv* env, jclass this, + jlong pathAddress, jint name) +{ + long err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + err = pathconf(path, (int)name); + if (err == -1) { + throwUnixException(env, errno); + } + return (jlong)err; +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_fpathconf(JNIEnv* env, jclass this, + jint fd, jint name) +{ + long err; + + err = fpathconf((int)fd, (int)name); + if (err == -1) { + throwUnixException(env, errno); + } + return (jlong)err; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_mknod0(JNIEnv* env, jclass this, + jlong pathAddress, jint mode, jlong dev) +{ + int err; + const char* path = (const char*)jlong_to_ptr(pathAddress); + + RESTARTABLE(mknod(path, (mode_t)mode, (dev_t)dev), err); + if (err == -1) { + throwUnixException(env, errno); + } +} + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getpwuid(JNIEnv* env, jclass this, jint uid) +{ + jbyteArray result = NULL; + int buflen; + + buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) { + throwUnixException(env, errno); + } else { + char* pwbuf = (char*)malloc(buflen); + if (pwbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); + } else { + struct passwd pwent; + struct passwd* p; + int res = 0; + +#ifdef __solaris__ + p = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen); +#else + res = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p); +#endif + + if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + throwUnixException(env, errno); + } else { + jsize len = strlen(p->pw_name); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name)); + } + } + free(pwbuf); + } + } + return result; +} + + +JNIEXPORT jbyteArray JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid) +{ + jbyteArray result = NULL; + int buflen; + + buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); + if (buflen == -1) { + throwUnixException(env, errno); + } else { + char* grbuf = (char*)malloc(buflen); + if (grbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); + } else { + struct group grent; + struct group* g; + int res = 0; + +#ifdef __solaris__ + g = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen); +#else + res = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g); +#endif + if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { + throwUnixException(env, errno); + } else { + jsize len = strlen(g->gr_name); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name)); + } + } + free(grbuf); + } + } + return result; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this, + jlong nameAddress) +{ + jint uid = -1; + int buflen; + char* pwbuf; + struct passwd pwent; + struct passwd* p; + int res = 0; + const char* name = (const char*)jlong_to_ptr(nameAddress); + + buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) { + throwUnixException(env, errno); + return -1; + } + pwbuf = (char*)malloc(buflen); + if (pwbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); + return -1; + } + +#ifdef __solaris__ + p = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen); +#else + res = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p); +#endif + + if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + /* not found or error */ + } else { + uid = p->pw_uid; + } + + free(pwbuf); + + return uid; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0(JNIEnv* env, jclass this, + jlong nameAddress) +{ + jint gid = -1; + int buflen; + char* grbuf; + struct group grent; + struct group* g; + int res = 0; + const char* name = (const char*)jlong_to_ptr(nameAddress); + + buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); + if (buflen == -1) { + throwUnixException(env, errno); + return -1; + } + grbuf = (char*)malloc(buflen); + if (grbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); + return -1; + } + +#ifdef __solaris__ + g = getgrnam_r(name, &grent, grbuf, (size_t)buflen); +#else + res = getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g); +#endif + + if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { + /* not found or error */ + } else { + gid = g->gr_gid; + } + free(grbuf); + + return gid; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getextmntent(JNIEnv* env, jclass this, + jlong value, jobject entry) +{ +#ifdef __solaris__ + struct extmnttab ent; +#else + struct mntent ent; + char buf[1024]; + int buflen = sizeof(buf); + struct mntent* m; +#endif + FILE* fp = jlong_to_ptr(value); + jsize len; + jbyteArray bytes; + char* name; + char* dir; + char* fstype; + char* options; + dev_t dev; + +#ifdef __solaris__ + if (getextmntent(fp, &ent, 0)) + return -1; + name = ent.mnt_special; + dir = ent.mnt_mountp; + fstype = ent.mnt_fstype; + options = ent.mnt_mntopts; + dev = makedev(ent.mnt_major, ent.mnt_minor); + if (dev == NODEV) { + /* possible bug on Solaris 8 and 9 */ + throwUnixException(env, errno); + return -1; + } +#else + m = getmntent_r(fp, &ent, (char*)&buf, buflen); + if (m == NULL) + return -1; + name = m->mnt_fsname; + dir = m->mnt_dir; + fstype = m->mnt_type; + options = m->mnt_opts; + dev = 0; +#endif + + len = strlen(name); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) + return -1; + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name); + (*env)->SetObjectField(env, entry, entry_name, bytes); + + len = strlen(dir); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) + return -1; + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir); + (*env)->SetObjectField(env, entry, entry_dir, bytes); + + len = strlen(fstype); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) + return -1; + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype); + (*env)->SetObjectField(env, entry, entry_fstype, bytes); + + len = strlen(options); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) + return -1; + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options); + (*env)->SetObjectField(env, entry, entry_options, bytes); + + if (dev != 0) + (*env)->SetLongField(env, entry, entry_dev, (jlong)dev); + + return 0; +} diff --git a/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c b/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c new file mode 100644 index 00000000000..182449e4ab5 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c @@ -0,0 +1,105 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include +#include +#include +#include + +/** + * Generates sun.nio.fs.SolarisConstants + */ + +static void out(char* s) { + printf("%s\n", s); +} + +static void emit(char* name, int value) { + printf(" static final int %s = %d;\n", name, value); +} + +static void emitX(char* name, int value) { + printf(" static final int %s = 0x%x;\n", name, value); +} + +#define DEF(X) emit(#X, X); +#define DEFX(X) emitX(#X, X); + +int main(int argc, const char* argv[]) { + out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT "); + out("package sun.nio.fs; "); + out("class SolarisConstants { "); + out(" private SolarisConstants() { } "); + + // extended attributes + DEFX(O_XATTR); + DEF(_PC_XATTR_ENABLED); + + // ACL configuration + DEF(_PC_ACL_ENABLED); + DEFX(_ACL_ACE_ENABLED); + + // ACL commands + DEFX(ACE_GETACL); + DEFX(ACE_SETACL); + + // ACL mask/flags/types + emitX("ACE_ACCESS_ALLOWED_ACE_TYPE", 0x0000); + emitX("ACE_ACCESS_DENIED_ACE_TYPE", 0x0001); + emitX("ACE_SYSTEM_AUDIT_ACE_TYPE", 0x0002); + emitX("ACE_SYSTEM_ALARM_ACE_TYPE", 0x0003); + emitX("ACE_READ_DATA", 0x00000001); + emitX("ACE_LIST_DIRECTORY", 0x00000001); + emitX("ACE_WRITE_DATA", 0x00000002); + emitX("ACE_ADD_FILE", 0x00000002); + emitX("ACE_APPEND_DATA", 0x00000004); + emitX("ACE_ADD_SUBDIRECTORY", 0x00000004); + emitX("ACE_READ_NAMED_ATTRS", 0x00000008); + emitX("ACE_WRITE_NAMED_ATTRS", 0x00000010); + emitX("ACE_EXECUTE", 0x00000020); + emitX("ACE_DELETE_CHILD", 0x00000040); + emitX("ACE_READ_ATTRIBUTES", 0x00000080); + emitX("ACE_WRITE_ATTRIBUTES", 0x00000100); + emitX("ACE_DELETE", 0x00010000); + emitX("ACE_READ_ACL", 0x00020000); + emitX("ACE_WRITE_ACL", 0x00040000); + emitX("ACE_WRITE_OWNER", 0x00080000); + emitX("ACE_SYNCHRONIZE", 0x00100000); + emitX("ACE_FILE_INHERIT_ACE", 0x0001); + emitX("ACE_DIRECTORY_INHERIT_ACE", 0x0002); + emitX("ACE_NO_PROPAGATE_INHERIT_ACE", 0x0004); + emitX("ACE_INHERIT_ONLY_ACE", 0x0008); + emitX("ACE_SUCCESSFUL_ACCESS_ACE_FLAG", 0x0010); + emitX("ACE_FAILED_ACCESS_ACE_FLAG", 0x0020); + emitX("ACE_IDENTIFIER_GROUP", 0x0040); + emitX("ACE_OWNER", 0x1000); + emitX("ACE_GROUP", 0x2000); + emitX("ACE_EVERYONE", 0x4000); + + out("} "); + return 0; +} diff --git a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c new file mode 100644 index 00000000000..c01f641a690 --- /dev/null +++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c @@ -0,0 +1,125 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include +#include +#include + +/** + * Generates sun.nio.fs.UnixConstants + */ + +static void out(char* s) { + printf("%s\n", s); +} + +static void emit(char* name, int value) { + printf(" static final int %s = %d;\n", name, value); +} + +static void emitX(char* name, int value) { + printf(" static final int %s = 0x%x;\n", name, value); +} + +#define DEF(X) emit(#X, X); +#define DEFX(X) emitX(#X, X); + +int main(int argc, const char* argv[]) { + out("// AUTOMATICALLY GENERATED FILE - DO NOT EDIT "); + out("package sun.nio.fs; "); + out("class UnixConstants { "); + out(" private UnixConstants() { } "); + + // open flags + DEF(O_RDONLY); + DEF(O_WRONLY); + DEF(O_RDWR); + DEFX(O_APPEND); + DEFX(O_CREAT); + DEFX(O_EXCL); + DEFX(O_TRUNC); + DEFX(O_SYNC); + DEFX(O_DSYNC); + DEFX(O_NOFOLLOW); + + // flags used with openat/unlinkat/etc. +#ifdef __solaris__ + DEFX(AT_SYMLINK_NOFOLLOW); + DEFX(AT_REMOVEDIR); +#endif +#ifdef __linux__ + emitX("AT_SYMLINK_NOFOLLOW", 0x100); // since 2.6.16 + emitX("AT_REMOVEDIR", 0x200); +#endif + + // mode masks + emitX("S_IAMB", + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH)); + DEF(S_IRUSR); + DEF(S_IWUSR); + DEF(S_IXUSR); + DEF(S_IRGRP); + DEF(S_IWGRP); + DEF(S_IXGRP); + DEF(S_IROTH); + DEF(S_IWOTH); + DEF(S_IXOTH); + DEFX(S_IFMT); + DEFX(S_IFREG); + DEFX(S_IFDIR); + DEFX(S_IFLNK); + DEFX(S_IFCHR); + DEFX(S_IFBLK); + DEFX(S_IFIFO); + + // access modes + DEF(R_OK); + DEF(W_OK); + DEF(X_OK); + DEF(F_OK); + + // errors + DEF(ENOENT); + DEF(EACCES); + DEF(EEXIST); + DEF(ENOTDIR); + DEF(EINVAL); + DEF(EXDEV); + DEF(EISDIR); + DEF(ENOTEMPTY); + DEF(ENOSPC); + DEF(EAGAIN); + DEF(ENOSYS); + DEF(ELOOP); + DEF(EROFS); + DEF(ENODATA); + DEF(ERANGE); + + out("} "); + + return 0; +} diff --git a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c index 6801dd94701..aee5cf9b080 100644 --- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c +++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c @@ -1641,6 +1641,13 @@ JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeSwapBuffers AWT_CHECK_HAVE_LOCK(); return XdbeSwapBuffers((Display*) jlong_to_ptr(display), (XdbeSwapInfo *) jlong_to_ptr(swap_info), num_windows); } +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XQueryKeymap +(JNIEnv *env, jclass clazz, jlong display, jlong vector) +{ + + AWT_CHECK_HAVE_LOCK(); + XQueryKeymap( (Display *) jlong_to_ptr(display), (char *) jlong_to_ptr(vector)); +} JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz, @@ -1911,19 +1918,30 @@ Java_sun_awt_X11_XlibWrapper_SetRectangularShape jint x1, jint y1, jint x2, jint y2, jobject region) { - XRectangle rects[256]; - XRectangle *pRect = rects; - int numrects; - AWT_CHECK_HAVE_LOCK(); - numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, - &pRect, 256); + // If all the params are zeros, the shape must be simply reset. + // Otherwise, the shape may be not rectangular. + if (region || x1 || x2 || y1 || y2) { + XRectangle rects[256]; + XRectangle *pRect = rects; - XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, + &pRect, 256); + + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeClip, 0, 0, pRect, numrects, ShapeSet, YXBanded); + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), ShapeBounding, 0, 0, pRect, numrects, ShapeSet, YXBanded); - if (pRect != rects) { - free(pRect); + if (pRect != rects) { + free(pRect); + } + } else { + // Reset the shape to a rectangular form. + XShapeCombineMask((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeClip, 0, 0, None, ShapeSet); + XShapeCombineMask((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeBounding, 0, 0, None, ShapeSet); } } diff --git a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java index 0f71eda29de..afbd170cc7f 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -68,13 +68,6 @@ public abstract class WComponentPeer extends WObjectPeer private static final Logger log = Logger.getLogger("sun.awt.windows.WComponentPeer"); private static final Logger shapeLog = Logger.getLogger("sun.awt.windows.shape.WComponentPeer"); - static { - wheelInit(); - } - - // Only actually does stuff if running on 95 - native static void wheelInit(); - // ComponentPeer implementation SurfaceData surfaceData; @@ -964,8 +957,12 @@ public abstract class WComponentPeer extends WObjectPeer + "; SHAPE: " + shape); } - setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(), - (shape.isRectangular() ? null : shape)); + if (shape != null) { + setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(), + (shape.isRectangular() ? null : shape)); + } else { + setRectangularShape(0, 0, 0, 0, null); + } } } diff --git a/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java b/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java index 33be7f8b4be..6cec225db97 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java +++ b/jdk/src/windows/classes/sun/awt/windows/WInputMethod.java @@ -548,11 +548,15 @@ public class WInputMethod extends InputMethodAdapter public void inquireCandidatePosition() { + Component source = getClientComponent(); + if (source == null) { + return; + } // This call should return immediately just to cause // InputMethodRequests.getTextLocation be called within // AWT Event thread. Otherwise, a potential deadlock // could happen. - java.awt.EventQueue.invokeLater(new Runnable() { + Runnable r = new Runnable() { public void run() { int x = 0; int y = 0; @@ -573,7 +577,9 @@ public class WInputMethod extends InputMethodAdapter openCandidateWindow(awtFocussedComponentPeer, x, y); } - }); + }; + WToolkit.postEvent(WToolkit.targetToAppContext(source), + new InvocationEvent(source, r)); } // java.awt.Toolkit#getNativeContainer() is not available diff --git a/jdk/src/windows/classes/sun/awt/windows/WRobotPeer.java b/jdk/src/windows/classes/sun/awt/windows/WRobotPeer.java index 1fb8ce2b51e..4cd3d2d3c26 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WRobotPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WRobotPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,8 @@ class WRobotPeer extends WObjectPeer implements RobotPeer } public native int getRGBPixelImpl(int x, int y); + public native int getNumberOfButtons(); + public int [] getRGBPixels(Rectangle bounds) { int pixelArray[] = new int[bounds.width*bounds.height]; getRGBPixels(bounds.x, bounds.y, bounds.width, bounds.height, pixelArray); diff --git a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java index 5ea8ca3acc5..55c1dde092d 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java @@ -80,6 +80,10 @@ public class WToolkit extends SunToolkit implements Runnable { // Dynamic Layout Resize client code setting protected boolean dynamicLayoutSetting = false; + //Is it allowed to generate events assigned to extra mouse buttons. + //Set to true by default. + private static boolean areExtraMouseButtonsEnabled = true; + /** * Initialize JNI field and method IDs */ @@ -249,6 +253,11 @@ public class WToolkit extends SunToolkit implements Runnable { // Enabled "live resizing" by default. It remains controlled // by the native system though. setDynamicLayout(true); + + areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); + //set system property if not yet assigned + System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); + setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled); } public void run() { @@ -961,4 +970,9 @@ public class WToolkit extends SunToolkit implements Runnable { return new WDesktopPeer(); } + public static native void setExtraMouseButtonsEnabledNative(boolean enable); + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return areExtraMouseButtonsEnabled; + } } diff --git a/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java new file mode 100644 index 00000000000..6187aa31878 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java @@ -0,0 +1,43 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.spi.AsynchronousChannelProvider; + +/** + * Creates this platform's default asynchronous channel provider + */ + +public class DefaultAsynchronousChannelProvider { + private DefaultAsynchronousChannelProvider() { } + + /** + * Returns the default AsynchronousChannelProvider. + */ + public static AsynchronousChannelProvider create() { + return new WindowsAsynchronousChannelProvider(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java similarity index 71% rename from jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java rename to jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java index 6928449664f..30390f7a61b 100644 --- a/jdk/src/windows/classes/sun/nio/ch/FileDispatcher.java +++ b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,13 +27,7 @@ package sun.nio.ch; import java.io.*; - -/** - * Allows different platforms to call different native methods - * for read and write operations. - */ - -class FileDispatcher extends NativeDispatcher +class FileDispatcherImpl extends FileDispatcher { static { @@ -74,6 +68,28 @@ class FileDispatcher extends NativeDispatcher return writev0(fd, address, len); } + int force(FileDescriptor fd, boolean metaData) throws IOException { + return force0(fd, metaData); + } + + int truncate(FileDescriptor fd, long size) throws IOException { + return truncate0(fd, size); + } + + long size(FileDescriptor fd) throws IOException { + return size0(fd); + } + + int lock(FileDescriptor fd, boolean blocking, long pos, long size, + boolean shared) throws IOException + { + return lock0(fd, blocking, pos, size, shared); + } + + void release(FileDescriptor fd, long pos, long size) throws IOException { + release0(fd, pos, size); + } + void close(FileDescriptor fd) throws IOException { close0(fd); } @@ -98,6 +114,20 @@ class FileDispatcher extends NativeDispatcher static native long writev0(FileDescriptor fd, long address, int len) throws IOException; + static native int force0(FileDescriptor fd, boolean metaData) + throws IOException; + + static native int truncate0(FileDescriptor fd, long size) + throws IOException; + + static native long size0(FileDescriptor fd) throws IOException; + + static native int lock0(FileDescriptor fd, boolean blocking, long pos, + long size, boolean shared) throws IOException; + + static native void release0(FileDescriptor fd, long pos, long size) + throws IOException; + static native void close0(FileDescriptor fd) throws IOException; static native void closeByHandle(long fd) throws IOException; diff --git a/jdk/src/windows/classes/sun/nio/ch/Iocp.java b/jdk/src/windows/classes/sun/nio/ch/Iocp.java new file mode 100644 index 00000000000..b4c2cdef61e --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/Iocp.java @@ -0,0 +1,437 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.io.Closeable; +import java.io.IOException; +import java.io.FileDescriptor; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import sun.misc.Unsafe; + +/** + * Windows implementation of AsynchronousChannelGroup encapsulating an I/O + * completion port. + */ + +class Iocp extends AsynchronousChannelGroupImpl { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final long INVALID_HANDLE_VALUE = -1L; + + // maps completion key to channel + private final ReadWriteLock keyToChannelLock = new ReentrantReadWriteLock(); + private final Map keyToChannel = + new HashMap(); + private int nextCompletionKey; + + // handle to completion port + private final long port; + + // true if port has been closed + private boolean closed; + + // the set of "stale" OVERLAPPED structures. These OVERLAPPED structures + // relate to I/O operations where the completion notification was not + // received in a timely manner after the channel is closed. + private final Set staleIoSet = new HashSet(); + + Iocp(AsynchronousChannelProvider provider, ThreadPool pool) + throws IOException + { + super(provider, pool); + this.port = + createIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, fixedThreadCount()); + this.nextCompletionKey = 1; + } + + Iocp start() { + startThreads(new EventHandlerTask()); + return this; + } + + /* + * Channels implements this interface support overlapped I/O and can be + * associated with a completion port. + */ + static interface OverlappedChannel extends Closeable { + /** + * Returns a reference to the pending I/O result. + */ + PendingFuture getByOverlapped(long overlapped); + } + + // release all resources + void implClose() { + synchronized (this) { + if (closed) + return; + closed = true; + } + close0(port); + synchronized (staleIoSet) { + for (Long ov: staleIoSet) { + unsafe.freeMemory(ov); + } + staleIoSet.clear(); + } + } + + @Override + boolean isEmpty() { + keyToChannelLock.writeLock().lock(); + try { + return keyToChannel.isEmpty(); + } finally { + keyToChannelLock.writeLock().unlock(); + } + } + + @Override + final Object attachForeignChannel(final Channel channel, FileDescriptor fdObj) + throws IOException + { + int key = associate(new OverlappedChannel() { + public PendingFuture getByOverlapped(long overlapped) { + return null; + } + public void close() throws IOException { + channel.close(); + } + }, 0L); + return Integer.valueOf(key); + } + + @Override + final void detachForeignChannel(Object key) { + disassociate((Integer)key); + } + + @Override + void closeAllChannels() { + /** + * On Windows the close operation will close the socket/file handle + * and then wait until all outstanding I/O operations have aborted. + * This is necessary as each channel's cache of OVERLAPPED structures + * can only be freed once all I/O operations have completed. As I/O + * completion requires a lookup of the keyToChannel then we must close + * the channels when not holding the write lock. + */ + final int MAX_BATCH_SIZE = 32; + OverlappedChannel channels[] = new OverlappedChannel[MAX_BATCH_SIZE]; + int count; + do { + // grab a batch of up to 32 channels + keyToChannelLock.writeLock().lock(); + count = 0; + try { + for (Integer key: keyToChannel.keySet()) { + channels[count++] = keyToChannel.get(key); + if (count >= MAX_BATCH_SIZE) + break; + } + } finally { + keyToChannelLock.writeLock().unlock(); + } + + // close them + for (int i=0; i 0); + } + + private void wakeup() { + try { + postQueuedCompletionStatus(port, 0); + } catch (IOException e) { + // should not happen + throw new AssertionError(e); + } + } + + @Override + void executeOnHandlerTask(Runnable task) { + synchronized (this) { + if (closed) + throw new RejectedExecutionException(); + offerTask(task); + wakeup(); + } + + } + + @Override + void shutdownHandlerTasks() { + // shutdown all handler threads + int nThreads = threadCount(); + while (nThreads-- > 0) { + wakeup(); + } + } + + /** + * Associate the given handle with this group + */ + int associate(OverlappedChannel ch, long handle) throws IOException { + keyToChannelLock.writeLock().lock(); + + // generate a completion key (if not shutdown) + int key; + try { + if (isShutdown()) + throw new ShutdownChannelGroupException(); + + // generate unique key + do { + key = nextCompletionKey++; + } while ((key == 0) || keyToChannel.containsKey(key)); + + // associate with I/O completion port + if (handle != 0L) + createIoCompletionPort(handle, port, key, 0); + + // setup mapping + keyToChannel.put(key, ch); + } finally { + keyToChannelLock.writeLock().unlock(); + } + return key; + } + + /** + * Disassociate channel from the group. + */ + void disassociate(int key) { + boolean checkForShutdown = false; + + keyToChannelLock.writeLock().lock(); + try { + keyToChannel.remove(key); + + // last key to be removed so check if group is shutdown + if (keyToChannel.isEmpty()) + checkForShutdown = true; + + } finally { + keyToChannelLock.writeLock().unlock(); + } + + // continue shutdown + if (checkForShutdown && isShutdown()) { + try { + shutdownNow(); + } catch (IOException ignore) { } + } + } + + /** + * Invoked when a channel associated with this port is closed before + * notifications for all outstanding I/O operations have been received. + */ + void makeStale(Long overlapped) { + synchronized (staleIoSet) { + staleIoSet.add(overlapped); + } + } + + /** + * Checks if the given OVERLAPPED is stale and if so, releases it. + */ + private void checkIfStale(long ov) { + synchronized (staleIoSet) { + boolean removed = staleIoSet.remove(ov); + if (removed) { + unsafe.freeMemory(ov); + } + } + } + + /** + * The handler for consuming the result of an asynchronous I/O operation. + */ + static interface ResultHandler { + /** + * Invoked if the I/O operation completes successfully. + */ + public void completed(int bytesTransferred); + + /** + * Invoked if the I/O operation fails. + */ + public void failed(int error, IOException ioe); + } + + // Creates IOException for the given I/O error. + private static IOException translateErrorToIOException(int error) { + String msg = getErrorMessage(error); + if (msg == null) + msg = "Unknown error: 0x0" + Integer.toHexString(error); + return new IOException(msg); + } + + /** + * Long-running task servicing system-wide or per-file completion port + */ + private class EventHandlerTask implements Runnable { + public void run() { + Invoker.GroupAndInvokeCount myGroupAndInvokeCount = + Invoker.getGroupAndInvokeCount(); + CompletionStatus ioResult = new CompletionStatus(); + boolean replaceMe = false; + + try { + for (;;) { + // reset invoke count + if (myGroupAndInvokeCount != null) + myGroupAndInvokeCount.resetInvokeCount(); + + // wait for I/O completion event + // A error here is fatal (thread will not be replaced) + replaceMe = false; + try { + getQueuedCompletionStatus(port, ioResult); + } catch (IOException x) { + // should not happen + x.printStackTrace(); + return; + } + + // handle wakeup to execute task or shutdown + if (ioResult.completionKey() == 0 && + ioResult.overlapped() == 0L) + { + Runnable task = pollTask(); + if (task == null) { + // shutdown request + return; + } + + // run task + // (if error/exception then replace thread) + replaceMe = true; + task.run(); + continue; + } + + // map key to channel + OverlappedChannel ch = null; + keyToChannelLock.readLock().lock(); + try { + ch = keyToChannel.get(ioResult.completionKey()); + if (ch == null) { + checkIfStale(ioResult.overlapped()); + continue; + } + } finally { + keyToChannelLock.readLock().unlock(); + } + + // lookup I/O request + PendingFuture result = ch.getByOverlapped(ioResult.overlapped()); + if (result == null) { + // we get here if the OVERLAPPED structure is associated + // with an I/O operation on a channel that was closed + // but the I/O operation event wasn't read in a timely + // manner. Alternatively, it may be related to a + // tryLock operation as the OVERLAPPED structures for + // these operations are not in the I/O cache. + checkIfStale(ioResult.overlapped()); + continue; + } + + // synchronize on result in case I/O completed immediately + // and was handled by initiator + synchronized (result) { + if (result.isDone()) { + continue; + } + // not handled by initiator + } + + // invoke I/O result handler + int error = ioResult.error(); + ResultHandler rh = (ResultHandler)result.getContext(); + replaceMe = true; // (if error/exception then replace thread) + if (error == 0) { + rh.completed(ioResult.bytesTransferred()); + } else { + rh.failed(error, translateErrorToIOException(error)); + } + } + } finally { + // last thread to exit when shutdown releases resources + int remaining = threadExit(this, replaceMe); + if (remaining == 0 && isShutdown()) { + implClose(); + } + } + } + } + + /** + * Container for data returned by GetQueuedCompletionStatus + */ + private static class CompletionStatus { + private int error; + private int bytesTransferred; + private int completionKey; + private long overlapped; + + private CompletionStatus() { } + int error() { return error; } + int bytesTransferred() { return bytesTransferred; } + int completionKey() { return completionKey; } + long overlapped() { return overlapped; } + } + + // -- native methods -- + + private static native void initIDs(); + + private static native long createIoCompletionPort(long handle, + long existingPort, int completionKey, int concurrency) throws IOException; + + private static native void close0(long handle); + + private static native void getQueuedCompletionStatus(long completionPort, + CompletionStatus status) throws IOException; + + private static native void postQueuedCompletionStatus(long completionPort, + int completionKey) throws IOException; + + private static native String getErrorMessage(int error); + + static { + Util.load(); + initIDs(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java b/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java new file mode 100644 index 00000000000..2e3d50385fc --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.*; +import sun.misc.Unsafe; + +/** + * Maintains a mapping of pending I/O requests (identified by the address of + * an OVERLAPPED structure) to Futures. + */ + +class PendingIoCache { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int addressSize = unsafe.addressSize(); + + private static int dependsArch(int value32, int value64) { + return (addressSize == 4) ? value32 : value64; + } + + /* + * typedef struct _OVERLAPPED { + * DWORD Internal; + * DWORD InternalHigh; + * DWORD Offset; + * DWORD OffsetHigh; + * HANDLE hEvent; + * } OVERLAPPED; + */ + private static final int SIZEOF_OVERLAPPED = dependsArch(20, 32); + + // set to true when closed + private boolean closed; + + // set to true when thread is waiting for all I/O operations to complete + private boolean closePending; + + // maps OVERLAPPED to PendingFuture + private final Map pendingIoMap = + new HashMap(); + + // per-channel cache of OVERLAPPED structures + private long[] overlappedCache = new long[4]; + private int overlappedCacheCount = 0; + + PendingIoCache() { + } + + long add(PendingFuture result) { + synchronized (this) { + if (closed) + throw new AssertionError("Should not get here"); + long ov; + if (overlappedCacheCount > 0) { + ov = overlappedCache[--overlappedCacheCount]; + } else { + ov = unsafe.allocateMemory(SIZEOF_OVERLAPPED); + } + pendingIoMap.put(ov, result); + return ov; + } + } + + @SuppressWarnings("unchecked") + PendingFuture remove(long overlapped) { + synchronized (this) { + PendingFuture res = pendingIoMap.remove(overlapped); + if (res != null) { + if (overlappedCacheCount < overlappedCache.length) { + overlappedCache[overlappedCacheCount++] = overlapped; + } else { + // cache full or channel closing + unsafe.freeMemory(overlapped); + } + // notify closing thread. + if (closePending) { + this.notifyAll(); + } + } + return res; + } + } + + void close() { + synchronized (this) { + if (closed) + return; + + // handle the case that where there are I/O operations that have + // not completed. + if (!pendingIoMap.isEmpty()) + clearPendingIoMap(); + + // release memory for any cached OVERLAPPED structures + while (overlappedCacheCount > 0) { + unsafe.freeMemory( overlappedCache[--overlappedCacheCount] ); + } + + // done + closed = true; + } + } + + private void clearPendingIoMap() { + assert Thread.holdsLock(this); + + // wait up to 50ms for the I/O operations to complete + closePending = true; + try { + this.wait(50); + } catch (InterruptedException x) { } + closePending = false; + if (pendingIoMap.isEmpty()) + return; + + // cause all pending I/O operations to fail + // simulate the failure of all pending I/O operations. + for (Long ov: pendingIoMap.keySet()) { + PendingFuture result = pendingIoMap.get(ov); + assert !result.isDone(); + + // make I/O port aware of the stale OVERLAPPED structure + Iocp iocp = (Iocp)((Groupable)result.channel()).group(); + iocp.makeStale(ov); + + // execute a task that invokes the result handler's failed method + final Iocp.ResultHandler rh = (Iocp.ResultHandler)result.getContext(); + Runnable task = new Runnable() { + public void run() { + rh.failed(-1, new AsynchronousCloseException()); + } + }; + iocp.executeOnPooledThread(task); + } + pendingIoMap.clear(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java new file mode 100644 index 00000000000..435b5297b2e --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousChannelProvider.java @@ -0,0 +1,101 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.net.ProtocolFamily; +import java.io.IOException; + +public class WindowsAsynchronousChannelProvider + extends AsynchronousChannelProvider +{ + private static volatile Iocp defaultIocp; + + public WindowsAsynchronousChannelProvider() { + // nothing to do + } + + private Iocp defaultIocp() throws IOException { + if (defaultIocp == null) { + synchronized (WindowsAsynchronousChannelProvider.class) { + if (defaultIocp == null) { + // default thread pool may be shared with AsynchronousFileChannels + defaultIocp = new Iocp(this, ThreadPool.getDefault()).start(); + } + } + } + return defaultIocp; + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory) + throws IOException + { + return new Iocp(this, ThreadPool.create(nThreads, factory)).start(); + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) + throws IOException + { + return new Iocp(this, ThreadPool.wrap(executor, initialSize)).start(); + } + + private Iocp toIocp(AsynchronousChannelGroup group) throws IOException { + if (group == null) { + return defaultIocp(); + } else { + if (!(group instanceof Iocp)) + throw new IllegalChannelGroupException(); + return (Iocp)group; + } + } + + @Override + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new WindowsAsynchronousServerSocketChannelImpl(toIocp(group)); + } + + @Override + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) + throws IOException + { + return new WindowsAsynchronousSocketChannelImpl(toIocp(group)); + } + + @Override + public AsynchronousDatagramChannel openAsynchronousDatagramChannel(ProtocolFamily family, + AsynchronousChannelGroup group) + throws IOException + { + return new SimpleAsynchronousDatagramChannelImpl(family, toIocp(group)); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java new file mode 100644 index 00000000000..ef668648d67 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -0,0 +1,741 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.nio.BufferOverflowException; +import java.io.IOException; +import java.io.FileDescriptor; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; + +/** + * Windows implementation of AsynchronousFileChannel using overlapped I/O. + */ + +public class WindowsAsynchronousFileChannelImpl + extends AsynchronousFileChannelImpl + implements Iocp.OverlappedChannel, Groupable +{ + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + // error when EOF is detected asynchronously. + private static final int ERROR_HANDLE_EOF = 38; + + // Lazy initialization of default I/O completion port + private static class DefaultIocpHolder { + static final Iocp defaultIocp = defaultIocp(); + private static Iocp defaultIocp() { + try { + return new Iocp(null, ThreadPool.createDefault()).start(); + } catch (IOException ioe) { + InternalError e = new InternalError(); + e.initCause(ioe); + throw e; + } + } + } + + // Used for force/truncate/size methods + private static final FileDispatcher nd = new FileDispatcherImpl(); + + // The handle is extracted for use in native methods invoked from this class. + private final long handle; + + // The key that identifies the channel's association with the I/O port + private final int completionKey; + + // I/O completion port (group) + private final Iocp iocp; + + private final boolean isDefaultIocp; + + // Caches OVERLAPPED structure for each outstanding I/O operation + private final PendingIoCache ioCache; + + + private WindowsAsynchronousFileChannelImpl(FileDescriptor fdObj, + boolean reading, + boolean writing, + Iocp iocp, + boolean isDefaultIocp) + throws IOException + { + super(fdObj, reading, writing, iocp.executor()); + this.handle = fdAccess.getHandle(fdObj); + this.iocp = iocp; + this.isDefaultIocp = isDefaultIocp; + this.ioCache = new PendingIoCache(); + this.completionKey = iocp.associate(this, handle); + } + + public static AsynchronousFileChannel open(FileDescriptor fdo, + boolean reading, + boolean writing, + ThreadPool pool) + throws IOException + { + Iocp iocp; + boolean isDefaultIocp; + if (pool == null) { + iocp = DefaultIocpHolder.defaultIocp; + isDefaultIocp = true; + } else { + iocp = new Iocp(null, pool).start(); + isDefaultIocp = false; + } + try { + return new + WindowsAsynchronousFileChannelImpl(fdo, reading, writing, iocp, isDefaultIocp); + } catch (IOException x) { + // error binding to port so need to close it (if created for this channel) + if (!isDefaultIocp) + iocp.implClose(); + throw x; + } + } + + @Override + public PendingFuture getByOverlapped(long overlapped) { + return ioCache.remove(overlapped); + } + + @Override + public void close() throws IOException { + closeLock.writeLock().lock(); + try { + if (closed) + return; // already closed + closed = true; + } finally { + closeLock.writeLock().unlock(); + } + + // invalidate all locks held for this channel + invalidateAllLocks(); + + // close the file + close0(handle); + + // waits until all I/O operations have completed + ioCache.close(); + + // disassociate from port and shutdown thread pool if not default + iocp.disassociate(completionKey); + if (!isDefaultIocp) + iocp.shutdown(); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + /** + * Translates Throwable to IOException + */ + private static IOException toIOException(Throwable x) { + if (x instanceof IOException) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + return (IOException)x; + } + return new IOException(x); + } + + @Override + public long size() throws IOException { + try { + begin(); + return nd.size(fdObj); + } finally { + end(); + } + } + + @Override + public AsynchronousFileChannel truncate(long size) throws IOException { + if (size < 0) + throw new IllegalArgumentException("Negative size"); + if (!writing) + throw new NonWritableChannelException(); + try { + begin(); + if (size > nd.size(fdObj)) + return this; + nd.truncate(fdObj, size); + } finally { + end(); + } + return this; + } + + @Override + public void force(boolean metaData) throws IOException { + try { + begin(); + nd.force(fdObj, metaData); + } finally { + end(); + } + } + + // -- file locking -- + + /** + * Task that initiates locking operation and handles completion result. + */ + private class LockTask implements Runnable, Iocp.ResultHandler { + private final long position; + private final FileLockImpl fli; + private final PendingFuture result; + + LockTask(long position, + FileLockImpl fli, + PendingFuture result) + { + this.position = position; + this.fli = fli; + this.result = result; + } + + @Override + public void run() { + long overlapped = 0L; + try { + begin(); + + // allocate OVERLAPPED structure + overlapped = ioCache.add(result); + + // synchronize on result to avoid race with handler thread + // when lock is acquired immediately. + synchronized (result) { + int n = lockFile(handle, position, fli.size(), fli.isShared(), + overlapped); + if (n == IOStatus.UNAVAILABLE) { + // I/O is pending + return; + } + // acquired lock immediately + result.setResult(fli); + } + + } catch (Throwable x) { + // lock failed or channel closed + removeFromFileLockTable(fli); + if (overlapped != 0L) + ioCache.remove(overlapped); + result.setFailure(toIOException(x)); + } finally { + end(); + } + + // invoke completion handler + Invoker.invoke(result.handler(), result); + } + + @Override + public void completed(int bytesTransferred) { + // release waiters and invoke completion handler + result.setResult(fli); + Invoker.invoke(result.handler(), result); + } + + @Override + public void failed(int error, IOException x) { + // lock not acquired so remove from lock table + removeFromFileLockTable(fli); + + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result.handler(), result); + } + } + + @Override + public Future lock(long position, + long size, + boolean shared, + A attachment, + CompletionHandler handler) + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + // create Future and task that will be invoked to acquire lock + PendingFuture result = + new PendingFuture(this, handler, attachment); + LockTask lockTask = new LockTask(position, fli, result); + result.setContext(lockTask); + + // initiate I/O (can only be done from thread in thread pool) + try { + Invoker.invokeOnThreadInThreadPool(this, lockTask); + } catch (ShutdownChannelGroupException e) { + // rollback + removeFromFileLockTable(fli); + throw e; + } + return result; + } + + static final int NO_LOCK = -1; // Failed to lock + static final int LOCKED = 0; // Obtained requested lock + + @Override + public FileLock tryLock(long position, long size, boolean shared) + throws IOException + { + if (shared && !reading) + throw new NonReadableChannelException(); + if (!shared && !writing) + throw new NonWritableChannelException(); + + // add to lock table + final FileLockImpl fli = addToFileLockTable(position, size, shared); + if (fli == null) + throw new ClosedChannelException(); + + boolean gotLock = false; + try { + begin(); + // try to acquire the lock + int res = nd.lock(fdObj, false, position, size, shared); + if (res == NO_LOCK) + return null; + gotLock = true; + return fli; + } finally { + if (!gotLock) + removeFromFileLockTable(fli); + end(); + } + } + + // invoke by FileFileImpl to release lock + @Override + void release(FileLockImpl fli) throws IOException { + try { + begin(); + nd.release(fdObj, fli.position(), fli.size()); + removeFromFileLockTable(fli); + } finally { + end(); + } + } + + /** + * Task that initiates read operation and handles completion result. + */ + private class ReadTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer dst; + private final int pos, rem; // buffer position/remaining + private final long position; // file position + private final PendingFuture result; + + // set to dst if direct; otherwise set to substituted direct buffer + private volatile ByteBuffer buf; + + ReadTask(ByteBuffer dst, + int pos, + int rem, + long position, + PendingFuture result) + { + this.dst = dst; + this.pos = pos; + this.rem = rem; + this.position = position; + this.result = result; + } + + void releaseBufferIfSubstituted() { + if (buf != dst) + Util.releaseTemporaryDirectBuffer(buf); + } + + void updatePosition(int bytesTransferred) { + // if the I/O succeeded then adjust buffer position + if (bytesTransferred > 0) { + if (buf == dst) { + try { + dst.position(pos + bytesTransferred); + } catch (IllegalArgumentException x) { + // someone has changed the position; ignore + } + } else { + // had to substitute direct buffer + buf.position(bytesTransferred).flip(); + try { + dst.put(buf); + } catch (BufferOverflowException x) { + // someone has changed the position; ignore + } + } + } + } + + @Override + public void run() { + int n = -1; + long overlapped = 0L; + long address; + + // Substitute a native buffer if not direct + if (dst instanceof DirectBuffer) { + buf = dst; + address = ((DirectBuffer)dst).address() + pos; + } else { + buf = Util.getTemporaryDirectBuffer(rem); + address = ((DirectBuffer)buf).address(); + } + + try { + begin(); + + // allocate OVERLAPPED + overlapped = ioCache.add(result); + + // synchronize on result to allow this thread handle the case + // where the read completes immediately. + synchronized (result) { + n = readFile(handle, address, rem, position, overlapped); + if (n == IOStatus.UNAVAILABLE) { + // I/O is pending + return; + } + // read completed immediately: + // 1. update buffer position + // 2. release waiters + updatePosition(n); + result.setResult(n); + } + } catch (Throwable x) { + // failed to initiate read + result.setFailure(toIOException(x)); + } finally { + end(); + } + + // read failed or EOF so completion port will not be notified + if (n < 0 && overlapped != 0L) { + ioCache.remove(overlapped); + } + + // return direct buffer to cache if substituted + releaseBufferIfSubstituted(); + + // invoke completion handler + Invoker.invoke(result.handler(), result); + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred) { + updatePosition(bytesTransferred); + + // return direct buffer to cache if substituted + releaseBufferIfSubstituted(); + + // release waiters and invoke completion handler + result.setResult(bytesTransferred); + Invoker.invoke(result.handler(), result); + } + + @Override + public void failed(int error, IOException x) { + // if EOF detected asynchronously then it is reported as error + if (error == ERROR_HANDLE_EOF) { + completed(-1); + } else { + // return direct buffer to cache if substituted + releaseBufferIfSubstituted(); + + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result.handler(), result); + } + } + } + + @Override + public Future read(ByteBuffer dst, + long position, + A attachment, + CompletionHandler handler) + { + if (!reading) + throw new NonReadableChannelException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + + // check if channel is closed + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + int pos = dst.position(); + int lim = dst.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + // no space remaining + if (rem == 0) { + CompletedFuture result = + CompletedFuture.withResult(this, 0, attachment); + Invoker.invoke(handler, result); + return result; + } + + // create Future and task that initiates read + PendingFuture result = + new PendingFuture(this, handler, attachment); + ReadTask readTask = new ReadTask(dst, pos, rem, position, result); + result.setContext(readTask); + + // initiate I/O (can only be done from thread in thread pool) + Invoker.invokeOnThreadInThreadPool(this, readTask); + return result; + } + + /** + * Task that initiates write operation and handles completion result. + */ + private class WriteTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer src; + private final int pos, rem; // buffer position/remaining + private final long position; // file position + private final PendingFuture result; + + // set to src if direct; otherwise set to substituted direct buffer + private volatile ByteBuffer buf; + + WriteTask(ByteBuffer src, + int pos, + int rem, + long position, + PendingFuture result) + { + this.src = src; + this.pos = pos; + this.rem = rem; + this.position = position; + this.result = result; + } + + void releaseBufferIfSubstituted() { + if (buf != src) + Util.releaseTemporaryDirectBuffer(buf); + } + + void updatePosition(int bytesTransferred) { + // if the I/O succeeded then adjust buffer position + if (bytesTransferred > 0) { + try { + src.position(pos + bytesTransferred); + } catch (IllegalArgumentException x) { + // someone has changed the position + } + } + } + + @Override + public void run() { + int n = -1; + long overlapped = 0L; + long address; + + // Substitute a native buffer if not direct + if (src instanceof DirectBuffer) { + buf = src; + address = ((DirectBuffer)src).address() + pos; + } else { + buf = Util.getTemporaryDirectBuffer(rem); + buf.put(src); + buf.flip(); + // temporarily restore position as we don't know how many bytes + // will be written + src.position(pos); + address = ((DirectBuffer)buf).address(); + } + + try { + begin(); + + // allocate an OVERLAPPED structure + overlapped = ioCache.add(result); + + // synchronize on result to allow this thread handle the case + // where the read completes immediately. + synchronized (result) { + n = writeFile(handle, address, rem, position, overlapped); + if (n == IOStatus.UNAVAILABLE) { + // I/O is pending + return; + } + // read completed immediately: + // 1. update buffer position + // 2. release waiters + updatePosition(n); + result.setResult(n); + } + } catch (Throwable x) { + // failed to initiate read: + result.setFailure(toIOException(x)); + + // release resources + if (overlapped != 0L) + ioCache.remove(overlapped); + releaseBufferIfSubstituted(); + + } finally { + end(); + } + + // invoke completion handler + Invoker.invoke(result.handler(), result); + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred) { + updatePosition(bytesTransferred); + + // return direct buffer to cache if substituted + releaseBufferIfSubstituted(); + + // release waiters and invoke completion handler + result.setResult(bytesTransferred); + Invoker.invoke(result.handler(), result); + } + + @Override + public void failed(int error, IOException x) { + // return direct buffer to cache if substituted + releaseBufferIfSubstituted(); + + // release waiters and invoker completion handler + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result.handler(), result); + } + } + + @Override + public Future write(ByteBuffer src, + long position, + A attachment, + CompletionHandler handler) + { + if (!writing) + throw new NonWritableChannelException(); + if (position < 0) + throw new IllegalArgumentException("Negative position"); + + // check if channel is closed + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + int pos = src.position(); + int lim = src.limit(); + assert (pos <= lim); + int rem = (pos <= lim ? lim - pos : 0); + + // nothing to write + if (rem == 0) { + CompletedFuture result = + CompletedFuture.withResult(this, 0, attachment); + Invoker.invoke(handler, result); + return result; + } + + // create Future and task to initiate write + PendingFuture result = + new PendingFuture(this, handler, attachment); + WriteTask writeTask = new WriteTask(src, pos, rem, position, result); + result.setContext(writeTask); + + // initiate I/O (can only be done from thread in thread pool) + Invoker.invokeOnThreadInThreadPool(this, writeTask); + return result; + } + + // -- Native methods -- + + private static native int readFile(long handle, long address, int len, + long offset, long overlapped) throws IOException; + + private static native int writeFile(long handle, long address, int len, + long offset, long overlapped) throws IOException; + + private static native int lockFile(long handle, long position, long size, + boolean shared, long overlapped) throws IOException; + + private static native void close0(long handle); + + static { + Util.load(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java new file mode 100644 index 00000000000..8efb10d75e6 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java @@ -0,0 +1,367 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.net.InetSocketAddress; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.io.IOException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.misc.Unsafe; + +/** + * Windows implementation of AsynchronousServerSocketChannel using overlapped I/O. + */ + +class WindowsAsynchronousServerSocketChannelImpl + extends AsynchronousServerSocketChannelImpl implements Iocp.OverlappedChannel +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // 2 * (sizeof(SOCKET_ADDRESS) + 16) + private static final int DATA_BUFFER_SIZE = 88; + + private final long handle; + private final int completionKey; + private final Iocp iocp; + + // typically there will be zero, or one I/O operations pending. In rare + // cases there may be more. These rare cases arise when a sequence of accept + // operations complete immediately and handled by the initiating thread. + // The corresponding OVERLAPPED cannot be reused/released until the completion + // event has been posted. + private final PendingIoCache ioCache; + + // the data buffer to receive the local/remote socket address + private final long dataBuffer; + + // flag to indicate that an accept operation is outstanding + private AtomicBoolean accepting = new AtomicBoolean(); + + + WindowsAsynchronousServerSocketChannelImpl(Iocp iocp) throws IOException { + super(iocp); + + // associate socket with given completion port + long h = IOUtil.fdVal(fd); + int key; + try { + key = iocp.associate(this, h); + } catch (IOException x) { + closesocket0(h); // prevent leak + throw x; + } + + this.handle = h; + this.completionKey = key; + this.iocp = iocp; + this.ioCache = new PendingIoCache(); + this.dataBuffer = unsafe.allocateMemory(DATA_BUFFER_SIZE); + } + + @Override + public PendingFuture getByOverlapped(long overlapped) { + return ioCache.remove(overlapped); + } + + @Override + void implClose() throws IOException { + // close socket (which may cause outstanding accept to be aborted). + closesocket0(handle); + + // waits until the accept operations have completed + ioCache.close(); + + // finally disassociate from the completion port + iocp.disassociate(completionKey); + + // release other resources + unsafe.freeMemory(dataBuffer); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + /** + * Task to initiate accept operation and to handle result. + */ + private class AcceptTask implements Runnable, Iocp.ResultHandler { + private final WindowsAsynchronousSocketChannelImpl channel; + private final AccessControlContext acc; + private final PendingFuture result; + + AcceptTask(WindowsAsynchronousSocketChannelImpl channel, + AccessControlContext acc, + PendingFuture result) + { + this.channel = channel; + this.acc = acc; + this.result = result; + } + + void enableAccept() { + accepting.set(false); + } + + void closeChildChannel() { + try { + channel.close(); + } catch (IOException ignore) { } + } + + // caller must have acquired read lock for the listener and child channel. + void finishAccept() throws IOException { + /** + * Set local/remote addresses. This is currently very inefficient + * in that it requires 2 calls to getsockname and 2 calls to getpeername. + * (should change this to use GetAcceptExSockaddrs) + */ + updateAcceptContext(handle, channel.handle()); + + InetSocketAddress local = Net.localAddress(channel.fd); + final InetSocketAddress remote = Net.remoteAddress(channel.fd); + channel.setConnected(local, remote); + + // permission check (in context of initiating thread) + if (acc != null) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + SecurityManager sm = System.getSecurityManager(); + sm.checkAccept(remote.getAddress().getHostAddress(), + remote.getPort()); + return null; + } + }, acc); + } + } + + /** + * Initiates the accept operation. + */ + @Override + public void run() { + long overlapped = 0L; + + try { + // begin usage of listener socket + begin(); + try { + // begin usage of child socket (as it is registered with + // completion port and so may be closed in the event that + // the group is forcefully closed). + channel.begin(); + + synchronized (result) { + overlapped = ioCache.add(result); + + int n = accept0(handle, channel.handle(), overlapped, dataBuffer); + if (n == IOStatus.UNAVAILABLE) { + return; + } + + // connection accepted immediately + finishAccept(); + + // allow another accept before the result is set + enableAccept(); + result.setResult(channel); + } + } finally { + // end usage on child socket + channel.end(); + } + } catch (Throwable x) { + // failed to initiate accept so release resources + if (overlapped != 0L) + ioCache.remove(overlapped); + closeChildChannel(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + enableAccept(); + result.setFailure(x); + } finally { + // end of usage of listener socket + end(); + } + + // accept completed immediately but may not have executed on + // initiating thread in which case the operation may have been + // cancelled. + if (result.isCancelled()) { + closeChildChannel(); + } + + // invoke completion handler + Invoker.invokeIndirectly(result.handler(), result); + } + + /** + * Executed when the I/O has completed + */ + @Override + public void completed(int bytesTransferred) { + try { + // connection accept after group has shutdown + if (iocp.isShutdown()) { + throw new IOException(new ShutdownChannelGroupException()); + } + + // finish the accept + try { + begin(); + try { + channel.begin(); + finishAccept(); + } finally { + channel.end(); + } + } finally { + end(); + } + + // allow another accept before the result is set + enableAccept(); + result.setResult(channel); + } catch (Throwable x) { + enableAccept(); + closeChildChannel(); + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + if (!(x instanceof IOException) && !(x instanceof SecurityException)) + x = new IOException(x); + result.setFailure(x); + } + + // if an async cancel has already cancelled the operation then + // close the new channel so as to free resources + if (result.isCancelled()) { + closeChildChannel(); + } + + // invoke handler (but not directly) + Invoker.invokeIndirectly(result.handler(), result); + } + + @Override + public void failed(int error, IOException x) { + enableAccept(); + closeChildChannel(); + + // release waiters + if (isOpen()) { + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invokeIndirectly(result.handler(), result); + } + } + + @Override + public Future accept(A attachment, + final CompletionHandler handler) + { + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invokeIndirectly(handler, result); + return result; + } + if (isAcceptKilled()) + throw new RuntimeException("Accept not allowed due to cancellation"); + + // ensure channel is bound to local address + if (localAddress == null) + throw new NotYetBoundException(); + + // create the socket that will be accepted. The creation of the socket + // is enclosed by a begin/end for the listener socket to ensure that + // we check that the listener is open and also to prevent the I/O + // port from being closed as the new socket is registered. + WindowsAsynchronousSocketChannelImpl ch = null; + IOException ioe = null; + try { + begin(); + ch = new WindowsAsynchronousSocketChannelImpl(iocp, false); + } catch (IOException x) { + ioe = x; + } finally { + end(); + } + if (ioe != null) { + CompletedFuture result = + CompletedFuture.withFailure(this, ioe, attachment); + Invoker.invokeIndirectly(handler, result); + return result; + } + + // need calling context when there is security manager as + // permission check may be done in a different thread without + // any application call frames on the stack + AccessControlContext acc = (System.getSecurityManager() == null) ? + null : AccessController.getContext(); + + PendingFuture result = + new PendingFuture(this, handler, attachment); + AcceptTask task = new AcceptTask(ch, acc, result); + result.setContext(task); + + // check and set flag to prevent concurrent accepting + if (!accepting.compareAndSet(false, true)) + throw new AcceptPendingException(); + + // initiate accept. As I/O operations are tied to the initiating thread + // then it will only be invoked direcly if this thread is in the thread + // pool. If this thread is not in the thread pool when a task is + // submitted to initiate the accept. + Invoker.invokeOnThreadInThreadPool(this, task); + return result; + } + + // -- Native methods -- + + private static native void initIDs(); + + private static native int accept0(long listenSocket, long acceptSocket, + long overlapped, long dataBuffer) throws IOException; + + private static native void updateAcceptContext(long listenSocket, + long acceptSocket) throws IOException; + + private static native void closesocket0(long socket) throws IOException; + + static { + Util.load(); + initIDs(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java new file mode 100644 index 00000000000..fe9920c15cc --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -0,0 +1,911 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA conne02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.ch; + +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.nio.BufferOverflowException; +import java.net.*; +import java.util.concurrent.*; +import java.io.IOException; +import sun.misc.Unsafe; + +/** + * Windows implementation of AsynchronousSocketChannel using overlapped I/O. + */ + +class WindowsAsynchronousSocketChannelImpl + extends AsynchronousSocketChannelImpl implements Iocp.OverlappedChannel +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static int addressSize = unsafe.addressSize(); + + private static int dependsArch(int value32, int value64) { + return (addressSize == 4) ? value32 : value64; + } + + /* + * typedef struct _WSABUF { + * u_long len; + * char FAR * buf; + * } WSABUF; + */ + private static final int SIZEOF_WSABUF = dependsArch(8, 16); + private static final int OFFSETOF_LEN = 0; + private static final int OFFSETOF_BUF = dependsArch(4, 8); + + // maximum vector size for scatter/gather I/O + private static final int MAX_WSABUF = 16; + + private static final int SIZEOF_WSABUFARRAY = MAX_WSABUF * SIZEOF_WSABUF; + + + // socket handle. Use begin()/end() around each usage of this handle. + final long handle; + + // I/O completion port that the socket is associated with + private final Iocp iocp; + + // completion key to identify channel when I/O completes + private final int completionKey; + + // Pending I/O operations are tied to an OVERLAPPED structure that can only + // be released when the I/O completion event is posted to the completion + // port. Where I/O operations complete immediately then it is possible + // there may be more than two OVERLAPPED structures in use. + private final PendingIoCache ioCache; + + // per-channel arrays of WSABUF structures + private final long readBufferArray; + private final long writeBufferArray; + + + WindowsAsynchronousSocketChannelImpl(Iocp iocp, boolean failIfGroupShutdown) + throws IOException + { + super(iocp); + + // associate socket with default completion port + long h = IOUtil.fdVal(fd); + int key = 0; + try { + key = iocp.associate(this, h); + } catch (ShutdownChannelGroupException x) { + if (failIfGroupShutdown) { + closesocket0(h); + throw x; + } + } catch (IOException x) { + closesocket0(h); + throw x; + } + + this.handle = h; + this.iocp = iocp; + this.completionKey = key; + this.ioCache = new PendingIoCache(); + + // allocate WSABUF arrays + this.readBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY); + this.writeBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY); + } + + WindowsAsynchronousSocketChannelImpl(Iocp iocp) throws IOException { + this(iocp, true); + } + + @Override + public AsynchronousChannelGroupImpl group() { + return iocp; + } + + /** + * Invoked by Iocp when an I/O operation competes. + */ + @Override + public PendingFuture getByOverlapped(long overlapped) { + return ioCache.remove(overlapped); + } + + // invoked by WindowsAsynchronousServerSocketChannelImpl + long handle() { + return handle; + } + + // invoked by WindowsAsynchronousServerSocketChannelImpl when new connection + // accept + void setConnected(SocketAddress localAddress, SocketAddress remoteAddress) { + synchronized (stateLock) { + state = ST_CONNECTED; + this.localAddress = localAddress; + this.remoteAddress = remoteAddress; + } + } + + @Override + void implClose() throws IOException { + // close socket (may cause outstanding async I/O operations to fail). + closesocket0(handle); + + // waits until all I/O operations have completed + ioCache.close(); + + // release arrays of WSABUF structures + unsafe.freeMemory(readBufferArray); + unsafe.freeMemory(writeBufferArray); + + // finally disassociate from the completion port (key can be 0 if + // channel created when group is shutdown) + if (completionKey != 0) + iocp.disassociate(completionKey); + } + + @Override + public void onCancel(PendingFuture task) { + if (task.getContext() instanceof ConnectTask) + killConnect(); + if (task.getContext() instanceof ReadTask) + killReading(); + if (task.getContext() instanceof WriteTask) + killWriting(); + } + + /** + * Implements the task to initiate a connection and the handler to + * consume the result when the connection is established (or fails). + */ + private class ConnectTask implements Runnable, Iocp.ResultHandler { + private final InetSocketAddress remote; + private final PendingFuture result; + + ConnectTask(InetSocketAddress remote, PendingFuture result) { + this.remote = remote; + this.result = result; + } + + private void closeChannel() { + try { + close(); + } catch (IOException ignore) { } + } + + private IOException toIOException(Throwable x) { + if (x instanceof IOException) { + if (x instanceof ClosedChannelException) + x = new AsynchronousCloseException(); + return (IOException)x; + } + return new IOException(x); + } + + /** + * Invoke after a connection is successfully established. + */ + private void afterConnect() throws IOException { + updateConnectContext(handle); + synchronized (stateLock) { + state = ST_CONNECTED; + remoteAddress = remote; + } + } + + /** + * Task to initiate a connection. + */ + @Override + public void run() { + long overlapped = 0L; + Throwable exc = null; + try { + begin(); + + // synchronize on result to allow this thread handle the case + // where the connection is established immediately. + synchronized (result) { + overlapped = ioCache.add(result); + // initiate the connection + int n = connect0(handle, Net.isIPv6Available(), remote.getAddress(), + remote.getPort(), overlapped); + if (n == IOStatus.UNAVAILABLE) { + // connection is pending + return; + } + + // connection established immediately + afterConnect(); + result.setResult(null); + } + } catch (Throwable x) { + exc = x; + } finally { + end(); + } + + if (exc != null) { + if (overlapped != 0L) + ioCache.remove(overlapped); + closeChannel(); + result.setFailure(toIOException(exc)); + } + Invoker.invoke(result.handler(), result); + } + + /** + * Invoked by handler thread when connection established. + */ + @Override + public void completed(int bytesTransferred) { + Throwable exc = null; + try { + begin(); + afterConnect(); + result.setResult(null); + } catch (Throwable x) { + // channel is closed or unable to finish connect + exc = x; + } finally { + end(); + } + + // can't close channel while in begin/end block + if (exc != null) { + closeChannel(); + result.setFailure(toIOException(exc)); + } + + Invoker.invoke(result.handler(), result); + } + + /** + * Invoked by handler thread when failed to establish connection. + */ + @Override + public void failed(int error, IOException x) { + if (isOpen()) { + closeChannel(); + result.setFailure(x); + } else { + result.setFailure(new AsynchronousCloseException()); + } + Invoker.invoke(result.handler(), result); + } + } + + @Override + public Future connect(SocketAddress remote, + A attachment, + CompletionHandler handler) + { + if (!isOpen()) { + CompletedFuture result = CompletedFuture + .withFailure(this, new ClosedChannelException(), attachment); + Invoker.invoke(handler, result); + return result; + } + + InetSocketAddress isa = Net.checkAddress(remote); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); + + // check and update state + // ConnectEx requires the socket to be bound to a local address + IOException bindException = null; + synchronized (stateLock) { + if (state == ST_CONNECTED) + throw new AlreadyConnectedException(); + if (state == ST_PENDING) + throw new ConnectionPendingException(); + if (localAddress == null) { + try { + bind(new InetSocketAddress(0)); + } catch (IOException x) { + bindException = x; + } + } + if (bindException == null) + state = ST_PENDING; + } + + // handle bind failure + if (bindException != null) { + try { + close(); + } catch (IOException ignore) { } + CompletedFuture result = CompletedFuture + .withFailure(this, bindException, attachment); + Invoker.invoke(handler, result); + return result; + } + + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + ConnectTask task = new ConnectTask(isa, result); + result.setContext(task); + + // initiate I/O (can only be done from thread in thread pool) + Invoker.invokeOnThreadInThreadPool(this, task); + return result; + } + + /** + * Implements the task to initiate a read and the handler to consume the + * result when the read completes. + */ + private class ReadTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer[] bufs; + private final int numBufs; + private final boolean scatteringRead; + private final PendingFuture result; + + // set by run method + private ByteBuffer[] shadow; + + ReadTask(ByteBuffer[] bufs, + boolean scatteringRead, + PendingFuture result) + { + this.bufs = bufs; + this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length; + this.scatteringRead = scatteringRead; + this.result = result; + } + + /** + * Invoked prior to read to prepare the WSABUF array. Where necessary, + * it substitutes non-direct buffers with direct buffers. + */ + void prepareBuffers() { + shadow = new ByteBuffer[numBufs]; + long address = readBufferArray; + for (int i=0; i= len) { + bytesRead -= len; + int newPosition = pos + len; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by another + } + } else { // Buffers not completely filled + if (bytesRead > 0) { + assert(pos + bytesRead < (long)Integer.MAX_VALUE); + int newPosition = pos + bytesRead; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by another + } + } + break; + } + } + + // Put results from shadow into the slow buffers + for (int i=0; i Future readImpl(ByteBuffer[] bufs, + boolean scatteringRead, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + final ReadTask readTask = new ReadTask(bufs, scatteringRead, result); + result.setContext(readTask); + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = iocp.schedule(new Runnable() { + public void run() { + readTask.timeout(); + } + }, timeout, unit); + result.setTimeoutTask(timeoutTask); + } + + // initiate I/O (can only be done from thread in thread pool) + Invoker.invokeOnThreadInThreadPool(this, readTask); + return result; + } + + /** + * Implements the task to initiate a write and the handler to consume the + * result when the write completes. + */ + private class WriteTask implements Runnable, Iocp.ResultHandler { + private final ByteBuffer[] bufs; + private final int numBufs; + private final boolean gatheringWrite; + private final PendingFuture result; + + // set by run method + private ByteBuffer[] shadow; + + WriteTask(ByteBuffer[] bufs, + boolean gatheringWrite, + PendingFuture result) + { + this.bufs = bufs; + this.numBufs = (bufs.length > MAX_WSABUF) ? MAX_WSABUF : bufs.length; + this.gatheringWrite = gatheringWrite; + this.result = result; + } + + /** + * Invoked prior to write to prepare the WSABUF array. Where necessary, + * it substitutes non-direct buffers with direct buffers. + */ + void prepareBuffers() { + shadow = new ByteBuffer[numBufs]; + long address = writeBufferArray; + for (int i=0; i= len) { + bytesWritten -= len; + int newPosition = pos + len; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by someone else + } + } else { // Buffers not completely filled + if (bytesWritten > 0) { + assert(pos + bytesWritten < (long)Integer.MAX_VALUE); + int newPosition = pos + bytesWritten; + try { + nextBuffer.position(newPosition); + } catch (IllegalArgumentException x) { + // position changed by someone else + } + } + break; + } + } + } + + void releaseBuffers() { + for (int i=0; i Future writeImpl(ByteBuffer[] bufs, + boolean gatheringWrite, + long timeout, + TimeUnit unit, + A attachment, + CompletionHandler handler) + { + // setup task + PendingFuture result = + new PendingFuture(this, handler, attachment); + final WriteTask writeTask = new WriteTask(bufs, gatheringWrite, result); + result.setContext(writeTask); + + // schedule timeout + if (timeout > 0L) { + Future timeoutTask = iocp.schedule(new Runnable() { + public void run() { + writeTask.timeout(); + } + }, timeout, unit); + result.setTimeoutTask(timeoutTask); + } + + // initiate I/O (can only be done from thread in thread pool) + Invoker.invokeOnThreadInThreadPool(this, writeTask); + return result; + } + + // -- Native methods -- + + private static native void initIDs(); + + private static native int connect0(long socket, boolean preferIPv6, + InetAddress remote, int remotePort, long overlapped) throws IOException; + + private static native void updateConnectContext(long socket) throws IOException; + + private static native int read0(long socket, int count, long addres, long overlapped) + throws IOException; + + private static native int write0(long socket, int count, long address, + long overlapped) throws IOException; + + private static native void shutdown0(long socket, int how) throws IOException; + + private static native void closesocket0(long socket) throws IOException; + + static { + Util.load(); + initIDs(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java new file mode 100644 index 00000000000..93923103e5f --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/DefaultFileSystemProvider.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.spi.FileSystemProvider; + +/** + * Creates default provider on Windows + */ +public class DefaultFileSystemProvider { + private DefaultFileSystemProvider() { } + public static FileSystemProvider create() { + return new WindowsFileSystemProvider(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java b/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java new file mode 100644 index 00000000000..1e775aee81c --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/DefaultFileTypeDetector.java @@ -0,0 +1,36 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.spi.FileTypeDetector; + +public class DefaultFileTypeDetector { + private DefaultFileTypeDetector() { } + + public static FileTypeDetector create() { + return new RegistryFileTypeDetector(); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java b/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java new file mode 100644 index 00000000000..dc4b9c0e2ef --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * File type detector that does lookup of file extension using Windows Registry. + */ + +public class RegistryFileTypeDetector + extends AbstractFileTypeDetector +{ + public RegistryFileTypeDetector() { + super(); + } + + @Override + public String implProbeContentType(FileRef file) throws IOException { + if (!(file instanceof Path)) + return null; + + // get file extension + Path name = ((Path)file).getName(); + if (name == null) + return null; + String filename = name.toString(); + int dot = filename.lastIndexOf('.'); + if ((dot < 0) || (dot == (filename.length()-1))) + return null; + + // query HKEY_CLASSES_ROOT\ + String key = filename.substring(dot); + NativeBuffer keyBuffer = WindowsNativeDispatcher.asNativeBuffer(key); + NativeBuffer nameBuffer = WindowsNativeDispatcher.asNativeBuffer("Content Type"); + try { + return queryStringValue(keyBuffer.address(), nameBuffer.address()); + } finally { + nameBuffer.release(); + keyBuffer.release(); + } + } + + private static native String queryStringValue(long subKey, long name); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + // nio.dll has dependency on net.dll + System.loadLibrary("net"); + System.loadLibrary("nio"); + return null; + }}); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java b/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java new file mode 100644 index 00000000000..937aedd85a0 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java @@ -0,0 +1,226 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.ProviderMismatchException; +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Windows implementation of AclFileAttributeView. + */ + +class WindowsAclFileAttributeView + extends AbstractAclFileAttributeView +{ + /** + * typedef struct _SECURITY_DESCRIPTOR { + * BYTE Revision; + * BYTE Sbz1; + * SECURITY_DESCRIPTOR_CONTROL Control; + * PSID Owner; + * PSID Group; + * PACL Sacl; + * PACL Dacl; + * } SECURITY_DESCRIPTOR; + */ + private static final short SIZEOF_SECURITY_DESCRIPTOR = 20; + + private final WindowsPath file; + private final boolean followLinks; + + WindowsAclFileAttributeView(WindowsPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + // permision check + private void checkAccess(WindowsPath file, + boolean checkRead, + boolean checkWrite) + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (checkRead) + sm.checkRead(file.getPathForPermissionCheck()); + if (checkWrite) + sm.checkWrite(file.getPathForPermissionCheck()); + sm.checkPermission(new RuntimePermission("accessUserInformation")); + } + } + + // invokes GetFileSecurity to get requested security information + static NativeBuffer getFileSecurity(String path, int request) + throws IOException + { + // invoke get to buffer size + int size = 0; + try { + size = GetFileSecurity(path, request, 0L, 0); + } catch (WindowsException x) { + x.rethrowAsIOException(path); + } + assert size > 0; + + // allocate buffer and re-invoke to get security information + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + for (;;) { + int newSize = GetFileSecurity(path, request, buffer.address(), size); + if (newSize <= size) + return buffer; + + // buffer was insufficient + buffer.release(); + buffer = NativeBuffers.getNativeBuffer(newSize); + size = newSize; + } + } catch (WindowsException x) { + buffer.release(); + x.rethrowAsIOException(path); + return null; + } + } + + @Override + public UserPrincipal getOwner() + throws IOException + { + checkAccess(file, true, false); + + // GetFileSecurity does not follow links so when following links we + // need the final target + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + NativeBuffer buffer = getFileSecurity(path, OWNER_SECURITY_INFORMATION); + try { + // get the address of the SID + long sidAddress = GetSecurityDescriptorOwner(buffer.address()); + if (sidAddress == 0L) + throw new IOException("no owner"); + return WindowsUserPrincipals.fromSid(sidAddress); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; + } finally { + buffer.release(); + } + } + + @Override + public List getAcl() + throws IOException + { + checkAccess(file, true, false); + + // GetFileSecurity does not follow links so when following links we + // need the final target + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + + // ALLOW and DENY entries in DACL; + // AUDIT entries in SACL (ignore for now as it requires privileges) + NativeBuffer buffer = getFileSecurity(path, DACL_SECURITY_INFORMATION); + try { + return WindowsSecurityDescriptor.getAcl(buffer.address()); + } finally { + buffer.release(); + } + } + + @Override + public void setOwner(UserPrincipal obj) + throws IOException + { + if (obj == null) + throw new NullPointerException("'owner' is null"); + if (!(obj instanceof WindowsUserPrincipals.User)) + throw new ProviderMismatchException(); + WindowsUserPrincipals.User owner = (WindowsUserPrincipals.User)obj; + + // permission check + checkAccess(file, false, true); + + // SetFileSecurity does not follow links so when following links we + // need the final target + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + + // ConvertStringSidToSid allocates memory for SID so must invoke + // LocalFree to free it when we are done + long pOwner = 0L; + try { + pOwner = ConvertStringSidToSid(owner.sidString()); + } catch (WindowsException x) { + throw new IOException("Failed to get SID for " + owner.getName() + + ": " + x.errorString()); + } + + // Allocate buffer for security descriptor, initialize it, set + // owner information and update the file. + try { + NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR); + try { + InitializeSecurityDescriptor(buffer.address()); + SetSecurityDescriptorOwner(buffer.address(), pOwner); + // may need SeRestorePrivilege to set the owner + WindowsSecurity.Privilege priv = + WindowsSecurity.enablePrivilege("SeRestorePrivilege"); + try { + SetFileSecurity(path, + OWNER_SECURITY_INFORMATION, + buffer.address()); + } finally { + priv.drop(); + } + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } finally { + buffer.release(); + } + } finally { + LocalFree(pOwner); + } + } + + @Override + public void setAcl(List acl) throws IOException { + checkAccess(file, false, true); + + // SetFileSecurity does not follow links so when following links we + // need the final target + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl); + try { + SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } finally { + sd.release(); + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java b/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java new file mode 100644 index 00000000000..f559166bb6b --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java @@ -0,0 +1,341 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.channels.*; +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.*; + +import com.sun.nio.file.ExtendedOpenOption; + +import sun.nio.ch.FileChannelImpl; +import sun.nio.ch.ThreadPool; +import sun.nio.ch.WindowsAsynchronousFileChannelImpl; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Factory to create FileChannels and AsynchronousFileChannels. + */ + +class WindowsChannelFactory { + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + private WindowsChannelFactory() { } + + /** + * Do not follow reparse points when opening an existing file. Do not fail + * if the file is a reparse point. + */ + static final OpenOption OPEN_REPARSE_POINT = new OpenOption() { }; + + /** + * Represents the flags from a user-supplied set of open options. + */ + private static class Flags { + boolean read; + boolean write; + boolean append; + boolean truncateExisting; + boolean create; + boolean createNew; + boolean deleteOnClose; + boolean sparse; + boolean overlapped; + boolean sync; + boolean dsync; + + // non-standard + boolean shareRead = true; + boolean shareWrite = true; + boolean shareDelete = true; + boolean noFollowLinks; + boolean openReparsePoint; + + static Flags toFlags(Set options) { + Flags flags = new Flags(); + for (OpenOption option: options) { + if (option instanceof StandardOpenOption) { + switch ((StandardOpenOption)option) { + case READ : flags.read = true; break; + case WRITE : flags.write = true; break; + case APPEND : flags.append = true; break; + case TRUNCATE_EXISTING : flags.truncateExisting = true; break; + case CREATE : flags.create = true; break; + case CREATE_NEW : flags.createNew = true; break; + case DELETE_ON_CLOSE : flags.deleteOnClose = true; break; + case SPARSE : flags.sparse = true; break; + case SYNC : flags.sync = true; break; + case DSYNC : flags.dsync = true; break; + default: throw new UnsupportedOperationException(); + } + continue; + } + if (option instanceof ExtendedOpenOption) { + switch ((ExtendedOpenOption)option) { + case NOSHARE_READ : flags.shareRead = false; break; + case NOSHARE_WRITE : flags.shareWrite = false; break; + case NOSHARE_DELETE : flags.shareDelete = false; break; + default: throw new UnsupportedOperationException(); + } + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + flags.noFollowLinks = true; + continue; + } + if (option == OPEN_REPARSE_POINT) { + flags.openReparsePoint = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException(); + } + return flags; + } + } + + /** + * Open/creates file, returning FileChannel to access the file + * + * @param pathForWindows + * The path of the file to open/create + * @param pathToCheck + * The path used for permission checks (if security manager) + */ + static FileChannel newFileChannel(String pathForWindows, + String pathToCheck, + Set options, + long pSecurityDescriptor) + throws WindowsException + { + Flags flags = Flags.toFlags(options); + + // default is reading; append => writing + if (!flags.read && !flags.write) { + if (flags.append) { + flags.write = true; + } else { + flags.read = true; + } + } + + // validation + if (flags.read && flags.append) + throw new IllegalArgumentException("READ + APPEND not allowed"); + if (flags.append && flags.truncateExisting) + throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); + + FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); + return FileChannelImpl.open(fdObj, flags.read, flags.write, null); + } + + /** + * Open/creates file, returning AsynchronousFileChannel to access the file + * + * @param pathForWindows + * The path of the file to open/create + * @param pathToCheck + * The path used for permission checks (if security manager) + * @param pool + * The thread pool that the channel is associated with + */ + static AsynchronousFileChannel newAsynchronousFileChannel(String pathForWindows, + String pathToCheck, + Set options, + long pSecurityDescriptor, + ThreadPool pool) + throws IOException + { + Flags flags = Flags.toFlags(options); + + // Overlapped I/O required + flags.overlapped = true; + + // default is reading + if (!flags.read && !flags.write) { + flags.read = true; + } + + // validation + if (flags.append) + throw new UnsupportedOperationException("APPEND not allowed"); + + // open file for overlapped I/O + FileDescriptor fdObj; + try { + fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); + } catch (WindowsException x) { + x.rethrowAsIOException(pathForWindows); + return null; + } + + // create the AsynchronousFileChannel + try { + return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool); + } catch (IOException x) { + // IOException is thrown if the file handle cannot be associated + // with the completion port. All we can do is close the file. + long handle = fdAccess.getHandle(fdObj); + CloseHandle(handle); + throw x; + } + } + + /** + * Opens file based on parameters and options, returning a FileDescriptor + * encapsulating the handle to the open file. + */ + private static FileDescriptor open(String pathForWindows, + String pathToCheck, + Flags flags, + long pSecurityDescriptor) + throws WindowsException + { + // set to true if file must be truncated after open + boolean truncateAfterOpen = false; + + // map options + int dwDesiredAccess = 0; + if (flags.read) + dwDesiredAccess |= GENERIC_READ; + if (flags.write) + dwDesiredAccess |= (flags.append) ? FILE_APPEND_DATA : GENERIC_WRITE; + + int dwShareMode = 0; + if (flags.shareRead) + dwShareMode |= FILE_SHARE_READ; + if (flags.shareWrite) + dwShareMode |= FILE_SHARE_WRITE; + if (flags.shareDelete) + dwShareMode |= FILE_SHARE_DELETE; + + int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + int dwCreationDisposition = OPEN_EXISTING; + if (flags.write) { + if (flags.createNew) { + dwCreationDisposition = CREATE_NEW; + // force create to fail if file is orphaned reparse point + dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; + } else { + if (flags.create) + dwCreationDisposition = OPEN_ALWAYS; + if (flags.truncateExisting) { + // Windows doesn't have a creation disposition that exactly + // corresponds to CREATE + TRUNCATE_EXISTING so we use + // the OPEN_ALWAYS mode and then truncate the file. + if (dwCreationDisposition == OPEN_ALWAYS) { + truncateAfterOpen = true; + } else { + dwCreationDisposition = TRUNCATE_EXISTING; + } + } + } + } + + if (flags.dsync || flags.sync) + dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH; + if (flags.overlapped) + dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED; + if (flags.deleteOnClose) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + // NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point + boolean okayToFollowLinks = true; + if (dwCreationDisposition != CREATE_NEW && + (flags.noFollowLinks || + flags.openReparsePoint || + flags.deleteOnClose)) + { + if (flags.noFollowLinks || flags.deleteOnClose) + okayToFollowLinks = false; + dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + // permission check + if (pathToCheck != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (flags.read) + sm.checkRead(pathToCheck); + if (flags.write) + sm.checkWrite(pathToCheck); + if (flags.deleteOnClose) + sm.checkDelete(pathToCheck); + } + } + + // open file + long handle = CreateFile(pathForWindows, + dwDesiredAccess, + dwShareMode, + pSecurityDescriptor, + dwCreationDisposition, + dwFlagsAndAttributes); + + // make sure this isn't a symbolic link. + if (!okayToFollowLinks) { + try { + if (WindowsFileAttributes.readAttributes(handle).isSymbolicLink()) + throw new WindowsException("File is symbolic link"); + } catch (WindowsException x) { + CloseHandle(handle); + throw x; + } + } + + // truncate file (for CREATE + TRUNCATE_EXISTING case) + if (truncateAfterOpen) { + try { + SetEndOfFile(handle); + } catch (WindowsException x) { + CloseHandle(handle); + throw x; + } + } + + // make the file sparse if needed + if (dwCreationDisposition == CREATE_NEW && flags.sparse) { + try { + DeviceIoControlSetSparse(handle); + } catch (WindowsException x) { + // ignore as sparse option is hint + } + } + + // create FileDescriptor and return + FileDescriptor fdObj = new FileDescriptor(); + fdAccess.setHandle(fdObj, handle); + return fdObj; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java new file mode 100644 index 00000000000..f2619ac8060 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java @@ -0,0 +1,192 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * Win32 APIs constants. + */ + +class WindowsConstants { + private WindowsConstants() { } + + // general + public static final long INVALID_HANDLE_VALUE = -1L; + + // generic rights + public static final int GENERIC_READ = 0x80000000; + public static final int GENERIC_WRITE = 0x40000000; + + // share modes + public static final int FILE_SHARE_READ = 0x00000001; + public static final int FILE_SHARE_WRITE = 0x00000002; + public static final int FILE_SHARE_DELETE = 0x00000004; + + // creation modes + public static final int CREATE_NEW = 1; + public static final int CREATE_ALWAYS = 2; + public static final int OPEN_EXISTING = 3; + public static final int OPEN_ALWAYS = 4; + public static final int TRUNCATE_EXISTING = 5; + + // attributes and flags + public static final int FILE_ATTRIBUTE_READONLY = 0x00000001; + public static final int FILE_ATTRIBUTE_HIDDEN = 0x00000002; + public static final int FILE_ATTRIBUTE_SYSTEM = 0x00000004; + public static final int FILE_ATTRIBUTE_DIRECTORY = 0x00000010; + public static final int FILE_ATTRIBUTE_ARCHIVE = 0x00000020; + public static final int FILE_ATTRIBUTE_DEVICE = 0x00000040; + public static final int FILE_ATTRIBUTE_NORMAL = 0x00000080; + public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x400; + public static final int FILE_FLAG_NO_BUFFERING = 0x20000000; + public static final int FILE_FLAG_OVERLAPPED = 0x40000000; + public static final int FILE_FLAG_WRITE_THROUGH = 0x80000000; + public static final int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; + public static final int FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; + public static final int FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000; + + // stream ids + public static final int BACKUP_ALTERNATE_DATA = 0x00000004; + public static final int BACKUP_SPARSE_BLOCK = 0x00000009; + + // reparse point/symbolic link related constants + public static final int IO_REPARSE_TAG_SYMLINK = 0xA000000C; + public static final int MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024; + public static final int SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1; + + // volume flags + public static final int FILE_CASE_SENSITIVE_SEARCH = 0x00000001; + public static final int FILE_CASE_PRESERVED_NAMES = 0x00000002; + public static final int FILE_PERSISTENT_ACLS = 0x00000008; + public static final int FILE_VOLUME_IS_COMPRESSED = 0x00008000; + public static final int FILE_NAMED_STREAMS = 0x00040000; + public static final int FILE_READ_ONLY_VOLUME = 0x00080000; + + // error codes + public static final int ERROR_FILE_NOT_FOUND = 2; + public static final int ERROR_PATH_NOT_FOUND = 3; + public static final int ERROR_ACCESS_DENIED = 5; + public static final int ERROR_INVALID_HANDLE = 6; + public static final int ERROR_INVALID_DATA = 13; + public static final int ERROR_NOT_SAME_DEVICE = 17; + public static final int ERROR_NOT_READY = 21; + public static final int ERROR_FILE_EXISTS = 80; + public static final int ERROR_DISK_FULL = 112; + public static final int ERROR_INSUFFICIENT_BUFFER = 122; + public static final int ERROR_INVALID_LEVEL = 124; + public static final int ERROR_DIR_NOT_EMPTY = 145; + public static final int ERROR_ALREADY_EXISTS = 183; + public static final int ERROR_DIRECTORY = 267; + public static final int ERROR_NOTIFY_ENUM_DIR = 1022; + public static final int ERROR_NONE_MAPPED = 1332; + public static final int ERROR_NOT_A_REPARSE_POINT = 4390; + public static final int ERROR_INVALID_REPARSE_DATA = 4392; + + // notify filters + public static final int FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001; + public static final int FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002; + public static final int FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004; + public static final int FILE_NOTIFY_CHANGE_SIZE = 0x00000008; + public static final int FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010; + public static final int FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020; + public static final int FILE_NOTIFY_CHANGE_CREATION = 0x00000040; + public static final int FILE_NOTIFY_CHANGE_SECURITY = 0x00000100; + + // notify actions + public final static int FILE_ACTION_ADDED = 0x00000001; + public final static int FILE_ACTION_REMOVED = 0x00000002; + public final static int FILE_ACTION_MODIFIED = 0x00000003; + public final static int FILE_ACTION_RENAMED_OLD_NAME = 0x00000004; + public final static int FILE_ACTION_RENAMED_NEW_NAME = 0x00000005; + + // copy flags + public static final int COPY_FILE_FAIL_IF_EXISTS = 0x00000001; + public static final int COPY_FILE_COPY_SYMLINK = 0x00000800; + + // move flags + public static final int MOVEFILE_REPLACE_EXISTING = 0x00000001; + public static final int MOVEFILE_COPY_ALLOWED = 0x00000002; + + // drive types + public static final int DRIVE_UNKNOWN = 0; + public static final int DRIVE_NO_ROOT_DIR = 1; + public static final int DRIVE_REMOVABLE = 2; + public static final int DRIVE_FIXED = 3; + public static final int DRIVE_REMOTE = 4; + public static final int DRIVE_CDROM = 5; + public static final int DRIVE_RAMDISK = 6; + + // file security + public static final int OWNER_SECURITY_INFORMATION = 0x00000001; + public static final int GROUP_SECURITY_INFORMATION = 0x00000002; + public static final int DACL_SECURITY_INFORMATION = 0x00000004; + public static final int SACL_SECURITY_INFORMATION = 0x00000008; + + public static final int SidTypeUser = 1; + public static final int SidTypeGroup = 2; + public static final int SidTypeDomain = 3; + public static final int SidTypeAlias = 4; + public static final int SidTypeWellKnownGroup = 5; + public static final int SidTypeDeletedAccount = 6; + public static final int SidTypeInvalid = 7; + public static final int SidTypeUnknown = 8; + public static final int SidTypeComputer= 9; + + public static final byte ACCESS_ALLOWED_ACE_TYPE = 0x0; + public static final byte ACCESS_DENIED_ACE_TYPE = 0x1; + + public static final byte OBJECT_INHERIT_ACE = 0x1; + public static final byte CONTAINER_INHERIT_ACE = 0x2; + public static final byte NO_PROPAGATE_INHERIT_ACE = 0x4; + public static final byte INHERIT_ONLY_ACE = 0x8; + + public static final int DELETE = 0x00010000; + public static final int READ_CONTROL = 0x00020000; + public static final int WRITE_DAC = 0x00040000; + public static final int WRITE_OWNER = 0x00080000; + public static final int SYNCHRONIZE = 0x00100000; + + public static final int FILE_LIST_DIRECTORY = 0x0001; + public static final int FILE_READ_DATA = 0x0001; + public static final int FILE_WRITE_DATA = 0x0002; + public static final int FILE_APPEND_DATA = 0x0004; + public static final int FILE_READ_EA = 0x0008; + public static final int FILE_WRITE_EA = 0x0010; + public static final int FILE_EXECUTE = 0x0020; + public static final int FILE_DELETE_CHILD = 0x0040; + public static final int FILE_READ_ATTRIBUTES = 0x0080; + public static final int FILE_WRITE_ATTRIBUTES = 0x0100; + + // operating system security + public static final int TOKEN_DUPLICATE = 0x0002; + public static final int TOKEN_IMPERSONATE = 0x0004; + public static final int TOKEN_QUERY = 0x0008; + public static final int TOKEN_ADJUST_PRIVILEGES = 0x0020; + + public static final int SE_PRIVILEGE_ENABLED = 0x00000002; + + public static final int TokenUser = 1; + public static final int PROCESS_QUERY_INFORMATION = 0x0400; +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java new file mode 100644 index 00000000000..fa0b148346c --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java @@ -0,0 +1,255 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Iterator; +import java.util.ConcurrentModificationException; +import java.util.NoSuchElementException; +import java.io.IOException; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Windows implementation of DirectoryStream + */ + +class WindowsDirectoryStream + implements DirectoryStream +{ + private final WindowsPath dir; + private final DirectoryStream.Filter filter; + + // handle to directory + private final long handle; + // first entry in the directory + private final String firstName; + + // buffer for WIN32_FIND_DATA structure that receives information about file + private final NativeBuffer findDataBuffer; + + private final Object closeLock = new Object(); + + // need closeLock to access these + private boolean isOpen = true; + private Iterator iterator; + + + WindowsDirectoryStream(WindowsPath dir, DirectoryStream.Filter filter) + throws IOException + { + this.dir = dir; + this.filter = filter; + + try { + // Need to append * or \* to match entries in directory. + String search = dir.getPathForWin32Calls(); + char last = search.charAt(search.length() -1); + if (last == ':' || last == '\\') { + search += "*"; + } else { + search += "\\*"; + } + + FirstFile first = FindFirstFile(search); + this.handle = first.handle(); + this.firstName = first.name(); + this.findDataBuffer = WindowsFileAttributes.getBufferForFindData(); + } catch (WindowsException x) { + if (x.lastError() == ERROR_DIRECTORY) { + throw new NotDirectoryException(dir.getPathForExceptionMessage()); + } + x.rethrowAsIOException(dir); + + // keep compiler happy + throw new AssertionError(); + } + } + + @Override + public void close() + throws IOException + { + synchronized (closeLock) { + if (!isOpen) + return; + isOpen = false; + } + findDataBuffer.release(); + try { + FindClose(handle); + } catch (WindowsException x) { + x.rethrowAsIOException(dir); + } + } + + @Override + public Iterator iterator() { + if (!isOpen) { + throw new IllegalStateException("Directory stream is closed"); + } + synchronized (this) { + if (iterator != null) + throw new IllegalStateException("Iterator already obtained"); + iterator = new WindowsDirectoryIterator(firstName); + return iterator; + } + } + + private static void throwAsConcurrentModificationException(Throwable t) { + ConcurrentModificationException cme = new ConcurrentModificationException(); + cme.initCause(t); + throw cme; + } + + private class WindowsDirectoryIterator implements Iterator { + private boolean atEof; + private String first; + private Path nextEntry; + private Path prevEntry; + + WindowsDirectoryIterator(String first) { + atEof = false; + this.first = first; + } + + // applies filter and also ignores "." and ".." + private Path acceptEntry(String s, BasicFileAttributes attrs) { + if (s.equals(".") || s.equals("..")) + return null; + if (dir.needsSlashWhenResolving()) { + StringBuilder sb = new StringBuilder(dir.toString()); + sb.append('\\'); + sb.append(s); + s = sb.toString(); + } else { + s = dir + s; + } + Path entry = WindowsPath + .createFromNormalizedPath(dir.getFileSystem(), s, attrs); + if (filter.accept(entry)) { + return entry; + } else { + return null; + } + } + + // reads next directory entry + private Path readNextEntry() { + // handle first element returned by search + if (first != null) { + nextEntry = acceptEntry(first, null); + first = null; + if (nextEntry != null) + return nextEntry; + } + + for (;;) { + String name = null; + WindowsFileAttributes attrs; + + // synchronize on closeLock to prevent close while reading + synchronized (closeLock) { + if (!isOpen) + throwAsConcurrentModificationException(new + IllegalStateException("Directory stream is closed")); + try { + name = FindNextFile(handle, findDataBuffer.address()); + if (name == null) { + // NO_MORE_FILES + return null; + } + } catch (WindowsException x) { + try { + x.rethrowAsIOException(dir); + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); + } + } + + // grab the attributes from the WIN32_FIND_DATA structure + // (needs to be done while holding closeLock because close + // will release the buffer) + attrs = WindowsFileAttributes + .fromFindData(findDataBuffer.address()); + } + + // return entry if accepted by filter + Path entry = acceptEntry(name, attrs); + if (entry != null) + return entry; + } + } + + @Override + public synchronized boolean hasNext() { + if (nextEntry == null && !atEof) { + nextEntry = readNextEntry(); + atEof = (nextEntry == null); + } + return nextEntry != null; + } + + @Override + public synchronized Path next() { + if (nextEntry == null) { + if (!atEof) { + nextEntry = readNextEntry(); + } + if (nextEntry == null) { + atEof = true; + throw new NoSuchElementException(); + } + } + prevEntry = nextEntry; + nextEntry = null; + return prevEntry; + } + + @Override + public void remove() { + if (!isOpen) { + throw new IllegalStateException("Directory stream is closed"); + } + Path entry; + synchronized (this) { + if (prevEntry == null) + throw new IllegalStateException("no last element"); + entry = prevEntry; + prevEntry = null; + } + try { + entry.delete(true); + } catch (IOException ioe) { + throwAsConcurrentModificationException(ioe); + } catch (SecurityException se) { + throwAsConcurrentModificationException(se); + } + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsException.java b/jdk/src/windows/classes/sun/nio/fs/WindowsException.java new file mode 100644 index 00000000000..7da722076f3 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsException.java @@ -0,0 +1,109 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; + +import static sun.nio.fs.WindowsConstants.*; + +/** + * Internal exception thrown when a Win32 calls fails. + */ + +class WindowsException extends Exception { + static final long serialVersionUID = 2765039493083748820L; + + private int lastError; + private String msg; + + WindowsException(int lastError) { + this.lastError = lastError; + this.msg = null; + } + + WindowsException(String msg) { + this.lastError = 0; + this.msg = msg; + } + + int lastError() { + return lastError; + } + + String errorString() { + if (msg == null) { + msg = WindowsNativeDispatcher.FormatMessage(lastError); + if (msg == null) { + msg = "Unknown error: 0x" + Integer.toHexString(lastError); + } + } + return msg; + } + + @Override + public String getMessage() { + return errorString(); + } + + private IOException translateToIOException(String file, String other) { + // not created with last error + if (lastError() == 0) + return new IOException(errorString()); + + // handle specific cases + if (lastError() == ERROR_FILE_NOT_FOUND || lastError() == ERROR_PATH_NOT_FOUND) + return new NoSuchFileException(file, other, null); + if (lastError() == ERROR_FILE_EXISTS || lastError() == ERROR_ALREADY_EXISTS) + return new FileAlreadyExistsException(file, other, null); + if (lastError() == ERROR_ACCESS_DENIED) + return new AccessDeniedException(file, other, null); + + // fallback to the more general exception + return new FileSystemException(file, other, errorString()); + } + + void rethrowAsIOException(String file) throws IOException { + IOException x = translateToIOException(file, null); + throw x; + } + + void rethrowAsIOException(WindowsPath file, WindowsPath other) throws IOException { + String a = (file == null) ? null : file.getPathForExceptionMessage(); + String b = (other == null) ? null : other.getPathForExceptionMessage(); + IOException x = translateToIOException(a, b); + throw x; + } + + void rethrowAsIOException(WindowsPath file) throws IOException { + rethrowAsIOException(file, null); + } + + IOException asIOException(WindowsPath file) { + return translateToIOException(file.getPathForExceptionMessage(), null); + } + +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java new file mode 100644 index 00000000000..39c34a10ea9 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java @@ -0,0 +1,296 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + + +import java.nio.file.attribute.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.io.IOException; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +class WindowsFileAttributeViews { + + private static class Basic extends AbstractBasicFileAttributeView { + final WindowsPath file; + final boolean followLinks; + + Basic(WindowsPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + @Override + public WindowsFileAttributes readAttributes() throws IOException { + try { + return WindowsFileAttributes.get(file, followLinks); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } + + /** + * Parameter values in Windows times. + */ + void setFileTimes(long createTime, long lastAccessTime, long lastWriteTime) + throws IOException + { + long handle = -1L; + try { + int flags = FILE_FLAG_BACKUP_SEMANTICS; + if (!followLinks && file.getFileSystem().supportsLinks()) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + + handle = CreateFile(file.getPathForWin32Calls(), + FILE_WRITE_ATTRIBUTES, + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), + OPEN_EXISTING, + flags); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } + + // update attributes + try { + SetFileTime(handle, createTime, lastAccessTime, lastWriteTime); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } finally { + CloseHandle(handle); + } + } + + @Override + public void setTimes(Long lastModifiedTime, + Long lastAccessTime, + Long createTime, + TimeUnit unit) throws IOException + { + file.checkWrite(); + + // if all null then do nothing + if (lastModifiedTime == null && lastAccessTime == null && + createTime == null) + { + // no effect + return; + } + + // null => no change + // -1 => change to current time + long now = System.currentTimeMillis(); + long modTime = 0L, accTime = 0L, crTime = 0L; + if (lastModifiedTime != null) { + if (lastModifiedTime < 0L) { + if (lastModifiedTime != -1L) + throw new IllegalArgumentException(); + modTime = now; + } else { + modTime = TimeUnit.MILLISECONDS.convert(lastModifiedTime, unit); + } + modTime = WindowsFileAttributes.toWindowsTime(modTime); + } + if (lastAccessTime != null) { + if (lastAccessTime < 0L) { + if (lastAccessTime != -1L) + throw new IllegalArgumentException(); + accTime = now; + } else { + accTime = TimeUnit.MILLISECONDS.convert(lastAccessTime, unit); + } + accTime = WindowsFileAttributes.toWindowsTime(accTime); + } + if (createTime != null) { + if (createTime < 0L) { + if (createTime != -1L) + throw new IllegalArgumentException(); + crTime = now; + } else { + crTime = TimeUnit.MILLISECONDS.convert(createTime, unit); + } + crTime = WindowsFileAttributes.toWindowsTime(crTime); + } + + setFileTimes(crTime, accTime, modTime); + } + } + + static class Dos extends Basic implements DosFileAttributeView { + private static final String READONLY_NAME = "readonly"; + private static final String ARCHIVE_NAME = "archive"; + private static final String SYSTEM_NAME = "system"; + private static final String HIDDEN_NAME = "hidden"; + private static final String ATTRIBUTES_NAME = "attributes"; + + Dos(WindowsPath file, boolean followLinks) { + super(file, followLinks); + } + + @Override + public String name() { + return "dos"; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(READONLY_NAME)) + return readAttributes().isReadOnly(); + if (attribute.equals(ARCHIVE_NAME)) + return readAttributes().isArchive(); + if (attribute.equals(SYSTEM_NAME)) + return readAttributes().isSystem(); + if (attribute.equals(HIDDEN_NAME)) + return readAttributes().isHidden(); + // implementation specific + if (attribute.equals(ATTRIBUTES_NAME)) + return readAttributes().attributes(); + return super.getAttribute(attribute); + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + if (attribute.equals(READONLY_NAME)) { + setReadOnly((Boolean)value); + return; + } + if (attribute.equals(ARCHIVE_NAME)) { + setArchive((Boolean)value); + return; + } + if (attribute.equals(SYSTEM_NAME)) { + setSystem((Boolean)value); + return; + } + if (attribute.equals(HIDDEN_NAME)) { + setHidden((Boolean)value); + return; + } + super.setAttribute(attribute, value); + } + + @Override + public Map readAttributes(String first, String[] rest) + throws IOException + { + AttributesBuilder builder = AttributesBuilder.create(first, rest); + WindowsFileAttributes attrs = readAttributes(); + addBasicAttributesToBuilder(attrs, builder); + if (builder.match(READONLY_NAME)) + builder.add(READONLY_NAME, attrs.isReadOnly()); + if (builder.match(ARCHIVE_NAME)) + builder.add(ARCHIVE_NAME, attrs.isArchive()); + if (builder.match(SYSTEM_NAME)) + builder.add(SYSTEM_NAME, attrs.isSystem()); + if (builder.match(HIDDEN_NAME)) + builder.add(HIDDEN_NAME, attrs.isHidden()); + if (builder.match(ATTRIBUTES_NAME)) + builder.add(ATTRIBUTES_NAME, attrs.attributes()); + return builder.unmodifiableMap(); + } + + /** + * Update DOS attributes + */ + private void updateAttributes(int flag, boolean enable) + throws IOException + { + file.checkWrite(); + + // GetFileAttribtues & SetFileAttributes do not follow links so when + // following links we need the final target + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + try { + int oldValue = GetFileAttributes(path); + int newValue = oldValue; + if (enable) { + newValue |= flag; + } else { + newValue &= ~flag; + } + if (newValue != oldValue) { + SetFileAttributes(path, newValue); + } + } catch (WindowsException x) { + // don't reveal target in exception + x.rethrowAsIOException(file); + } + } + + @Override + public void setReadOnly(boolean value) throws IOException { + updateAttributes(FILE_ATTRIBUTE_READONLY, value); + } + + @Override + public void setHidden(boolean value) throws IOException { + updateAttributes(FILE_ATTRIBUTE_HIDDEN, value); + } + + @Override + public void setArchive(boolean value) throws IOException { + updateAttributes(FILE_ATTRIBUTE_ARCHIVE, value); + } + + @Override + public void setSystem(boolean value) throws IOException { + updateAttributes(FILE_ATTRIBUTE_SYSTEM, value); + } + + // package-private + // Copy given attributes to the file. + void setAttributes(WindowsFileAttributes attrs) + throws IOException + { + // copy DOS attributes to target + int flags = 0; + if (attrs.isReadOnly()) flags |= FILE_ATTRIBUTE_READONLY; + if (attrs.isHidden()) flags |= FILE_ATTRIBUTE_HIDDEN; + if (attrs.isArchive()) flags |= FILE_ATTRIBUTE_ARCHIVE; + if (attrs.isSystem()) flags |= FILE_ATTRIBUTE_SYSTEM; + updateAttributes(flags, true); + + // copy file times to target - must be done after updating FAT attributes + // as otherwise the last modified time may be wrong. + setFileTimes( + WindowsFileAttributes.toWindowsTime(attrs.creationTime()), + WindowsFileAttributes.toWindowsTime(attrs.lastModifiedTime()), + WindowsFileAttributes.toWindowsTime(attrs.lastAccessTime())); + } + } + + static BasicFileAttributeView createBasicView(WindowsPath file, boolean followLinks) { + return new Basic(file, followLinks); + } + + static WindowsFileAttributeViews.Dos createDosView(WindowsPath file, boolean followLinks) { + return new Dos(file, followLinks); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java new file mode 100644 index 00000000000..ce053cf901f --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -0,0 +1,461 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.util.concurrent.TimeUnit; +import java.security.AccessController; +import sun.misc.Unsafe; +import sun.security.action.GetPropertyAction; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Windows implementation of DosFileAttributes/BasicFileAttributes + */ + +class WindowsFileAttributes + implements DosFileAttributes +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + /* + * typedef struct _BY_HANDLE_FILE_INFORMATION { + * DWORD dwFileAttributes; + * FILETIME ftCreationTime; + * FILETIME ftLastAccessTime; + * FILETIME ftLastWriteTime; + * DWORD dwVolumeSerialNumber; + * DWORD nFileSizeHigh; + * DWORD nFileSizeLow; + * DWORD nNumberOfLinks; + * DWORD nFileIndexHigh; + * DWORD nFileIndexLow; + * } BY_HANDLE_FILE_INFORMATION; + */ + private static final short SIZEOF_FILE_INFORMATION = 52; + private static final short OFFSETOF_FILE_INFORMATION_ATTRIBUTES = 0; + private static final short OFFSETOF_FILE_INFORMATION_CREATETIME = 4; + private static final short OFFSETOF_FILE_INFORMATION_LASTACCESSTIME = 12; + private static final short OFFSETOF_FILE_INFORMATION_LASTWRITETIME = 20; + private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM = 28; + private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH = 32; + private static final short OFFSETOF_FILE_INFORMATION_SIZELOW = 36; + private static final short OFFSETOF_FILE_INFORMATION_NUMLINKS = 40; + private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH = 44; + private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW = 48; + + /* + * typedef struct _WIN32_FILE_ATTRIBUTE_DATA { + * DWORD dwFileAttributes; + * FILETIME ftCreationTime; + * FILETIME ftLastAccessTime; + * FILETIME ftLastWriteTime; + * DWORD nFileSizeHigh; + * DWORD nFileSizeLow; + * } WIN32_FILE_ATTRIBUTE_DATA; + */ + private static final short SIZEOF_FILE_ATTRIBUTE_DATA = 36; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES = 0; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME = 4; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME = 12; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME = 20; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH = 28; + private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW = 32; + + /** + * typedef struct _WIN32_FIND_DATA { + * DWORD dwFileAttributes; + * FILETIME ftCreationTime; + * FILETIME ftLastAccessTime; + * FILETIME ftLastWriteTime; + * DWORD nFileSizeHigh; + * DWORD nFileSizeLow; + * DWORD dwReserved0; + * DWORD dwReserved1; + * TCHAR cFileName[MAX_PATH]; + * TCHAR cAlternateFileName[14]; + * } WIN32_FIND_DATA; + */ + private static final short SIZEOF_FIND_DATA = 592; + private static final short OFFSETOF_FIND_DATA_ATTRIBUTES = 0; + private static final short OFFSETOF_FIND_DATA_CREATETIME = 4; + private static final short OFFSETOF_FIND_DATA_LASTACCESSTIME = 12; + private static final short OFFSETOF_FIND_DATA_LASTWRITETIME = 20; + private static final short OFFSETOF_FIND_DATA_SIZEHIGH = 28; + private static final short OFFSETOF_FIND_DATA_SIZELOW = 32; + private static final short OFFSETOF_FIND_DATA_RESERVED0 = 36; + + // indicates if accurate metadata is required (interesting on NTFS only) + private static final boolean ensureAccurateMetadata; + static { + String propValue = AccessController.doPrivileged( + new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false")); + ensureAccurateMetadata = (propValue.length() == 0) ? + true : Boolean.valueOf(propValue); + } + + // attributes + private final int fileAttrs; + private final long creationTime; + private final long lastAccessTime; + private final long lastWriteTime; + private final long size; + private final int reparseTag; + + // additional attributes when using GetFileInformationByHandle + private final int linkCount; + private final int volSerialNumber; + private final int fileIndexHigh; + private final int fileIndexLow; + + /** + * Convert 64-bit value representing the number of 100-nanosecond intervals + * since January 1, 1601 to java time. + */ + private static long toJavaTime(long time) { + time /= 10000L; + time -= 11644473600000L; + return time; + } + + /** + * Convert java time to 64-bit value representing the number of 100-nanosecond + * intervals since January 1, 1601. + */ + static long toWindowsTime(long time) { + time += 11644473600000L; + time *= 10000L; + return time; + } + + /** + * Initialize a new instance of this class + */ + private WindowsFileAttributes(int fileAttrs, + long creationTime, + long lastAccessTime, + long lastWriteTime, + long size, + int reparseTag, + int linkCount, + int volSerialNumber, + int fileIndexHigh, + int fileIndexLow) + { + this.fileAttrs = fileAttrs; + this.creationTime = creationTime; + this.lastAccessTime = lastAccessTime; + this.lastWriteTime = lastWriteTime; + this.size = size; + this.reparseTag = reparseTag; + this.linkCount = linkCount; + this.volSerialNumber = volSerialNumber; + this.fileIndexHigh = fileIndexHigh; + this.fileIndexLow = fileIndexLow; + } + + /** + * Create a WindowsFileAttributes from a BY_HANDLE_FILE_INFORMATION structure + */ + private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) { + int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES); + long creationTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME)); + long lastAccessTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME)); + long lastWriteTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME)); + long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32) + + (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL); + int linkCount = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_NUMLINKS); + int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM); + int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH); + int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW); + return new WindowsFileAttributes(fileAttrs, + creationTime, + lastAccessTime, + lastWriteTime, + size, + reparseTag, + linkCount, + volSerialNumber, + fileIndexHigh, + fileIndexLow); + } + + /** + * Create a WindowsFileAttributes from a WIN32_FILE_ATTRIBUTE_DATA structure + */ + private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) { + int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES); + long creationTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME)); + long lastAccessTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME)); + long lastWriteTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME)); + long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32) + + (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL); + return new WindowsFileAttributes(fileAttrs, + creationTime, + lastAccessTime, + lastWriteTime, + size, + reparseTag, + 1, // linkCount + 0, // volSerialNumber + 0, // fileIndexHigh + 0); // fileIndexLow + } + + + /** + * Allocates a native buffer for a WIN32_FIND_DATA structure + */ + static NativeBuffer getBufferForFindData() { + return NativeBuffers.getNativeBuffer(SIZEOF_FIND_DATA); + } + + /** + * Create a WindowsFileAttributes from a WIN32_FIND_DATA structure + */ + static WindowsFileAttributes fromFindData(long address) { + int fileAttrs = unsafe.getInt(address + OFFSETOF_FIND_DATA_ATTRIBUTES); + long creationTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_CREATETIME)); + long lastAccessTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTACCESSTIME)); + long lastWriteTime = + toJavaTime(unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME)); + long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32) + + (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL); + int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ? + + unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0; + return new WindowsFileAttributes(fileAttrs, + creationTime, + lastAccessTime, + lastWriteTime, + size, + reparseTag, + 1, // linkCount + 0, // volSerialNumber + 0, // fileIndexHigh + 0); // fileIndexLow + } + + /** + * Reads the attributes of an open file + */ + static WindowsFileAttributes readAttributes(long handle) + throws WindowsException + { + NativeBuffer buffer = NativeBuffers + .getNativeBuffer(SIZEOF_FILE_INFORMATION); + try { + long address = buffer.address(); + GetFileInformationByHandle(handle, address); + + // if file is a reparse point then read the tag + int reparseTag = 0; + int fileAttrs = unsafe + .getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES); + if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { + int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size); + try { + DeviceIoControlGetReparsePoint(handle, reparseBuffer.address(), size); + reparseTag = (int)unsafe.getLong(reparseBuffer.address()); + } finally { + reparseBuffer.release(); + } + } + + return fromFileInformation(address, reparseTag); + } finally { + buffer.release(); + } + } + + /** + * Returns attributes of given file. + */ + static WindowsFileAttributes get(WindowsPath path, boolean followLinks) + throws WindowsException + { + if (!ensureAccurateMetadata) { + NativeBuffer buffer = + NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA); + try { + long address = buffer.address(); + GetFileAttributesEx(path.getPathForWin32Calls(), address); + // if reparse point then file may be a sym link; otherwise + // just return the attributes + int fileAttrs = unsafe + .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES); + if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0) + return fromFileAttributeData(address, 0); + } finally { + buffer.release(); + } + } + + // file is reparse point so need to open file to get attributes + long handle = path.openForReadAttributeAccess(followLinks); + try { + return readAttributes(handle); + } finally { + CloseHandle(handle); + } + } + + /** + * Returns true if the attribtues are of the same file - both files must + * be open. + */ + static boolean isSameFile(WindowsFileAttributes attrs1, + WindowsFileAttributes attrs2) + { + // volume serial number and file index must be the same + return (attrs1.volSerialNumber == attrs2.volSerialNumber) && + (attrs1.fileIndexHigh == attrs2.fileIndexHigh) && + (attrs1.fileIndexLow == attrs2.fileIndexLow); + } + + // package-private + int attributes() { + return fileAttrs; + } + + int volSerialNumber() { + if (volSerialNumber == 0) + throw new AssertionError("Should not get here"); + return volSerialNumber; + } + + int fileIndexHigh() { + if (volSerialNumber == 0) + throw new AssertionError("Should not get here"); + return fileIndexHigh; + } + + int fileIndexLow() { + if (volSerialNumber == 0) + throw new AssertionError("Should not get here"); + return fileIndexLow; + } + + @Override + public long size() { + return size; + } + + @Override + public long lastModifiedTime() { + return (lastWriteTime >= 0L) ? lastWriteTime : 0L; + } + + @Override + public long lastAccessTime() { + return (lastAccessTime >= 0L) ? lastAccessTime : 0L; + } + + @Override + public long creationTime() { + return (creationTime >= 0L) ? creationTime : 0L; + } + + @Override + public TimeUnit resolution() { + return TimeUnit.MILLISECONDS; + } + + @Override + public int linkCount() { + return linkCount; + } + + @Override + public Object fileKey() { + return null; + } + + // package private + boolean isReparsePoint() { + return (fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + } + + boolean isDirectoryLink() { + return isSymbolicLink() && ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0); + } + + @Override + public boolean isSymbolicLink() { + return reparseTag == IO_REPARSE_TAG_SYMLINK; + } + + @Override + public boolean isDirectory() { + // ignore FILE_ATTRIBUTE_DIRECTORY attribute if file is a sym link + if (isSymbolicLink()) + return false; + return ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0); + } + + @Override + public boolean isOther() { + if (isSymbolicLink()) + return false; + // return true if device or reparse point + return ((fileAttrs & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0); + } + + @Override + public boolean isRegularFile() { + return !isSymbolicLink() && !isDirectory() && !isOther(); + } + + @Override + public boolean isReadOnly() { + return (fileAttrs & FILE_ATTRIBUTE_READONLY) != 0; + } + + @Override + public boolean isHidden() { + return (fileAttrs & FILE_ATTRIBUTE_HIDDEN) != 0; + } + + @Override + public boolean isArchive() { + return (fileAttrs & FILE_ATTRIBUTE_ARCHIVE) != 0; + } + + @Override + public boolean isSystem() { + return (fileAttrs & FILE_ATTRIBUTE_SYSTEM) != 0; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java new file mode 100644 index 00000000000..69a41262aed --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -0,0 +1,519 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import com.sun.nio.file.ExtendedCopyOption; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Utility methods for copying and moving files. + */ + +class WindowsFileCopy { + private WindowsFileCopy() { + } + + /** + * Copy file from source to target + */ + static void copy(final WindowsPath source, + final WindowsPath target, + CopyOption... options) + throws IOException + { + // map options + boolean replaceExisting = false; + boolean copyAttributes = false; + boolean followLinks = true; + boolean interruptible = false; + for (CopyOption option: options) { + if (option == StandardCopyOption.REPLACE_EXISTING) { + replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == StandardCopyOption.COPY_ATTRIBUTES) { + copyAttributes = true; + continue; + } + if (option == ExtendedCopyOption.INTERRUPTIBLE) { + interruptible = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + + // check permissions. If the source file is a symbolic link then + // later we must also check LinkPermission + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + source.checkRead(); + target.checkWrite(); + } + + // get attributes of source file + // attempt to get attributes of target file + // if both files are the same there is nothing to do + // if target exists and !replace then throw exception + + WindowsFileAttributes sourceAttrs = null; + WindowsFileAttributes targetAttrs = null; + + long sourceHandle = 0L; + try { + sourceHandle = source.openForReadAttributeAccess(followLinks); + } catch (WindowsException x) { + x.rethrowAsIOException(source); + } + try { + // source attributes + try { + sourceAttrs = WindowsFileAttributes.readAttributes(sourceHandle); + } catch (WindowsException x) { + x.rethrowAsIOException(source); + } + + // open target (don't follow links) + long targetHandle = 0L; + try { + targetHandle = target.openForReadAttributeAccess(false); + try { + targetAttrs = WindowsFileAttributes.readAttributes(targetHandle); + + // if both files are the same then nothing to do + if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) { + return; + } + + // can't replace file + if (!replaceExisting) { + throw new FileAlreadyExistsException( + target.getPathForExceptionMessage()); + } + + } finally { + CloseHandle(targetHandle); + } + } catch (WindowsException x) { + // ignore + } + + } finally { + CloseHandle(sourceHandle); + } + + // if source file is a symbolic link then we must check for LinkPermission + if (sm != null && sourceAttrs.isSymbolicLink()) { + sm.checkPermission(new LinkPermission("symbolic")); + } + + final String sourcePath = asWin32Path(source); + final String targetPath = asWin32Path(target); + + // if target exists then delete it. + if (targetAttrs != null) { + try { + if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) { + RemoveDirectory(targetPath); + } else { + DeleteFile(targetPath); + } + } catch (WindowsException x) { + if (targetAttrs.isDirectory()) { + // ERROR_ALREADY_EXISTS is returned when attempting to delete + // non-empty directory on SAMBA servers. + if (x.lastError() == ERROR_DIR_NOT_EMPTY || + x.lastError() == ERROR_ALREADY_EXISTS) + { + throw new FileAlreadyExistsException( + target.getPathForExceptionMessage()); + } + } + x.rethrowAsIOException(target); + } + } + + // Use CopyFileEx if the file is not a directory or junction + if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) { + final int flags = + (source.getFileSystem().supportsLinks() && !followLinks) ? + COPY_FILE_COPY_SYMLINK : 0; + + if (interruptible) { + // interruptible copy + Cancellable copyTask = new Cancellable() { + @Override + public int cancelValue() { + return 1; // TRUE + } + @Override + public void implRun() throws IOException { + try { + CopyFileEx(sourcePath, targetPath, flags, + addressToPollForCancel()); + } catch (WindowsException x) { + x.rethrowAsIOException(source, target); + } + } + }; + try { + Cancellable.runInterruptibly(copyTask); + } catch (ExecutionException e) { + Throwable t = e.getCause(); + if (t instanceof IOException) + throw (IOException)t; + throw new IOException(t); + } + } else { + // non-interruptible copy + try { + CopyFileEx(sourcePath, targetPath, flags, 0L); + } catch (WindowsException x) { + x.rethrowAsIOException(source, target); + } + } + if (copyAttributes) { + // CopyFileEx does not copy security attributes + try { + copySecurityAttributes(source, target, followLinks); + } catch (IOException x) { + // ignore + } + } + return; + } + + // copy directory or directory junction + try { + if (sourceAttrs.isDirectory()) { + CreateDirectory(targetPath, 0L); + } else { + String linkTarget = WindowsLinkSupport.readLink(source); + int flags = SYMBOLIC_LINK_FLAG_DIRECTORY; + CreateSymbolicLink(targetPath, + addPrefixIfNeeded(linkTarget), + flags); + } + } catch (WindowsException x) { + x.rethrowAsIOException(target); + } + if (copyAttributes) { + // copy DOS/timestamps attributes + WindowsFileAttributeViews.Dos view = + WindowsFileAttributeViews.createDosView(target, false); + try { + view.setAttributes(sourceAttrs); + } catch (IOException x) { + if (sourceAttrs.isDirectory()) { + try { + RemoveDirectory(targetPath); + } catch (WindowsException ignore) { } + } + } + + // copy security attributes. If this fail it doesn't cause the move + // to fail. + try { + copySecurityAttributes(source, target, followLinks); + } catch (IOException ignore) { } + } + } + + /** + * Move file from source to target + */ + static void move(WindowsPath source, WindowsPath target, CopyOption... options) + throws IOException + { + // map options + boolean atomicMove = false; + boolean replaceExisting = false; + for (CopyOption option: options) { + if (option == StandardCopyOption.ATOMIC_MOVE) { + atomicMove = true; + continue; + } + if (option == StandardCopyOption.REPLACE_EXISTING) { + replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + // ignore + continue; + } + if (option == null) throw new NullPointerException(); + throw new UnsupportedOperationException("Unsupported copy option"); + } + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + source.checkWrite(); + target.checkWrite(); + } + + final String sourcePath = asWin32Path(source); + final String targetPath = asWin32Path(target); + + // atomic case + if (atomicMove) { + try { + MoveFileEx(sourcePath, targetPath, MOVEFILE_REPLACE_EXISTING); + } catch (WindowsException x) { + if (x.lastError() == ERROR_NOT_SAME_DEVICE) { + throw new AtomicMoveNotSupportedException( + source.getPathForExceptionMessage(), + target.getPathForExceptionMessage(), + x.errorString()); + } + x.rethrowAsIOException(source, target); + } + return; + } + + // get attributes of source file + // attempt to get attributes of target file + // if both files are the same there is nothing to do + // if target exists and !replace then throw exception + + WindowsFileAttributes sourceAttrs = null; + WindowsFileAttributes targetAttrs = null; + + long sourceHandle = 0L; + try { + sourceHandle = source.openForReadAttributeAccess(false); + } catch (WindowsException x) { + x.rethrowAsIOException(source); + } + try { + // source attributes + try { + sourceAttrs = WindowsFileAttributes.readAttributes(sourceHandle); + } catch (WindowsException x) { + x.rethrowAsIOException(source); + } + + // open target (don't follow links) + long targetHandle = 0L; + try { + targetHandle = target.openForReadAttributeAccess(false); + try { + targetAttrs = WindowsFileAttributes.readAttributes(targetHandle); + + // if both files are the same then nothing to do + if (WindowsFileAttributes.isSameFile(sourceAttrs, targetAttrs)) { + return; + } + + // can't replace file + if (!replaceExisting) { + throw new FileAlreadyExistsException( + target.getPathForExceptionMessage()); + } + + } finally { + CloseHandle(targetHandle); + } + } catch (WindowsException x) { + // ignore + } + + } finally { + CloseHandle(sourceHandle); + } + + // if target exists then delete it. + if (targetAttrs != null) { + try { + if (targetAttrs.isDirectory() || targetAttrs.isDirectoryLink()) { + RemoveDirectory(targetPath); + } else { + DeleteFile(targetPath); + } + } catch (WindowsException x) { + if (targetAttrs.isDirectory()) { + // ERROR_ALREADY_EXISTS is returned when attempting to delete + // non-empty directory on SAMBA servers. + if (x.lastError() == ERROR_DIR_NOT_EMPTY || + x.lastError() == ERROR_ALREADY_EXISTS) + { + throw new FileAlreadyExistsException( + target.getPathForExceptionMessage()); + } + } + x.rethrowAsIOException(target); + } + } + + // first try MoveFileEx (no options). If target is on same volume then + // all attributes (including security attributes) are preserved. + try { + MoveFileEx(sourcePath, targetPath, 0); + return; + } catch (WindowsException x) { + if (x.lastError() != ERROR_NOT_SAME_DEVICE) + x.rethrowAsIOException(source, target); + } + + // target is on different volume so use MoveFileEx with copy option + if (!sourceAttrs.isDirectory() && !sourceAttrs.isDirectoryLink()) { + try { + MoveFileEx(sourcePath, targetPath, MOVEFILE_COPY_ALLOWED); + } catch (WindowsException x) { + x.rethrowAsIOException(source, target); + } + // MoveFileEx does not copy security attributes when moving + // across volumes. + try { + copySecurityAttributes(source, target, false); + } catch (IOException x) { + // ignore + } + return; + } + + // moving directory or directory-link to another file system + assert sourceAttrs.isDirectory() || sourceAttrs.isDirectoryLink(); + + // create new directory or directory junction + try { + if (sourceAttrs.isDirectory()) { + CreateDirectory(targetPath, 0L); + } else { + String linkTarget = WindowsLinkSupport.readLink(source); + CreateSymbolicLink(targetPath, + addPrefixIfNeeded(linkTarget), + SYMBOLIC_LINK_FLAG_DIRECTORY); + } + } catch (WindowsException x) { + x.rethrowAsIOException(target); + } + + // copy timestamps/DOS attributes + WindowsFileAttributeViews.Dos view = + WindowsFileAttributeViews.createDosView(target, false); + try { + view.setAttributes(sourceAttrs); + } catch (IOException x) { + // rollback + try { + RemoveDirectory(targetPath); + } catch (WindowsException ignore) { } + throw x; + } + + // copy security attributes. If this fails it doesn't cause the move + // to fail. + try { + copySecurityAttributes(source, target, false); + } catch (IOException ignore) { } + + // delete source + try { + RemoveDirectory(sourcePath); + } catch (WindowsException x) { + // rollback + try { + RemoveDirectory(targetPath); + } catch (WindowsException ignore) { } + // ERROR_ALREADY_EXISTS is returned when attempting to delete + // non-empty directory on SAMBA servers. + if (x.lastError() == ERROR_DIR_NOT_EMPTY || + x.lastError() == ERROR_ALREADY_EXISTS) + { + throw new DirectoryNotEmptyException( + target.getPathForExceptionMessage()); + } + x.rethrowAsIOException(source); + } + } + + + private static String asWin32Path(WindowsPath path) throws IOException { + try { + return path.getPathForWin32Calls(); + } catch (WindowsException x) { + x.rethrowAsIOException(path); + return null; + } + } + + /** + * Copy DACL/owner/group from source to target + */ + private static void copySecurityAttributes(WindowsPath source, + WindowsPath target, + boolean followLinks) + throws IOException + { + String path = WindowsLinkSupport.getFinalPath(source, followLinks); + + // may need SeRestorePrivilege to set file owner + WindowsSecurity.Privilege priv = + WindowsSecurity.enablePrivilege("SeRestorePrivilege"); + try { + int request = (DACL_SECURITY_INFORMATION | + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION); + NativeBuffer buffer = + WindowsAclFileAttributeView.getFileSecurity(path, request); + try { + try { + SetFileSecurity(target.getPathForWin32Calls(), request, + buffer.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(target); + } + } finally { + buffer.release(); + } + } finally { + priv.drop(); + } + } + + /** + * Add long path prefix to path if required + */ + private static String addPrefixIfNeeded(String path) { + if (path.length() > 248) { + if (path.startsWith("\\\\")) { + path = "\\\\?\\UNC" + path.substring(1, path.length()); + } else { + path = "\\\\?\\" + path; + } + } + return path; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java new file mode 100644 index 00000000000..5d3a0af2533 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java @@ -0,0 +1,337 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; + +import static sun.nio.fs.WindowsConstants.*; +import static sun.nio.fs.WindowsNativeDispatcher.*; + +/** + * Windows implementation of FileStore. + */ + +class WindowsFileStore + extends FileStore +{ + private final String root; + private final VolumeInformation volInfo; + private final int volType; + private final String displayName; // returned by toString + + private WindowsFileStore(String root) throws WindowsException { + assert root.charAt(root.length()-1) == '\\'; + this.root = root; + this.volInfo = GetVolumeInformation(root); + this.volType = GetDriveType(root); + + // file store "display name" is the volume name if available + String vol = volInfo.volumeName(); + if (vol.length() > 0) { + this.displayName = vol; + } else { + // TBD - should we map all types? Does this need to be localized? + this.displayName = (volType == DRIVE_REMOVABLE) ? "Removable Disk" : ""; + } + } + + static WindowsFileStore create(String root, boolean ignoreNotReady) + throws IOException + { + try { + return new WindowsFileStore(root); + } catch (WindowsException x) { + if (ignoreNotReady && x.lastError() == ERROR_NOT_READY) + return null; + x.rethrowAsIOException(root); + return null; // keep compiler happy + } + } + + static WindowsFileStore create(WindowsPath file) throws IOException { + try { + // if the file is a link then GetVolumePathName returns the + // volume that the link is on so we need to call it with the + // final target + String target; + if (file.getFileSystem().supportsLinks()) { + target = WindowsLinkSupport.getFinalPath(file, true); + } else { + // file must exist + WindowsFileAttributes.get(file, true); + target = file.getPathForWin32Calls(); + } + String root = GetVolumePathName(target); + return new WindowsFileStore(root); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } + + VolumeInformation volumeInformation() { + return volInfo; + } + + int volumeType() { + return volType; + } + + @Override + public String name() { + return volInfo.volumeName(); // "SYSTEM", "DVD-RW", ... + } + + @Override + public String type() { + return volInfo.fileSystemName(); // "FAT", "NTFS", ... + } + + @Override + public boolean isReadOnly() { + return ((volInfo.flags() & FILE_READ_ONLY_VOLUME) != 0); + } + + @Override + @SuppressWarnings("unchecked") + public V getFileStoreAttributeView(Class view) { + if (view == FileStoreSpaceAttributeView.class) + return (V) new WindowsFileStoreAttributeView(this); + return (V) null; + } + + @Override + public FileStoreAttributeView getFileStoreAttributeView(String name) { + if (name.equals("space")) + return new WindowsFileStoreAttributeView(this); + if (name.equals("volume")) + return new VolumeFileStoreAttributeView(this); + return null; + } + + @Override + public boolean supportsFileAttributeView(Class type) { + if (type == BasicFileAttributeView.class) + return true; + if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class) + return ((volInfo.flags() & FILE_PERSISTENT_ACLS) != 0); + if (type == UserDefinedFileAttributeView.class) + return ((volInfo.flags() & FILE_NAMED_STREAMS) != 0); + return false; + } + + @Override + public boolean supportsFileAttributeView(String name) { + if (name.equals("basic") || name.equals("dos")) + return true; + if (name.equals("acl")) + return supportsFileAttributeView(AclFileAttributeView.class); + if (name.equals("owner")) + return supportsFileAttributeView(FileOwnerAttributeView.class); + if (name.equals("xattr")) + return supportsFileAttributeView(UserDefinedFileAttributeView.class); + return false; + } + + @Override + public boolean equals(Object ob) { + if (ob == this) + return true; + if (!(ob instanceof WindowsFileStore)) + return false; + WindowsFileStore other = (WindowsFileStore)ob; + return this.volInfo.volumeSerialNumber() == other.volInfo.volumeSerialNumber(); + } + + @Override + public int hashCode() { + // reveals VSN without permission check - okay? + return volInfo.volumeSerialNumber(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(displayName); + if (sb.length() > 0) + sb.append(" "); + sb.append("("); + // drop trailing slash + sb.append(root.subSequence(0, root.length()-1)); + sb.append(")"); + return sb.toString(); + } + + static class WindowsFileStoreAttributeView + extends AbstractFileStoreSpaceAttributeView + { + private final WindowsFileStore fs; + + WindowsFileStoreAttributeView(WindowsFileStore fs) { + this.fs = fs; + } + + @Override + public FileStoreSpaceAttributes readAttributes() + throws IOException + { + // read the free space info + DiskFreeSpace info = null; + try { + info = GetDiskFreeSpaceEx(fs.root); + } catch (WindowsException x) { + x.rethrowAsIOException(fs.root); + } + + final DiskFreeSpace result = info; + return new FileStoreSpaceAttributes() { + @Override + public long totalSpace() { + return result.totalNumberOfBytes(); + } + @Override + public long usableSpace() { + return result.freeBytesAvailable(); + } + @Override + public long unallocatedSpace() { + return result.totalNumberOfFreeBytes(); + } + }; + } + } + + /** + * Windows-specific attribute view to allow access to volume information. + */ + static class VolumeFileStoreAttributeView + implements FileStoreAttributeView + { + private static final String VSN_NAME = "vsn"; + private static final String COMPRESSED_NAME = "compressed"; + private static final String REMOVABLE_NAME = "removable"; + private static final String CDROM_NAME = "cdrom"; + + private final WindowsFileStore fs; + + VolumeFileStoreAttributeView(WindowsFileStore fs) { + this.fs = fs; + } + + @Override + public String name() { + return "volume"; + } + + private int vsn() { + return fs.volumeInformation().volumeSerialNumber(); + } + + private boolean isCompressed() { + return (fs.volumeInformation().flags() & + FILE_VOLUME_IS_COMPRESSED) > 0; + } + + private boolean isRemovable() { + return fs.volumeType() == DRIVE_REMOVABLE; + } + + private boolean isCdrom() { + return fs.volumeType() == DRIVE_CDROM; + } + + @Override + public Object getAttribute(String attribute) throws IOException { + if (attribute.equals(VSN_NAME)) + return vsn(); + if (attribute.equals(COMPRESSED_NAME)) + return isCompressed(); + if (attribute.equals(REMOVABLE_NAME)) + return isRemovable(); + if (attribute.equals(CDROM_NAME)) + return isCdrom(); + return null; + } + + @Override + public void setAttribute(String attribute, Object value) + throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public Map readAttributes(String first, String... rest) + throws IOException + { + boolean all = false; + boolean vsn = false; + boolean compressed = false; + boolean removable = false; + boolean cdrom = false; + + if (first.equals(VSN_NAME)) vsn = true; + else if (first.equals(COMPRESSED_NAME)) compressed = true; + else if (first.equals(REMOVABLE_NAME)) removable = true; + else if (first.equals(CDROM_NAME)) cdrom = true; + else if (first.equals("*")) all = true; + + if (!all) { + for (String attribute: rest) { + if (attribute.equals("*")) { + all = true; + break; + } + if (attribute.equals(VSN_NAME)) { + vsn = true; + continue; + } + if (attribute.equals(COMPRESSED_NAME)) { + compressed = true; + continue; + } + if (attribute.equals(REMOVABLE_NAME)) { + removable = true; + continue; + } + } + } + + Map result = new HashMap(); + if (all || vsn) + result.put(VSN_NAME, vsn()); + if (all || compressed) + result.put(COMPRESSED_NAME, isCompressed()); + if (all || removable) + result.put(REMOVABLE_NAME, isRemovable()); + if (all || cdrom) + result.put(CDROM_NAME, isCdrom()); + return result; + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java new file mode 100644 index 00000000000..e80c829f311 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -0,0 +1,317 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.*; +import java.util.*; +import java.util.regex.Pattern; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + +class WindowsFileSystem + extends FileSystem +{ + private final WindowsFileSystemProvider provider; + + // default directory (is absolute), and default root + private final String defaultDirectory; + private final String defaultRoot; + + private final boolean supportsLinks; + private final boolean supportsStreamEnumeration; + + // package-private + WindowsFileSystem(WindowsFileSystemProvider provider, + String dir) + { + this.provider = provider; + + // parse default directory and check it is absolute + WindowsPathParser.Result result = WindowsPathParser.parse(dir); + + if (result.type() != WindowsPathType.ABSOLUTE) + throw new AssertionError("Default directory must be absolute/non-UNC"); + this.defaultDirectory = result.path(); + this.defaultRoot = result.root(); + + PrivilegedAction pa = new GetPropertyAction("os.version"); + String osversion = AccessController.doPrivileged(pa); + String[] vers = osversion.split("\\.", 0); + int major = Integer.parseInt(vers[0]); + int minor = Integer.parseInt(vers[1]); + + // symbolic links available on Vista and newer + supportsLinks = (major >= 6); + + // enumeration of data streams available on Windows Server 2003 and newer + supportsStreamEnumeration = (major >= 6) || (major == 5 && minor >= 2); + } + + // package-private + String defaultDirectory() { + return defaultDirectory; + } + + String defaultRoot() { + return defaultRoot; + } + + boolean supportsLinks() { + return supportsLinks; + } + + boolean supportsStreamEnumeration() { + return supportsStreamEnumeration; + } + + @Override + public FileSystemProvider provider() { + return provider; + } + + @Override + public String getSeparator() { + return "\\"; + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public boolean isReadOnly() { + return false; + } + + @Override + public void close() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public Iterable getRootDirectories() { + int drives = 0; + try { + drives = WindowsNativeDispatcher.GetLogicalDrives(); + } catch (WindowsException x) { + // shouldn't happen + throw new AssertionError(x.getMessage()); + } + + // iterate over roots, ignoring those that the security manager denies + ArrayList result = new ArrayList(); + SecurityManager sm = System.getSecurityManager(); + for (int i = 0; i <= 25; i++) { // 0->A, 1->B, 2->C... + if ((drives & (1 << i)) != 0) { + StringBuilder sb = new StringBuilder(3); + sb.append((char)('A' + i)); + sb.append(":\\"); + String root = sb.toString(); + if (sm != null) { + try { + sm.checkRead(root); + } catch (SecurityException x) { + continue; + } + } + result.add(WindowsPath.createFromNormalizedPath(this, root)); + } + } + return Collections.unmodifiableList(result); + } + + /** + * Iterator returned by getFileStores method. + */ + private class FileStoreIterator implements Iterator { + private final Iterator roots; + private FileStore next; + + FileStoreIterator() { + this.roots = getRootDirectories().iterator(); + } + + private FileStore readNext() { + assert Thread.holdsLock(this); + for (;;) { + if (!roots.hasNext()) + return null; + WindowsPath root = (WindowsPath)roots.next(); + // ignore if security manager denies access + try { + root.checkRead(); + } catch (SecurityException x) { + continue; + } + try { + FileStore fs = WindowsFileStore.create(root.toString(), true); + if (fs != null) + return fs; + } catch (IOException ioe) { + // skip it + } + } + } + + @Override + public synchronized boolean hasNext() { + if (next != null) + return true; + next = readNext(); + return next != null; + } + + @Override + public synchronized FileStore next() { + if (next == null) + next = readNext(); + if (next == null) { + throw new NoSuchElementException(); + } else { + FileStore result = next; + next = null; + return result; + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public Iterable getFileStores() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + } catch (SecurityException se) { + return Collections.emptyList(); + } + } + return new Iterable() { + public Iterator iterator() { + return new FileStoreIterator(); + } + }; + } + + // supported views + private static final Set supportedFileAttributeViews = Collections + .unmodifiableSet(new HashSet(Arrays.asList("basic", "dos", "acl", "owner", "xattr"))); + + @Override + public Set supportedFileAttributeViews() { + return supportedFileAttributeViews; + } + + @Override + public Path getPath(String path) { + return WindowsPath.parse(this, path); + } + + @Override + public UserPrincipalLookupService getUserPrincipalLookupService() { + return theLookupService; + } + + private static final UserPrincipalLookupService theLookupService = + new UserPrincipalLookupService() { + @Override + public UserPrincipal lookupPrincipalByName(String name) + throws IOException + { + return WindowsUserPrincipals.lookup(name); + } + @Override + public GroupPrincipal lookupPrincipalByGroupName(String group) + throws IOException + { + UserPrincipal user = WindowsUserPrincipals.lookup(group); + if (!(user instanceof GroupPrincipal)) + throw new UserPrincipalNotFoundException(group); + return (GroupPrincipal)user; + } + }; + + @Override + public PathMatcher getPathMatcher(String syntaxAndInput) { + int pos = syntaxAndInput.indexOf(':'); + if (pos <= 0 || pos == syntaxAndInput.length()) + throw new IllegalArgumentException(); + String syntax = syntaxAndInput.substring(0, pos); + String input = syntaxAndInput.substring(pos+1); + + String expr; + if (syntax.equals(GLOB_SYNTAX)) { + expr = Globs.toWindowsRegexPattern(input); + } else { + if (syntax.equals(REGEX_SYNTAX)) { + expr = input; + } else { + throw new UnsupportedOperationException("Syntax '" + syntax + + "' not recognized"); + } + } + + // match in uppercase + StringBuilder sb = new StringBuilder(expr.length()); + for (int i=0; i env) + throws IOException + { + checkUri(uri); + throw new FileSystemAlreadyExistsException(); + } + + @Override + public final FileSystem getFileSystem(URI uri) { + checkUri(uri); + return theFileSystem; + } + + @Override + public Path getPath(URI uri) { + return WindowsUriSupport.fromUri(theFileSystem, uri); + } + + @Override + public FileChannel newFileChannel(Path path, + Set options, + FileAttribute... attrs) + throws IOException + { + if (path == null) + throw new NullPointerException(); + if (!(path instanceof WindowsPath)) + throw new ProviderMismatchException(); + WindowsPath file = (WindowsPath)path; + + WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs); + try { + return WindowsChannelFactory + .newFileChannel(file.getPathForWin32Calls(), + file.getPathForPermissionCheck(), + options, + sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; + } finally { + if (sd != null) + sd.release(); + } + } + + @Override + public AsynchronousFileChannel newAsynchronousFileChannel(Path path, + Set options, + ExecutorService executor, + FileAttribute... attrs) + throws IOException + { + if (path == null) + throw new NullPointerException(); + if (!(path instanceof WindowsPath)) + throw new ProviderMismatchException(); + WindowsPath file = (WindowsPath)path; + ThreadPool pool = (executor == null) ? null : ThreadPool.wrap(executor, 0); + WindowsSecurityDescriptor sd = + WindowsSecurityDescriptor.fromAttribute(attrs); + try { + return WindowsChannelFactory + .newAsynchronousFileChannel(file.getPathForWin32Calls(), + file.getPathForPermissionCheck(), + options, + sd.address(), + pool); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; + } finally { + if (sd != null) + sd.release(); + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java new file mode 100644 index 00000000000..516275dfe55 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java @@ -0,0 +1,446 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; +import java.io.IOError; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.misc.Unsafe; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Utility methods for symbolic link support on Windows Vista and newer. + */ + +class WindowsLinkSupport { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private WindowsLinkSupport() { + } + + /** + * Returns the target of a symbolic link + */ + static String readLink(WindowsPath path) throws IOException { + long handle = 0L; + try { + handle = path.openForReadAttributeAccess(false); // don't follow links + } catch (WindowsException x) { + x.rethrowAsIOException(path); + } + try { + return readLinkImpl(handle); + } finally { + CloseHandle(handle); + } + } + + /** + * Returns the final path of a given path as a String. This should be used + * prior to calling Win32 system calls that do not follow links. + */ + static String getFinalPath(WindowsPath input, boolean followLinks) + throws IOException + { + WindowsFileSystem fs = input.getFileSystem(); + + try { + // if not following links then don't need final path + if (!followLinks || !fs.supportsLinks()) + return input.getPathForWin32Calls(); + + // if file is a sym link then don't need final path + if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) { + return input.getPathForWin32Calls(); + } + } catch (WindowsException x) { + x.rethrowAsIOException(input); + } + + // The file is a symbolic link so we open it and try to get the + // normalized path. This should succeed on NTFS but may fail if there + // is a link to a non-NFTS file system. + long h = 0; + try { + h = input.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(input); + } + try { + return stripPrefix(GetFinalPathNameByHandle(h)); + } catch (WindowsException x) { + // ERROR_INVALID_LEVEL is the error returned when not supported by + // the file system + if (x.lastError() != ERROR_INVALID_LEVEL) + x.rethrowAsIOException(input); + } finally { + CloseHandle(h); + } + + // Fallback: read target of link, resolve against parent, and repeat + // until file is not a link. + WindowsPath target = input; + int linkCount = 0; + do { + try { + WindowsFileAttributes attrs = + WindowsFileAttributes.get(target, false); + // non a link so we are done + if (!attrs.isSymbolicLink()) { + return target.getPathForWin32Calls(); + } + } catch (WindowsException x) { + x.rethrowAsIOException(target); + } + WindowsPath link = WindowsPath + .createFromNormalizedPath(fs, readLink(target)); + WindowsPath parent = target.getParent(); + if (parent == null) { + // no parent so use parent of absolute path + final WindowsPath t = target; + target = AccessController + .doPrivileged(new PrivilegedAction() { + @Override + public WindowsPath run() { + return t.toAbsolutePath(); + }}); + parent = target.getParent(); + } + target = parent.resolve(link); + + } while (++linkCount < 32); + + throw new FileSystemException(input.getPathForExceptionMessage(), null, + "Too many links"); + } + + /** + * Returns the actual path of a file, optionally resolving all symbolic + * links. + */ + static String getRealPath(WindowsPath input, boolean resolveLinks) + throws IOException + { + WindowsFileSystem fs = input.getFileSystem(); + if (!fs.supportsLinks()) + resolveLinks = false; + + // On Vista use GetFinalPathNameByHandle. This should succeed on NTFS + // but may fail if there is a link to a non-NFTS file system. + if (resolveLinks) { + long h = 0; + try { + h = input.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(input); + } + try { + return stripPrefix(GetFinalPathNameByHandle(h)); + } catch (WindowsException x) { + if (x.lastError() != ERROR_INVALID_LEVEL) + x.rethrowAsIOException(input); + } finally { + CloseHandle(h); + } + } + + // Not resolving links or we are on Windows Vista (or newer) with a + // link to non-NFTS file system. + + // Start with absolute path + String path = null; + try { + path = input.toAbsolutePath().toString(); + } catch (IOError x) { + throw (IOException)(x.getCause()); + } + + // Collapse "." and ".." + try { + path = GetFullPathName(path); + } catch (WindowsException x) { + x.rethrowAsIOException(input); + } + + // eliminate all symbolic links + if (resolveLinks) { + path = resolveAllLinks(WindowsPath.createFromNormalizedPath(fs, path)); + } + + // string builder to build up components of path + StringBuilder sb = new StringBuilder(path.length()); + + // Copy root component + int start; + char c0 = path.charAt(0); + char c1 = path.charAt(1); + if ((c0 <= 'z' && c0 >= 'a' || c0 <= 'Z' && c0 >= 'A') && + c1 == ':' && path.charAt(2) == '\\') { + // Driver specifier + sb.append(Character.toUpperCase(c0)); + sb.append(":\\"); + start = 3; + } else if (c0 == '\\' && c1 == '\\') { + // UNC pathname, begins with "\\\\host\\share" + int last = path.length() - 1; + int pos = path.indexOf('\\', 2); + // skip both server and share names + if (pos == -1 || (pos == last)) { + // The UNC does not have a share name (collapsed by GetFullPathName) + throw new FileSystemException(input.getPathForExceptionMessage(), + null, "UNC has invalid share"); + } + pos = path.indexOf('\\', pos+1); + if (pos < 0) { + pos = last; + sb.append(path).append("\\"); + } else { + sb.append(path, 0, pos+1); + } + start = pos + 1; + } else { + throw new AssertionError("path type not recognized"); + } + + // check root directory exists + try { + FirstFile fileData = FindFirstFile(sb.toString() + "*"); + FindClose(fileData.handle()); + } catch (WindowsException x) { + x.rethrowAsIOException(path); + } + + // iterate through each component to get its actual name in the + // directory + int curr = start; + while (curr < path.length()) { + int next = path.indexOf('\\', curr); + int end = (next == -1) ? path.length() : next; + String search = sb.toString() + path.substring(curr, end); + try { + FirstFile fileData = FindFirstFile(addLongPathPrefixIfNeeded(search)); + try { + sb.append(fileData.name()); + if (next != -1) { + sb.append('\\'); + } + } finally { + FindClose(fileData.handle()); + } + } catch (WindowsException e) { + e.rethrowAsIOException(path); + } + curr = end + 1; + } + + return sb.toString(); + } + + /** + * Returns target of a symbolic link given the handle of an open file + * (that should be a link). + */ + private static String readLinkImpl(long handle) throws IOException { + int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + try { + DeviceIoControlGetReparsePoint(handle, buffer.address(), size); + } catch (WindowsException x) { + // FIXME: exception doesn't have file name + if (x.lastError() == ERROR_NOT_A_REPARSE_POINT) + throw new NotLinkException(null, null, x.errorString()); + x.rethrowAsIOException((String)null); + } + + /* + * typedef struct _REPARSE_DATA_BUFFER { + * ULONG ReparseTag; + * USHORT ReparseDataLength; + * USHORT Reserved; + * union { + * struct { + * USHORT SubstituteNameOffset; + * USHORT SubstituteNameLength; + * USHORT PrintNameOffset; + * USHORT PrintNameLength; + * WCHAR PathBuffer[1]; + * } SymbolicLinkReparseBuffer; + * struct { + * USHORT SubstituteNameOffset; + * USHORT SubstituteNameLength; + * USHORT PrintNameOffset; + * USHORT PrintNameLength; + * WCHAR PathBuffer[1]; + * } MountPointReparseBuffer; + * struct { + * UCHAR DataBuffer[1]; + * } GenericReparseBuffer; + * }; + * } REPARSE_DATA_BUFFER + */ + final short OFFSETOF_REPARSETAG = 0; + final short OFFSETOF_PATHOFFSET = 8; + final short OFFSETOF_PATHLENGTH = 10; + final short OFFSETOF_PATHBUFFER = 16 + 4; // check this + + int tag = (int)unsafe.getLong(buffer.address() + OFFSETOF_REPARSETAG); + if (tag != IO_REPARSE_TAG_SYMLINK) { + // FIXME: exception doesn't have file name + throw new NotLinkException(null, null, "Reparse point is not a symbolic link"); + } + + // get offset and length of target + short nameOffset = unsafe.getShort(buffer.address() + OFFSETOF_PATHOFFSET); + short nameLengthInBytes = unsafe.getShort(buffer.address() + OFFSETOF_PATHLENGTH); + if ((nameLengthInBytes % 2) != 0) + throw new FileSystemException(null, null, "Symbolic link corrupted"); + + // copy into char array + char[] name = new char[nameLengthInBytes/2]; + unsafe.copyMemory(null, buffer.address() + OFFSETOF_PATHBUFFER + nameOffset, + name, Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes); + + // remove special prefix + String target = stripPrefix(new String(name)); + if (target.length() == 0) { + throw new IOException("Symbolic link target is invalid"); + } + return target; + } finally { + buffer.release(); + } + } + + /** + * Resolve all symbolic-links in a given absolute and normalized path + */ + private static String resolveAllLinks(WindowsPath path) + throws IOException + { + assert path.isAbsolute(); + WindowsFileSystem fs = path.getFileSystem(); + + // iterate through each name element of the path, resolving links as + // we go. + int linkCount = 0; + int elem = 0; + while (elem < path.getNameCount()) { + WindowsPath current = path.getRoot().resolve(path.subpath(0, elem+1)); + + WindowsFileAttributes attrs = null; + try { + attrs = WindowsFileAttributes.get(current, false); + } catch (WindowsException x) { + x.rethrowAsIOException(current); + } + + /** + * If a symbolic link then we resolve it against the parent + * of the current name element. We then resolve any remaining + * part of the path against the result. The target of the link + * may have "." and ".." components so re-normalize and restart + * the process from the first element. + */ + if (attrs.isSymbolicLink()) { + linkCount++; + if (linkCount > 32) + throw new IOException("Too many links"); + WindowsPath target = WindowsPath + .createFromNormalizedPath(fs, readLink(current)); + WindowsPath remainder = null; + int count = path.getNameCount(); + if ((elem+1) < count) { + remainder = path.subpath(elem+1, count); + } + path = current.getParent().resolve(target); + try { + String full = GetFullPathName(path.toString()); + if (!full.equals(path.toString())) { + path = WindowsPath.createFromNormalizedPath(fs, full); + } + } catch (WindowsException x) { + x.rethrowAsIOException(path); + } + if (remainder != null) { + path = path.resolve(remainder); + } + + // reset + elem = 0; + } else { + // not a link + elem++; + } + } + + return path.toString(); + } + + /** + * Add long path prefix to path if required. + */ + private static String addLongPathPrefixIfNeeded(String path) { + if (path.length() > 248) { + if (path.startsWith("\\\\")) { + path = "\\\\?\\UNC" + path.substring(1, path.length()); + } else { + path = "\\\\?\\" + path; + } + } + return path; + } + + /** + * Strip long path or symbolic link prefix from path + */ + private static String stripPrefix(String path) { + // prefix for resolved/long path + if (path.startsWith("\\\\?\\")) { + if (path.startsWith("\\\\?\\UNC\\")) { + path = "\\" + path.substring(7); + } else { + path = path.substring(4); + } + return path; + } + + // prefix for target of symbolic link + if (path.startsWith("\\??\\")) { + if (path.startsWith("\\??\\UNC\\")) { + path = "\\" + path.substring(7); + } else { + path = path.substring(4); + } + return path; + } + return path; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java new file mode 100644 index 00000000000..fafee20a4cd --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java @@ -0,0 +1,1134 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.misc.Unsafe; + +/** + * Win32 and library calls. + */ + +class WindowsNativeDispatcher { + private WindowsNativeDispatcher() { } + + /** + * HANDLE CreateFile( + * LPCTSTR lpFileName, + * DWORD dwDesiredAccess, + * DWORD dwShareMode, + * LPSECURITY_ATTRIBUTES lpSecurityAttributes, + * DWORD dwCreationDisposition, + * DWORD dwFlagsAndAttributes, + * HANDLE hTemplateFile + * ) + */ + static long CreateFile(String path, + int dwDesiredAccess, + int dwShareMode, + long lpSecurityAttributes, + int dwCreationDisposition, + int dwFlagsAndAttributes) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(path); + try { + return CreateFile0(buffer.address(), + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes); + } finally { + buffer.release(); + } + } + static long CreateFile(String path, + int dwDesiredAccess, + int dwShareMode, + int dwCreationDisposition, + int dwFlagsAndAttributes) + throws WindowsException + { + return CreateFile(path, dwDesiredAccess, dwShareMode, 0L, + dwCreationDisposition, dwFlagsAndAttributes); + } + private static native long CreateFile0(long lpFileName, + int dwDesiredAccess, + int dwShareMode, + long lpSecurityAttributes, + int dwCreationDisposition, + int dwFlagsAndAttributes) + throws WindowsException; + + /** + * CloseHandle( + * HANDLE hObject + * ) + */ + static native void CloseHandle(long handle); + + /** + * DeleteFile( + * LPCTSTR lpFileName + * ) + */ + static void DeleteFile(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + DeleteFile0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native void DeleteFile0(long lpFileName) + throws WindowsException; + + /** + * CreateDirectory( + * LPCTSTR lpPathName, + * LPSECURITY_ATTRIBUTES lpSecurityAttributes + * ) + */ + static void CreateDirectory(String path, long lpSecurityAttributes) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + CreateDirectory0(buffer.address(), lpSecurityAttributes); + } finally { + buffer.release(); + } + } + private static native void CreateDirectory0(long lpFileName, long lpSecurityAttributes) + throws WindowsException; + + /** + * RemoveDirectory( + * LPCTSTR lpPathName + * ) + */ + static void RemoveDirectory(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + RemoveDirectory0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native void RemoveDirectory0(long lpFileName) + throws WindowsException; + + /** + * Marks a file as a sparse file. + * + * DeviceIoControl( + * FSCTL_SET_SPARSE + * ) + */ + static native void DeviceIoControlSetSparse(long handle) + throws WindowsException; + + /** + * Retrieves the reparse point data associated with the file or directory. + * + * DeviceIoControl( + * FSCTL_GET_REPARSE_POINT + * ) + */ + static native void DeviceIoControlGetReparsePoint(long handle, + long bufferAddress, int bufferSize) throws WindowsException; + + /** + * HANDLE FindFirstFile( + * LPCTSTR lpFileName, + * LPWIN32_FIND_DATA lpFindFileData + * ) + */ + static FirstFile FindFirstFile(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + FirstFile data = new FirstFile(); + FindFirstFile0(buffer.address(), data); + return data; + } finally { + buffer.release(); + } + } + static class FirstFile { + private long handle; + private String name; + + private FirstFile() { } + public long handle() { return handle; } + public String name() { return name; } + } + private static native void FindFirstFile0(long lpFileName, FirstFile obj) + throws WindowsException; + + /** + * HANDLE FindFirstFile( + * LPCTSTR lpFileName, + * LPWIN32_FIND_DATA lpFindFileData + * ) + */ + static long FindFirstFile(String path, long address) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + return FindFirstFile1(buffer.address(), address); + } finally { + buffer.release(); + } + } + private static native long FindFirstFile1(long lpFileName, long address) + throws WindowsException; + + /** + * FindNextFile( + * HANDLE hFindFile, + * LPWIN32_FIND_DATA lpFindFileData + * ) + * + * @return lpFindFileData->cFileName or null + */ + static native String FindNextFile(long handle, long address) + throws WindowsException; + + /** + * HANDLE FindFirstStreamW( + * LPCWSTR lpFileName, + * STREAM_INFO_LEVELS InfoLevel, + * LPVOID lpFindStreamData, + * DWORD dwFlags + * ) + */ + static FirstStream FindFirstStream(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + FirstStream data = new FirstStream(); + FindFirstStream0(buffer.address(), data); + if (data.handle() == WindowsConstants.INVALID_HANDLE_VALUE) + return null; + return data; + } finally { + buffer.release(); + } + } + static class FirstStream { + private long handle; + private String name; + + private FirstStream() { } + public long handle() { return handle; } + public String name() { return name; } + } + private static native void FindFirstStream0(long lpFileName, FirstStream obj) + throws WindowsException; + + /* + * FindNextStreamW( + * HANDLE hFindStream, + * LPVOID lpFindStreamData + * ) + */ + static native String FindNextStream(long handle) throws WindowsException; + + /** + * FindClose( + * HANDLE hFindFile + * ) + */ + static native void FindClose(long handle) throws WindowsException; + + /** + * GetFileInformationByHandle( + * HANDLE hFile, + * LPBY_HANDLE_FILE_INFORMATION lpFileInformation + * ) + */ + static native void GetFileInformationByHandle(long handle, long address) + throws WindowsException; + + /** + * CopyFileEx( + * LPCWSTR lpExistingFileName + * LPCWSTR lpNewFileName, + * LPPROGRESS_ROUTINE lpProgressRoutine + * LPVOID lpData, + * LPBOOL pbCancel, + * DWORD dwCopyFlags + * ) + */ + static void CopyFileEx(String source, String target, int flags, + long addressToPollForCancel) + throws WindowsException + { + NativeBuffer sourceBuffer = asNativeBuffer(source); + NativeBuffer targetBuffer = asNativeBuffer(target); + try { + CopyFileEx0(sourceBuffer.address(), targetBuffer.address(), flags, + addressToPollForCancel); + } finally { + targetBuffer.release(); + sourceBuffer.release(); + } + } + private static native void CopyFileEx0(long existingAddress, long newAddress, + int flags, long addressToPollForCancel) throws WindowsException; + + /** + * MoveFileEx( + * LPCTSTR lpExistingFileName, + * LPCTSTR lpNewFileName, + * DWORD dwFlags + * ) + */ + static void MoveFileEx(String source, String target, int flags) + throws WindowsException + { + NativeBuffer sourceBuffer = asNativeBuffer(source); + NativeBuffer targetBuffer = asNativeBuffer(target); + try { + MoveFileEx0(sourceBuffer.address(), targetBuffer.address(), flags); + } finally { + targetBuffer.release(); + sourceBuffer.release(); + } + } + private static native void MoveFileEx0(long existingAddress, long newAddress, + int flags) throws WindowsException; + + /** + * DWORD GetFileAttributes( + * LPCTSTR lpFileName + * ) + */ + static int GetFileAttributes(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + return GetFileAttributes0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native int GetFileAttributes0(long lpFileName) + throws WindowsException; + + /** + * SetFileAttributes( + * LPCTSTR lpFileName, + * DWORD dwFileAttributes + */ + static void SetFileAttributes(String path, int dwFileAttributes) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(path); + try { + SetFileAttributes0(buffer.address(), dwFileAttributes); + } finally { + buffer.release(); + } + } + private static native void SetFileAttributes0(long lpFileName, + int dwFileAttributes) throws WindowsException; + + /** + * GetFileAttributesEx( + * LPCTSTR lpFileName, + * GET_FILEEX_INFO_LEVELS fInfoLevelId, + * LPVOID lpFileInformation + * ); + */ + static void GetFileAttributesEx(String path, long address) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + GetFileAttributesEx0(buffer.address(), address); + } finally { + buffer.release(); + } + } + private static native void GetFileAttributesEx0(long lpFileName, long address) + throws WindowsException; + /** + * SetFileTime( + * HANDLE hFile, + * CONST FILETIME *lpCreationTime, + * CONST FILETIME *lpLastAccessTime, + * CONST FILETIME *lpLastWriteTime + * ) + */ + static native void SetFileTime(long handle, long createTime, + long lastAccessTime, long lastWriteTime) throws WindowsException; + + /** + * SetEndOfFile( + * HANDLE hFile + * ) + */ + static native void SetEndOfFile(long handle) throws WindowsException; + + /** + * DWORD GetLogicalDrives(VOID) + */ + static native int GetLogicalDrives() throws WindowsException; + + /** + * GetVolumeInformation( + * LPCTSTR lpRootPathName, + * LPTSTR lpVolumeNameBuffer, + * DWORD nVolumeNameSize, + * LPDWORD lpVolumeSerialNumber, + * LPDWORD lpMaximumComponentLength, + * LPDWORD lpFileSystemFlags, + * LPTSTR lpFileSystemNameBuffer, + * DWORD nFileSystemNameSize + * ) + */ + static VolumeInformation GetVolumeInformation(String root) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(root); + try { + VolumeInformation info = new VolumeInformation(); + GetVolumeInformation0(buffer.address(), info); + return info; + } finally { + buffer.release(); + } + } + static class VolumeInformation { + private String fileSystemName; + private String volumeName; + private int volumeSerialNumber; + private int flags; + private VolumeInformation() { } + + public String fileSystemName() { return fileSystemName; } + public String volumeName() { return volumeName; } + public int volumeSerialNumber() { return volumeSerialNumber; } + public int flags() { return flags; } + } + private static native void GetVolumeInformation0(long lpRoot, + VolumeInformation obj) + throws WindowsException; + + /** + * UINT GetDriveType( + * LPCTSTR lpRootPathName + * ) + */ + static int GetDriveType(String root) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(root); + try { + return GetDriveType0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native int GetDriveType0(long lpRoot) throws WindowsException; + + /** + * GetDiskFreeSpaceEx( + * LPCTSTR lpDirectoryName, + * PULARGE_INTEGER lpFreeBytesAvailableToCaller, + * PULARGE_INTEGER lpTotalNumberOfBytes, + * PULARGE_INTEGER lpTotalNumberOfFreeBytes + * ) + */ + static DiskFreeSpace GetDiskFreeSpaceEx(String path) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(path); + try { + DiskFreeSpace space = new DiskFreeSpace(); + GetDiskFreeSpaceEx0(buffer.address(), space); + return space; + } finally { + buffer.release(); + } + } + static class DiskFreeSpace { + private long freeBytesAvailable; + private long totalNumberOfBytes; + private long totalNumberOfFreeBytes; + private DiskFreeSpace() { } + + public long freeBytesAvailable() { return freeBytesAvailable; } + public long totalNumberOfBytes() { return totalNumberOfBytes; } + public long totalNumberOfFreeBytes() { return totalNumberOfFreeBytes; } + } + private static native void GetDiskFreeSpaceEx0(long lpDirectoryName, + DiskFreeSpace obj) + throws WindowsException; + + + /** + * GetVolumePathName( + * LPCTSTR lpszFileName, + * LPTSTR lpszVolumePathName, + * DWORD cchBufferLength + * ) + * + * @return lpFileName + */ + static String GetVolumePathName(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + return GetVolumePathName0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native String GetVolumePathName0(long lpFileName) + throws WindowsException; + + + /** + * InitializeSecurityDescriptor( + * PSECURITY_DESCRIPTOR pSecurityDescriptor, + * DWORD dwRevision + * ) + */ + static native void InitializeSecurityDescriptor(long sdAddress) + throws WindowsException; + + /** + * InitializeAcl( + * PACL pAcl, + * DWORD nAclLength, + * DWORD dwAclRevision + * ) + */ + static native void InitializeAcl(long aclAddress, int size) + throws WindowsException; + + /** + * GetFileSecurity( + * LPCTSTR lpFileName, + * SECURITY_INFORMATION RequestedInformation, + * PSECURITY_DESCRIPTOR pSecurityDescriptor, + * DWORD nLength, + * LPDWORD lpnLengthNeeded + * ) + */ + static int GetFileSecurity(String path, + int requestedInformation, + long pSecurityDescriptor, + int nLength) throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(path); + try { + return GetFileSecurity0(buffer.address(), requestedInformation, + pSecurityDescriptor, nLength); + } finally { + buffer.release(); + } + } + private static native int GetFileSecurity0(long lpFileName, + int requestedInformation, + long pSecurityDescriptor, + int nLength) throws WindowsException; + + /** + * SetFileSecurity( + * LPCTSTR lpFileName, + * SECURITY_INFORMATION SecurityInformation, + * PSECURITY_DESCRIPTOR pSecurityDescriptor + * ) + */ + static void SetFileSecurity(String path, + int securityInformation, + long pSecurityDescriptor) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(path); + try { + SetFileSecurity0(buffer.address(), securityInformation, + pSecurityDescriptor); + } finally { + buffer.release(); + } + } + static native void SetFileSecurity0(long lpFileName, int securityInformation, + long pSecurityDescriptor) throws WindowsException; + + /** + * GetSecurityDescriptorOwner( + * PSECURITY_DESCRIPTOR pSecurityDescriptor + * PSID *pOwner, + * LPBOOL lpbOwnerDefaulted + * ) + * + * @return pOwner + */ + static native long GetSecurityDescriptorOwner(long pSecurityDescriptor) + throws WindowsException; + + /** + * SetSecurityDescriptorOwner( + * PSECURITY_DESCRIPTOR pSecurityDescriptor, + * PSID pOwner, + * BOOL bOwnerDefaulted + * ) + */ + static native void SetSecurityDescriptorOwner(long pSecurityDescriptor, + long pOwner) + throws WindowsException; + + /** + * GetSecurityDescriptorDacl( + * PSECURITY_DESCRIPTOR pSecurityDescriptor, + * LPBOOL lpbDaclPresent, + * PACL *pDacl, + * LPBOOL lpbDaclDefaulted + * ) + */ + static native long GetSecurityDescriptorDacl(long pSecurityDescriptor); + + /** + * SetSecurityDescriptorDacl( + * PSECURITY_DESCRIPTOR pSecurityDescriptor, + * BOOL bDaclPresent, + * PACL pDacl, + * BOOL bDaclDefaulted + * ) + */ + static native void SetSecurityDescriptorDacl(long pSecurityDescriptor, long pAcl) + throws WindowsException; + + + /** + * GetAclInformation( + * PACL pAcl, + * LPVOID pAclInformation, + * DWORD nAclInformationLength, + * ACL_INFORMATION_CLASS dwAclInformationClass + * ) + */ + static AclInformation GetAclInformation(long aclAddress) { + AclInformation info = new AclInformation(); + GetAclInformation0(aclAddress, info); + return info; + } + static class AclInformation { + private int aceCount; + private AclInformation() { } + + public int aceCount() { return aceCount; } + } + private static native void GetAclInformation0(long aclAddress, + AclInformation obj); + + /** + * GetAce( + * PACL pAcl, + * DWORD dwAceIndex, + * LPVOID *pAce + * ) + */ + static native long GetAce(long aclAddress, int aceIndex); + + /** + * AddAccessAllowedAceEx( + * PACL pAcl, + * DWORD dwAceRevision, + * DWORD AceFlags, + * DWORD AccessMask, + * PSID pSid + * ) + */ + static native void AddAccessAllowedAceEx(long aclAddress, int flags, + int mask, long sidAddress) throws WindowsException; + + /** + * AddAccessDeniedAceEx( + * PACL pAcl, + * DWORD dwAceRevision, + * DWORD AceFlags, + * DWORD AccessMask, + * PSID pSid + * ) + */ + static native void AddAccessDeniedAceEx(long aclAddress, int flags, + int mask, long sidAddress) throws WindowsException; + + /** + * LookupAccountSid( + * LPCTSTR lpSystemName, + * PSID Sid, + * LPTSTR Name, + * LPDWORD cbName, + * LPTSTR ReferencedDomainName, + * LPDWORD cbReferencedDomainName, + * PSID_NAME_USE peUse + * ) + */ + static Account LookupAccountSid(long sidAddress) throws WindowsException { + Account acc = new Account(); + LookupAccountSid0(sidAddress, acc); + return acc; + } + static class Account { + private String domain; + private String name; + private int use; + private Account() { } + + public String domain() { return domain; } + public String name() { return name; } + public int use() { return use; } + } + private static native void LookupAccountSid0(long sidAddress, Account obj) + throws WindowsException; + + /** + * LookupAccountName( + * LPCTSTR lpSystemName, + * LPCTSTR lpAccountName, + * PSID Sid, + * LPDWORD cbSid, + * LPTSTR ReferencedDomainName, + * LPDWORD cbReferencedDomainName, + * PSID_NAME_USE peUse + * ) + * + * @return cbSid + */ + static int LookupAccountName(String accountName, + long pSid, + int cbSid) throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(accountName); + try { + return LookupAccountName0(buffer.address(), pSid, cbSid); + } finally { + buffer.release(); + } + } + private static native int LookupAccountName0(long lpAccountName, long pSid, + int cbSid) throws WindowsException; + + /** + * DWORD GetLengthSid( + * PSID pSid + * ) + */ + static native int GetLengthSid(long sidAddress); + + /** + * ConvertSidToStringSid( + * PSID Sid, + * LPTSTR* StringSid + * ) + * + * @return StringSid + */ + static native String ConvertSidToStringSid(long sidAddress) + throws WindowsException; + + /** + * ConvertStringSidToSid( + * LPCTSTR StringSid, + * PSID* pSid + * ) + * + * @return pSid + */ + static long ConvertStringSidToSid(String sidString) + throws WindowsException + { + NativeBuffer buffer = asNativeBuffer(sidString); + try { + return ConvertStringSidToSid0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native long ConvertStringSidToSid0(long lpStringSid) + throws WindowsException; + + /** + * HANDLE GetCurrentProcess(VOID) + */ + static native long GetCurrentProcess(); + + /** + * HANDLE GetCurrentThread(VOID) + */ + static native long GetCurrentThread(); + + /** + * OpenProcessToken( + * HANDLE ProcessHandle, + * DWORD DesiredAccess, + * PHANDLE TokenHandle + * ) + */ + static native long OpenProcessToken(long hProcess, int desiredAccess) + throws WindowsException; + + /** + * OpenThreadToken( + * HANDLE ThreadHandle, + * DWORD DesiredAccess, + * BOOL OpenAsSelf, + * PHANDLE TokenHandle + * ) + */ + static native long OpenThreadToken(long hThread, int desiredAccess, + boolean openAsSelf) throws WindowsException; + + /** + */ + static native long DuplicateTokenEx(long hThread, int desiredAccess) + throws WindowsException; + + /** + * SetThreadToken( + * PHANDLE Thread, + * HANDLE Token + * ) + */ + static native void SetThreadToken(long thread, long hToken) + throws WindowsException; + + /** + * GetTokenInformation( + * HANDLE TokenHandle, + * TOKEN_INFORMATION_CLASS TokenInformationClass, + * LPVOID TokenInformation, + * DWORD TokenInformationLength, + * PDWORD ReturnLength + * ) + */ + static native int GetTokenInformation(long token, int tokenInfoClass, + long pTokenInfo, int tokenInfoLength) throws WindowsException; + + /** + * AdjustTokenPrivileges( + * HANDLE TokenHandle, + * BOOL DisableAllPrivileges + * PTOKEN_PRIVILEGES NewState + * DWORD BufferLength + * PTOKEN_PRIVILEGES + * PDWORD ReturnLength + * ) + */ + static native void AdjustTokenPrivileges(long token, long luid, int attributes) + throws WindowsException; + + /** + */ + static long LookupPrivilegeValue(String name) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(name); + try { + return LookupPrivilegeValue0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native long LookupPrivilegeValue0(long lpName) + throws WindowsException; + + /** + * BuildTrusteeWithSid( + * PTRUSTEE pTrustee, + * PSID pSid + * ) + * + * @return pTrustee + */ + static native long BuildTrusteeWithSid(long pSid); + + /** + * GetEffectiveRightsFromAcl( + * PACL pacl, + * PTRUSTEE pTrustee, + * PACCESS_MASK pAccessRights + * ) + * + * @return AccessRights + */ + static native int GetEffectiveRightsFromAcl(long pAcl, long pTrustee) + throws WindowsException; + + /** + * CreateSymbolicLink( + * LPCWSTR lpSymlinkFileName, + * LPCWSTR lpTargetFileName, + * DWORD dwFlags + * ) + */ + static void CreateSymbolicLink(String link, String target, int flags) + throws WindowsException + { + NativeBuffer linkBuffer = asNativeBuffer(link); + NativeBuffer targetBuffer = asNativeBuffer(target); + try { + CreateSymbolicLink0(linkBuffer.address(), targetBuffer.address(), + flags); + } finally { + targetBuffer.release(); + linkBuffer.release(); + } + } + private static native void CreateSymbolicLink0(long linkAddress, + long targetAddress, int flags) throws WindowsException; + + /** + * CreateHardLink( + * LPCTSTR lpFileName, + * LPCTSTR lpExistingFileName, + * LPSECURITY_ATTRIBUTES lpSecurityAttributes + * ) + */ + static void CreateHardLink(String newFile, String existingFile) + throws WindowsException + { + NativeBuffer newFileBuffer = asNativeBuffer(newFile); + NativeBuffer existingFileBuffer = asNativeBuffer(existingFile); + try { + CreateHardLink0(newFileBuffer.address(), existingFileBuffer.address()); + } finally { + existingFileBuffer.release(); + newFileBuffer.release(); + } + } + private static native void CreateHardLink0(long newFileBuffer, + long existingFiletBuffer) throws WindowsException; + + /** + * GetFullPathName( + * LPCTSTR lpFileName, + * DWORD nBufferLength, + * LPTSTR lpBuffer, + * LPTSTR *lpFilePart + * ) + */ + static String GetFullPathName(String path) throws WindowsException { + NativeBuffer buffer = asNativeBuffer(path); + try { + return GetFullPathName0(buffer.address()); + } finally { + buffer.release(); + } + } + private static native String GetFullPathName0(long pathAddress) + throws WindowsException; + + /** + * GetFinalPathNameByHandle( + * HANDLE hFile, + * LPTSTR lpszFilePath, + * DWORD cchFilePath, + * DWORD dwFlags + * ) + */ + static native String GetFinalPathNameByHandle(long handle) + throws WindowsException; + + /** + * FormatMessage( + * DWORD dwFlags, + * LPCVOID lpSource, + * DWORD dwMessageId, + * DWORD dwLanguageId, + * LPTSTR lpBuffer, + * DWORD nSize, + * va_list *Arguments + * ) + */ + static native String FormatMessage(int errorCode); + + /** + * LocalFree( + * HLOCAL hMem + * ) + */ + static native void LocalFree(long address); + + /** + * HANDLE CreateIoCompletionPort ( + * HANDLE FileHandle, + * HANDLE ExistingCompletionPort, + * DWORD CompletionKey, + * DWORD NumberOfConcurrentThreads + * ) + */ + static native long CreateIoCompletionPort(long fileHandle, long existingPort, + int completionKey) throws WindowsException; + + + /** + * GetQueuedCompletionStatus( + * HANDLE CompletionPort, + * LPDWORD lpNumberOfBytesTransferred, + * LPDWORD lpCompletionKey, + * LPOVERLAPPED *lpOverlapped, + * DWORD dwMilliseconds + */ + static CompletionStatus GetQueuedCompletionStatus(long completionPort) + throws WindowsException + { + CompletionStatus status = new CompletionStatus(); + GetQueuedCompletionStatus0(completionPort, status); + return status; + } + static class CompletionStatus { + private int error; + private int bytesTransferred; + private int completionKey; + private CompletionStatus() { } + + int error() { return error; } + int bytesTransferred() { return bytesTransferred; } + int completionKey() { return completionKey; } + } + private static native void GetQueuedCompletionStatus0(long completionPort, + CompletionStatus status) throws WindowsException; + + /** + * PostQueuedCompletionStatus( + * HANDLE CompletionPort, + * DWORD dwNumberOfBytesTransferred, + * DWORD dwCompletionKey, + * LPOVERLAPPED lpOverlapped + * ) + */ + static native void PostQueuedCompletionStatus(long completionPort, + int completionKey) throws WindowsException; + + /** + * ReadDirectoryChangesW( + * HANDLE hDirectory, + * LPVOID lpBuffer, + * DWORD nBufferLength, + * BOOL bWatchSubtree, + * DWORD dwNotifyFilter, + * LPDWORD lpBytesReturned, + * LPOVERLAPPED lpOverlapped, + * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine + * ) + */ + static native void ReadDirectoryChangesW(long hDirectory, + long bufferAddress, + int bufferLength, + boolean watchSubTree, + int filter, + long bytesReturnedAddress, + long pOverlapped) + throws WindowsException; + + /** + * BackupRead( + * HANDLE hFile, + * LPBYTE lpBuffer, + * DWORD nNumberOfBytesToRead, + * LPDWORD lpNumberOfBytesRead, + * BOOL bAbort, + * BOOL bProcessSecurity, + * LPVOID* lpContext + * ) + */ + static BackupResult BackupRead(long hFile, + long bufferAddress, + int bufferSize, + boolean abort, + long context) + throws WindowsException + { + BackupResult result = new BackupResult(); + BackupRead0(hFile, bufferAddress, bufferSize, abort, context, result); + return result; + } + static class BackupResult { + private int bytesTransferred; + private long context; + private BackupResult() { } + + int bytesTransferred() { return bytesTransferred; } + long context() { return context; } + } + private static native void BackupRead0(long hFile, long bufferAddress, + int bufferSize, boolean abort, long context, BackupResult result) + throws WindowsException; + + /** + * BackupSeek( + * HANDLE hFile, + * DWORD dwLowBytesToSeek, + * DWORD dwHighBytesToSeek, + * LPDWORD lpdwLowByteSeeked, + * LPDWORD lpdwHighByteSeeked, + * LPVOID* lpContext + * ) + */ + static native void BackupSeek(long hFile, long bytesToSeek, long context) + throws WindowsException; + + + // -- support for copying String with a NativeBuffer -- + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + static NativeBuffer asNativeBuffer(String s) { + int stringLengthInBytes = s.length() << 1; + int sizeInBytes = stringLengthInBytes + 2; // char terminator + + // get a native buffer of sufficient size + NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(sizeInBytes); + if (buffer == null) { + buffer = NativeBuffers.allocNativeBuffer(sizeInBytes); + } else { + // buffer already contains the string contents + if (buffer.owner() == s) + return buffer; + } + + // copy into buffer and zero terminate + char[] chars = s.toCharArray(); + unsafe.copyMemory(chars, Unsafe.ARRAY_CHAR_BASE_OFFSET, null, + buffer.address(), (long)stringLengthInBytes); + unsafe.putChar(buffer.address() + stringLengthInBytes, (char)0); + buffer.setOwner(s); + return buffer; + } + + // -- native library initialization -- + + private static native void initIDs(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + // nio.dll has dependency on net.dll + System.loadLibrary("net"); + System.loadLibrary("nio"); + return null; + }}); + initIDs(); + } + +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java new file mode 100644 index 00000000000..2fda59d2bfb --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java @@ -0,0 +1,1375 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.file.spi.AbstractPath; +import java.nio.channels.*; +import java.io.*; +import java.net.URI; +import java.security.AccessController; +import java.util.*; +import java.lang.ref.WeakReference; + +import com.sun.nio.file.ExtendedWatchEventModifier; + +import sun.security.util.SecurityConstants; +import sun.misc.Unsafe; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Windows implementation of Path + */ + +class WindowsPath extends AbstractPath { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // The maximum path that does not require long path prefix. On Windows + // the maximum path is 260 minus 1 (NUL) but for directories it is 260 + // minus 12 minus 1 (to allow for the creation of a 8.3 file in the + // directory). + private static final int MAX_PATH = 247; + + // Maximum extended-length path + private static final int MAX_LONG_PATH = 32000; + + // FIXME - eliminate this reference to reduce space + private final WindowsFileSystem fs; + + // path type + private final WindowsPathType type; + // root component (may be empty) + private final String root; + // normalized path + private final String path; + + // the path to use in Win32 calls. This differs from path for relative + // paths and has a long path prefix for all paths longer than MAX_PATH. + private volatile WeakReference pathForWin32Calls; + + // offsets into name components (computed lazily) + private volatile Integer[] offsets; + + // computed hash code (computed lazily, no need to be volatile) + private int hash; + + + /** + * Initializes a new instance of this class. + */ + private WindowsPath(WindowsFileSystem fs, + WindowsPathType type, + String root, + String path) + { + this.fs = fs; + this.type = type; + this.root = root; + this.path = path; + } + + /** + * Creates a Path by parsing the given path. + */ + static WindowsPath parse(WindowsFileSystem fs, String path) { + WindowsPathParser.Result result = WindowsPathParser.parse(path); + return new WindowsPath(fs, result.type(), result.root(), result.path()); + } + + /** + * Creates a Path from a given path that is known to be normalized. + */ + static WindowsPath createFromNormalizedPath(WindowsFileSystem fs, + String path, + BasicFileAttributes attrs) + { + try { + WindowsPathParser.Result result = + WindowsPathParser.parseNormalizedPath(path); + if (attrs == null) { + return new WindowsPath(fs, + result.type(), + result.root(), + result.path()); + } else { + return new WindowsPathWithAttributes(fs, + result.type(), + result.root(), + result.path(), + attrs); + } + } catch (InvalidPathException x) { + throw new AssertionError(x.getMessage()); + } + } + + /** + * Creates a WindowsPath from a given path that is known to be normalized. + */ + static WindowsPath createFromNormalizedPath(WindowsFileSystem fs, + String path) + { + return createFromNormalizedPath(fs, path, null); + } + + /** + * Special implementation with attached/cached attributes (used to quicken + * file tree traveral) + */ + private static class WindowsPathWithAttributes + extends WindowsPath implements BasicFileAttributesHolder + { + final WeakReference ref; + + WindowsPathWithAttributes(WindowsFileSystem fs, + WindowsPathType type, + String root, + String path, + BasicFileAttributes attrs) + { + super(fs, type, root, path); + ref = new WeakReference(attrs); + } + + @Override + public BasicFileAttributes get() { + return ref.get(); + } + + @Override + public void invalidate() { + ref.clear(); + } + } + + // use this message when throwing exceptions + String getPathForExceptionMessage() { + return path; + } + + // use this path for permission checks + String getPathForPermissionCheck() { + return path; + } + + // use this path for Win32 calls + // This method will prefix long paths with \\?\ or \\?\UNC as required. + String getPathForWin32Calls() throws WindowsException { + // short absolute paths can be used directly + if (isAbsolute() && path.length() <= MAX_PATH) + return path; + + // return cached values if available + WeakReference ref = pathForWin32Calls; + String resolved = (ref != null) ? ref.get() : null; + if (resolved != null) { + // Win32 path already available + return resolved; + } + + // resolve against default directory + resolved = getAbsolutePath(); + + // Long paths need to have "." and ".." removed and be prefixed with + // "\\?\". Note that it is okay to remove ".." even when it follows + // a link - for example, it is okay for foo/link/../bar to be changed + // to foo/bar. The reason is that Win32 APIs to access foo/link/../bar + // will access foo/bar anyway (which differs to Unix systems) + if (resolved.length() > MAX_PATH) { + if (resolved.length() > MAX_LONG_PATH) { + throw new WindowsException("Cannot access file with path exceeding " + + MAX_LONG_PATH + " characters"); + } + resolved = addPrefixIfNeeded(GetFullPathName(resolved)); + } + + // cache the resolved path (except drive relative paths as the working + // directory on removal media devices can change during the lifetime + // of the VM) + if (type != WindowsPathType.DRIVE_RELATIVE) { + synchronized (path) { + pathForWin32Calls = new WeakReference(resolved); + } + } + return resolved; + } + + // return this path resolved against the file system's default directory + private String getAbsolutePath() throws WindowsException { + if (isAbsolute()) + return path; + + // Relative path ("foo" for example) + if (type == WindowsPathType.RELATIVE) { + String defaultDirectory = getFileSystem().defaultDirectory(); + if (defaultDirectory.endsWith("\\")) { + return defaultDirectory + path; + } else { + StringBuilder sb = + new StringBuilder(defaultDirectory.length() + path.length() + 1); + return sb.append(defaultDirectory).append('\\').append(path).toString(); + } + } + + // Directory relative path ("\foo" for example) + if (type == WindowsPathType.DIRECTORY_RELATIVE) { + String defaultRoot = getFileSystem().defaultRoot(); + return defaultRoot + path.substring(1); + } + + // Drive relative path ("C:foo" for example). + if (isSameDrive(root, getFileSystem().defaultRoot())) { + // relative to default directory + String remaining = path.substring(root.length()); + String defaultDirectory = getFileSystem().defaultDirectory(); + String result; + if (defaultDirectory.endsWith("\\")) { + result = defaultDirectory + remaining; + } else { + result = defaultDirectory + "\\" + remaining; + } + return result; + } else { + // relative to some other drive + String wd; + try { + int dt = GetDriveType(root + "\\"); + if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR) + throw new WindowsException(""); + wd = GetFullPathName(root + "."); + } catch (WindowsException x) { + throw new WindowsException("Unable to get working directory of drive '" + + Character.toUpperCase(root.charAt(0)) + "'"); + } + String result = wd; + if (wd.endsWith("\\")) { + result += path.substring(root.length()); + } else { + if (path.length() > root.length()) + result += "\\" + path.substring(root.length()); + } + return result; + } + } + + // returns true if same drive letter + private static boolean isSameDrive(String root1, String root2) { + return Character.toUpperCase(root1.charAt(0)) == + Character.toUpperCase(root2.charAt(0)); + } + + // Add long path prefix to path if required + private static String addPrefixIfNeeded(String path) { + if (path.length() > 248) { + if (path.startsWith("\\\\")) { + path = "\\\\?\\UNC" + path.substring(1, path.length()); + } else { + path = "\\\\?\\" + path; + } + } + return path; + } + + @Override + public WindowsFileSystem getFileSystem() { + return fs; + } + + // -- Path operations -- + + @Override + public Path getName() { + // represents root component only + if (root.length() == path.length()) + return null; + int off = path.lastIndexOf('\\'); + if (off < root.length()) + off = root.length(); + else + off++; + return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", path.substring(off)); + } + + @Override + public WindowsPath getParent() { + // represents root component only + if (root.length() == path.length()) + return null; + int off = path.lastIndexOf('\\'); + if (off < root.length()) + return getRoot(); + else + return new WindowsPath(getFileSystem(), + type, + root, + path.substring(0, off)); + } + + @Override + public WindowsPath getRoot() { + if (root.length() == 0) + return null; + return new WindowsPath(getFileSystem(), type, root, root); + } + + // package-private + boolean isUnc() { + return type == WindowsPathType.UNC; + } + + boolean needsSlashWhenResolving() { + if (path.endsWith("\\")) + return false; + return path.length() > root.length(); + } + + @Override + public boolean isAbsolute() { + return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC; + } + + private WindowsPath checkPath(FileRef path) { + if (path == null) + throw new NullPointerException(); + if (!(path instanceof WindowsPath)) { + throw new ProviderMismatchException(); + } + return (WindowsPath)path; + } + + @Override + public WindowsPath relativize(Path obj) { + WindowsPath other = checkPath(obj); + if (this.equals(other)) + return null; + + // can only relativize paths of the same type + if (this.type != other.type) + throw new IllegalArgumentException("'other' is different type of Path"); + + // can only relativize paths if root component matches + if (!this.root.equalsIgnoreCase(other.root)) + throw new IllegalArgumentException("'other' has different root"); + + int bn = this.getNameCount(); + int cn = other.getNameCount(); + + // skip matching names + int n = (bn > cn) ? cn : bn; + int i = 0; + while (i < n) { + if (!this.getName(i).equals(other.getName(i))) + break; + i++; + } + + // append ..\ for remaining names in the base + StringBuilder result = new StringBuilder(); + for (int j=i; j ignore name + int remaining = count; // number of names remaining + + // multiple passes to eliminate all occurences of "." and "name/.." + int prevRemaining; + do { + prevRemaining = remaining; + int prevName = -1; + for (int i=0; i 2) { + prevName = i; + continue; + } + + // "." or something else + if (name.length() == 1) { + // ignore "." + if (name.charAt(0) == '.') { + ignore[i] = true; + remaining--; + } else { + prevName = i; + } + continue; + } + + // not ".." + if (name.charAt(0) != '.' || name.charAt(1) != '.') { + prevName = i; + continue; + } + + // ".." found + if (prevName >= 0) { + // name//.. found so mark name and ".." to be + // ignored + ignore[prevName] = true; + ignore[i] = true; + remaining = remaining - 2; + prevName = -1; + } else { + // Cases: + // C:\\.. + // \\server\\share\\.. + // \.. + if (isAbsolute() || type == WindowsPathType.DIRECTORY_RELATIVE) { + boolean hasPrevious = false; + for (int j=0; j remaining); + + // no redundant names + if (remaining == count) + return this; + + // corner case - all names removed + if (remaining == 0) { + return getRoot(); + } + + // re-constitute the path from the remaining names. + StringBuilder result = new StringBuilder(); + if (root != null) + result.append(root); + for (int i=0; i list = new ArrayList(); + int start = root.length(); + int off = root.length(); + while (off < path.length()) { + if (path.charAt(off) != '\\') { + off++; + } else { + list.add(start); + start = ++off; + } + } + if (start != off) + list.add(start); + synchronized (this) { + if (offsets == null) + offsets = list.toArray(new Integer[list.size()]); + } + } + } + + @Override + public int getNameCount() { + initOffsets(); + return offsets.length; + } + + private String elementAsString(int i) { + initOffsets(); + if (i == (offsets.length-1)) + return path.substring(offsets[i]); + return path.substring(offsets[i], offsets[i+1]-1); + } + + @Override + public WindowsPath getName(int index) { + initOffsets(); + if (index < 0 || index >= offsets.length) + throw new IllegalArgumentException(); + return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", elementAsString(index)); + } + + @Override + public WindowsPath subpath(int beginIndex, int endIndex) { + initOffsets(); + if (beginIndex < 0) + throw new IllegalArgumentException(); + if (beginIndex >= offsets.length) + throw new IllegalArgumentException(); + if (endIndex > offsets.length) + throw new IllegalArgumentException(); + if (beginIndex >= endIndex) + throw new IllegalArgumentException(); + + StringBuilder sb = new StringBuilder(); + Integer[] nelems = new Integer[endIndex - beginIndex]; + for (int i = beginIndex; i < endIndex; i++) { + nelems[i-beginIndex] = sb.length(); + sb.append(elementAsString(i)); + if (i != (endIndex-1)) + sb.append("\\"); + } + return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", sb.toString()); + } + + @Override + public boolean startsWith(Path obj) { + WindowsPath other = checkPath(obj); + + // if this path has a root component the given path's root must match + if (!this.root.equalsIgnoreCase(other.root)) + return false; + + // roots match so compare elements + int thisCount = getNameCount(); + int otherCount = other.getNameCount(); + if (otherCount <= thisCount) { + while (--otherCount >= 0) { + String thisElement = this.elementAsString(otherCount); + String otherElement = other.elementAsString(otherCount); + // FIXME: should compare in uppercase + if (!thisElement.equalsIgnoreCase(otherElement)) + return false; + } + return true; + } + return false; + } + + @Override + public boolean endsWith(Path obj) { + WindowsPath other = checkPath(obj); + + // other path is longer + if (other.path.length() > path.length()) { + return false; + } + + int thisCount = this.getNameCount(); + int otherCount = other.getNameCount(); + + // given path has more elements that this path + if (otherCount > thisCount) { + return false; + } + + // compare roots + if (other.root.length() > 0) { + if (otherCount < thisCount) + return false; + // FIXME: should compare in uppercase + if (!this.root.equalsIgnoreCase(other.root)) + return false; + } + + // match last 'otherCount' elements + int off = thisCount - otherCount; + while (--otherCount >= 0) { + String thisElement = this.elementAsString(off + otherCount); + String otherElement = other.elementAsString(otherCount); + // FIXME: should compare in uppercase + if (!thisElement.equalsIgnoreCase(otherElement)) + return false; + } + return true; + } + + @Override + public int compareTo(Path obj) { + if (obj == null) + throw new NullPointerException(); + String s1 = path; + String s2 = ((WindowsPath)obj).path; + int n1 = s1.length(); + int n2 = s2.length(); + int min = Math.min(n1, n2); + for (int i = 0; i < min; i++) { + char c1 = s1.charAt(i); + char c2 = s2.charAt(i); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + return n1 - n2; + } + + @Override + public boolean equals(Object obj) { + if ((obj != null) && (obj instanceof WindowsPath)) { + return compareTo((Path)obj) == 0; + } + return false; + } + + @Override + public int hashCode() { + // OK if two or more threads compute hash + int h = hash; + if (h == 0) { + for (int i = 0; i< path.length(); i++) { + h = 31*h + Character.toUpperCase(path.charAt(i)); + } + hash = h; + } + return h; + } + + @Override + public String toString() { + return path; + } + + @Override + public Iterator iterator() { + return new Iterator() { + private int i = 0; + @Override + public boolean hasNext() { + return (i < getNameCount()); + } + @Override + public Path next() { + if (i < getNameCount()) { + Path result = getName(i); + i++; + return result; + } else { + throw new NoSuchElementException(); + } + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + // -- file operations -- + + // package-private + long openForReadAttributeAccess(boolean followLinks) + throws WindowsException + { + int flags = FILE_FLAG_BACKUP_SEMANTICS; + if (!followLinks && getFileSystem().supportsLinks()) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + return CreateFile(getPathForWin32Calls(), + FILE_READ_ATTRIBUTES, + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), + 0L, + OPEN_EXISTING, + flags); + } + + void checkRead() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkRead(getPathForPermissionCheck()); + } + } + + void checkWrite() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkWrite(getPathForPermissionCheck()); + } + } + + void checkDelete() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkDelete(getPathForPermissionCheck()); + } + } + + @Override + public FileStore getFileStore() + throws IOException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + checkRead(); + } + return WindowsFileStore.create(this); + } + + /** + * Returns buffer with SID_AND_ATTRIBUTES structure representing the user + * associated with the current thread access token. + * FIXME - this should be cached. + */ + private NativeBuffer getUserInfo() throws IOException { + try { + long hToken = WindowsSecurity.processTokenWithQueryAccess; + int size = GetTokenInformation(hToken, TokenUser, 0L, 0); + assert size > 0; + + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + int newsize = GetTokenInformation(hToken, TokenUser, + buffer.address(), size); + if (newsize != size) + throw new AssertionError(); + return buffer; + } catch (WindowsException x) { + buffer.release(); + throw x; + } + } catch (WindowsException x) { + throw new IOException(x.getMessage()); + } + } + + /** + * Reads the file ACL and return the effective access as ACCESS_MASK + */ + private int getEffectiveAccess() throws IOException { + // read security descriptor continaing ACL (symlinks are followed) + String target = WindowsLinkSupport.getFinalPath(this, true); + NativeBuffer aclBuffer = WindowsAclFileAttributeView + .getFileSecurity(target, DACL_SECURITY_INFORMATION); + + // retrieves DACL from security descriptor + long pAcl = GetSecurityDescriptorDacl(aclBuffer.address()); + + // Use GetEffectiveRightsFromAcl to get effective access to file + try { + NativeBuffer userBuffer = getUserInfo(); + try { + try { + // SID_AND_ATTRIBUTES->pSid + long pSid = unsafe.getAddress(userBuffer.address()); + long pTrustee = BuildTrusteeWithSid(pSid); + try { + return GetEffectiveRightsFromAcl(pAcl, pTrustee); + } finally { + LocalFree(pTrustee); + } + } catch (WindowsException x) { + throw new IOException("Unable to get effective rights from ACL: " + + x.getMessage()); + } + } finally { + userBuffer.release(); + } + } finally { + aclBuffer.release(); + } + } + + @Override + public void checkAccess(AccessMode... modes) throws IOException { + // if no access modes then simply file attributes + if (modes.length == 0) { + checkRead(); + try { + WindowsFileAttributes.get(this, true); + } catch (WindowsException exc) { + exc.rethrowAsIOException(this); + } + return; + } + + boolean r = false; + boolean w = false; + boolean x = false; + for (AccessMode mode: modes) { + switch (mode) { + case READ : r = true; break; + case WRITE : w = true; break; + case EXECUTE : x = true; break; + default: throw new AssertionError("Should not get here"); + } + } + + int mask = 0; + if (r) { + checkRead(); + mask |= FILE_READ_DATA; + } + if (w) { + checkWrite(); + mask |= FILE_WRITE_DATA; + } + if (x) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkExec(getPathForPermissionCheck()); + mask |= FILE_EXECUTE; + } + + if ((getEffectiveAccess() & mask) == 0) + throw new AccessDeniedException( + this.getPathForExceptionMessage(), null, + "Effective permissions does not allow requested access"); + + // for write access we neeed to check if the DOS readonly attribute + // and if the volume is read-only + if (w) { + try { + WindowsFileAttributes attrs = WindowsFileAttributes.get(this, true); + if (!attrs.isDirectory() && attrs.isReadOnly()) + throw new AccessDeniedException( + this.getPathForExceptionMessage(), null, + "DOS readonly attribute is set"); + } catch (WindowsException exc) { + exc.rethrowAsIOException(this); + } + + if (WindowsFileStore.create(this).isReadOnly()) { + throw new AccessDeniedException( + this.getPathForExceptionMessage(), null, "Read-only file system"); + } + return; + } + } + + @Override + public void delete(boolean failIfNotExists) throws IOException { + checkDelete(); + + WindowsFileAttributes attrs = null; + try { + // need to know if file is a directory or junction + attrs = WindowsFileAttributes.get(this, false); + if (attrs.isDirectory() || attrs.isDirectoryLink()) { + RemoveDirectory(getPathForWin32Calls()); + } else { + DeleteFile(getPathForWin32Calls()); + } + } catch (WindowsException x) { + + // no-op if file does not exist + if (!failIfNotExists && + (x.lastError() == ERROR_FILE_NOT_FOUND || + x.lastError() == ERROR_PATH_NOT_FOUND)) return; + + if (attrs != null && attrs.isDirectory()) { + // ERROR_ALREADY_EXISTS is returned when attempting to delete + // non-empty directory on SAMBA servers. + if (x.lastError() == ERROR_DIR_NOT_EMPTY || + x.lastError() == ERROR_ALREADY_EXISTS) + { + throw new DirectoryNotEmptyException( + getPathForExceptionMessage()); + } + } + x.rethrowAsIOException(this); + } + } + + @Override + public DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) + throws IOException + { + checkRead(); + if (filter == null) + throw new NullPointerException(); + return new WindowsDirectoryStream(this, filter); + } + + @Override + public void implCopyTo(Path obj, CopyOption... options) throws IOException { + WindowsPath target = (WindowsPath)obj; + WindowsFileCopy.copy(this, target, options); + } + + @Override + public void implMoveTo(Path obj, CopyOption... options) throws IOException { + WindowsPath target = (WindowsPath)obj; + WindowsFileCopy.move(this, target, options); + } + + private boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption option: options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + + @Override + @SuppressWarnings("unchecked") + public V + getFileAttributeView(Class view, LinkOption... options) + { + if (view == null) + throw new NullPointerException(); + boolean followLinks = followLinks(options); + if (view == BasicFileAttributeView.class) + return (V) WindowsFileAttributeViews.createBasicView(this, followLinks); + if (view == DosFileAttributeView.class) + return (V) WindowsFileAttributeViews.createDosView(this, followLinks); + if (view == AclFileAttributeView.class) + return (V) new WindowsAclFileAttributeView(this, followLinks); + if (view == FileOwnerAttributeView.class) + return (V) new FileOwnerAttributeViewImpl( + new WindowsAclFileAttributeView(this, followLinks)); + if (view == UserDefinedFileAttributeView.class) + return (V) new WindowsUserDefinedFileAttributeView(this, followLinks); + return (V) null; + } + + @Override + public FileAttributeView getFileAttributeView(String name, LinkOption... options) { + boolean followLinks = followLinks(options); + if (name.equals("basic")) + return WindowsFileAttributeViews.createBasicView(this, followLinks); + if (name.equals("dos")) + return WindowsFileAttributeViews.createDosView(this, followLinks); + if (name.equals("acl")) + return new WindowsAclFileAttributeView(this, followLinks); + if (name.equals("owner")) + return new FileOwnerAttributeViewImpl( + new WindowsAclFileAttributeView(this, followLinks)); + if (name.equals("xattr")) + return new WindowsUserDefinedFileAttributeView(this, followLinks); + return null; + } + + @Override + public WindowsPath createDirectory(FileAttribute... attrs) + throws IOException + { + checkWrite(); + WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs); + try { + CreateDirectory(getPathForWin32Calls(), sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + } finally { + sd.release(); + } + return this; + } + + @Override + public InputStream newInputStream()throws IOException { + try { + Set options = Collections.emptySet(); + FileChannel fc = WindowsChannelFactory + .newFileChannel(getPathForWin32Calls(), + getPathForPermissionCheck(), + options, + 0L); + return Channels.newInputStream(fc); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } + } + + @Override + public SeekableByteChannel newByteChannel(Set options, + FileAttribute... attrs) + throws IOException + { + WindowsSecurityDescriptor sd = + WindowsSecurityDescriptor.fromAttribute(attrs); + try { + return WindowsChannelFactory + .newFileChannel(getPathForWin32Calls(), + getPathForPermissionCheck(), + options, + sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } finally { + sd.release(); + } + } + + @Override + public OutputStream newOutputStream(Set options, + FileAttribute... attrs) + throws IOException + { + // need to copy options to add WRITE + Set opts = new HashSet(options); + if (opts.contains(StandardOpenOption.READ)) + throw new IllegalArgumentException("READ not allowed"); + opts.add(StandardOpenOption.WRITE); + + WindowsSecurityDescriptor sd = + WindowsSecurityDescriptor.fromAttribute(attrs); + FileChannel fc; + try { + fc = WindowsChannelFactory + .newFileChannel(getPathForWin32Calls(), + getPathForPermissionCheck(), + opts, + sd.address()); + return Channels.newOutputStream(fc); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + return null; // keep compiler happy + } finally { + sd.release(); + } + } + + @Override + public boolean isSameFile(FileRef obj) throws IOException { + if (this.equals(obj)) + return true; + if (!(obj instanceof WindowsPath)) // includes null check + return false; + WindowsPath other = (WindowsPath)obj; + + // check security manager access to both files + this.checkRead(); + other.checkRead(); + + // open both files and see if they are the same + long h1 = 0L; + try { + h1 = this.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + } + try { + WindowsFileAttributes attrs1 = null; + try { + attrs1 = WindowsFileAttributes.readAttributes(h1); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + } + long h2 = 0L; + try { + h2 = other.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(other); + } + try { + WindowsFileAttributes attrs2 = null; + try { + attrs2 = WindowsFileAttributes.readAttributes(h2); + } catch (WindowsException x) { + x.rethrowAsIOException(other); + } + return WindowsFileAttributes.isSameFile(attrs1, attrs2); + } finally { + CloseHandle(h2); + } + } finally { + CloseHandle(h1); + } + } + + @Override + public WindowsPath createSymbolicLink(Path obj, FileAttribute... attrs) + throws IOException + { + if (!getFileSystem().supportsLinks()) { + throw new UnsupportedOperationException("Symbolic links not supported " + + "on this operating system"); + } + + WindowsPath target = checkPath(obj); + + // no attributes allowed + if (attrs.length > 0) { + WindowsSecurityDescriptor.fromAttribute(attrs); // may throw NPE or UOE + throw new UnsupportedOperationException("Initial file attributes" + + "not supported when creating symbolic link"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("symbolic")); + this.checkWrite(); + } + + /** + * Throw I/O exception for the drive-relative case because Windows + * creates a link with the resolved target for this case. + */ + if (target.type == WindowsPathType.DRIVE_RELATIVE) { + throw new IOException("Cannot create symbolic link to drive-relative target"); + } + + /* + * Windows treates symbolic links to directories differently than it + * does to other file types. For that reason we check if the exists and + * is a directory. + */ + int flags = 0; + WindowsPath resolvedTarget = + WindowsPath.createFromNormalizedPath(getFileSystem(), resolve(target).path); + try { + if (WindowsFileAttributes.get(resolvedTarget, true).isDirectory()) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } catch (WindowsException x) { + // unable to access target so assume target is not a directory + } + + // create the link + try { + CreateSymbolicLink(getPathForWin32Calls(), + addPrefixIfNeeded(target.toString()), + flags); + } catch (WindowsException x) { + if (x.lastError() == ERROR_INVALID_REPARSE_DATA) { + x.rethrowAsIOException(this, target); + } else { + x.rethrowAsIOException(this); + } + } + return this; + } + + @Override + public Path createLink(Path obj) throws IOException { + WindowsPath existing = checkPath(obj); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("hard")); + this.checkWrite(); + existing.checkWrite(); + } + + // create hard link + try { + CreateHardLink(this.getPathForWin32Calls(), + existing.getPathForWin32Calls()); + } catch (WindowsException x) { + x.rethrowAsIOException(this, existing); + } + + return this; + } + + @Override + public WindowsPath readSymbolicLink() throws IOException { + if (!getFileSystem().supportsLinks()) { + throw new UnsupportedOperationException("symbolic links not supported"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + FilePermission perm = new FilePermission(getPathForPermissionCheck(), + SecurityConstants.FILE_READLINK_ACTION); + AccessController.checkPermission(perm); + } + + String target = WindowsLinkSupport.readLink(this); + return createFromNormalizedPath(getFileSystem(), target); + } + + @Override + public URI toUri() { + return WindowsUriSupport.toUri(this); + } + + @Override + public WindowsPath toAbsolutePath() { + if (isAbsolute()) + return this; + + // permission check as per spec + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPropertyAccess("user.dir"); + } + + try { + return createFromNormalizedPath(getFileSystem(), getAbsolutePath()); + } catch (WindowsException x) { + throw new IOError(new IOException(x.getMessage())); + } + } + + @Override + public WindowsPath toRealPath(boolean resolveLinks) throws IOException { + checkRead(); + String rp = WindowsLinkSupport.getRealPath(this, resolveLinks); + return createFromNormalizedPath(getFileSystem(), rp); + } + + @Override + public boolean isHidden() throws IOException { + checkRead(); + WindowsFileAttributes attrs = null; + try { + attrs = WindowsFileAttributes.get(this, true); + } catch (WindowsException x) { + x.rethrowAsIOException(this); + } + // DOS hidden attribute not meaningful when set on directories + if (attrs.isDirectory()) + return false; + return attrs.isHidden(); + } + + @Override + public WatchKey register(WatchService watcher, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + if (watcher == null) + throw new NullPointerException(); + if (!(watcher instanceof WindowsWatchService)) + throw new ProviderMismatchException(); + + // When a security manager is set then we need to make a defensive + // copy of the modifiers and check for the Windows specific FILE_TREE + // modifier. When the modifier is present then check that permission + // has been granted recursively. + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + boolean watchSubtree = false; + final int ml = modifiers.length; + if (ml > 0) { + modifiers = Arrays.copyOf(modifiers, ml); + int i=0; + while (i < ml) { + if (modifiers[i++] == ExtendedWatchEventModifier.FILE_TREE) { + watchSubtree = true; + break; + } + } + } + String s = getPathForPermissionCheck(); + sm.checkRead(s); + if (watchSubtree) + sm.checkRead(s + "\\-"); + } + + return ((WindowsWatchService)watcher).register(this, events, modifiers); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java new file mode 100644 index 00000000000..411b91b1c47 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java @@ -0,0 +1,225 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.InvalidPathException; + +/** + * A parser of Windows path strings + */ + +class WindowsPathParser { + private WindowsPathParser() { } + + /** + * The result of a parse operation + */ + static class Result { + private final WindowsPathType type; + private final String root; + private final String path; + + Result(WindowsPathType type, String root, String path) { + this.type = type; + this.root = root; + this.path = path; + } + + /** + * The path type + */ + WindowsPathType type() { + return type; + } + + /** + * The root component + */ + String root() { + return root; + } + + /** + * The normalized path (includes root) + */ + String path() { + return path; + } + } + + /** + * Parses the given input as a Windows path + */ + static Result parse(String input) { + if (input == null || input.length() == 0) + throw new InvalidPathException(input, "Empty or null path"); + return parse(input, true); + } + + /** + * Parses the given input as a Windows path where it is known that the + * path is already normalized. + */ + static Result parseNormalizedPath(String input) { + return parse(input, false); + } + + /** + * Parses the given input as a Windows path. + * + * @param requireToNormalize + * Indicates if the path requires to be normalized + */ + private static Result parse(String input, boolean requireToNormalize) { + String root = ""; + WindowsPathType type = null; + + int len = input.length(); + int off = 0; + if (len > 1) { + char c0 = input.charAt(0); + char c1 = input.charAt(1); + char c = 0; + int next = 2; + if (isSlash(c0) && isSlash(c1)) { + // UNC: We keep the first two slash, collapse all the + // following, then take the hostname and share name out, + // meanwhile collapsing all the redundant slashes. + type = WindowsPathType.UNC; + off = nextNonSlash(input, next, len); + next = nextSlash(input, off, len); + if (off == next) + throw new InvalidPathException(input, "UNC path is missing hostname"); + String host = input.substring(off, next); //host + off = nextNonSlash(input, next, len); + next = nextSlash(input, off, len); + if (off == next) + throw new InvalidPathException(input, "UNC path is missing sharename"); + root = "\\\\" + host + "\\" + input.substring(off, next) + "\\"; + off = next; + } else { + if (isLetter(c0) && c1 == ':') { + root = input.substring(0, 2); + if (len > 2 && isSlash(input.charAt(2))) { + off = 3; + root += "\\"; + type = WindowsPathType.ABSOLUTE; + } else { + off = 2; + type = WindowsPathType.DRIVE_RELATIVE; + } + } + } + } + if (off == 0) { + if (isSlash(input.charAt(0))) { + type = WindowsPathType.DIRECTORY_RELATIVE; + root = "\\"; + } else { + type = WindowsPathType.RELATIVE; + } + } + + if (requireToNormalize) { + StringBuilder sb = new StringBuilder(input.length()); + sb.append(root); + return new Result(type, root, normalize(sb, input, off)); + } else { + return new Result(type, root, input); + } + } + + /** + * Remove redundant slashes from the rest of the path, forcing all slashes + * into the preferred slash. + */ + private static String normalize(StringBuilder sb, String path, int off) { + int len = path.length(); + off = nextNonSlash(path, off, len); + int start = off; + char lastC = 0; + while (off < len) { + char c = path.charAt(off); + if (isSlash(c)) { + if (lastC == ' ') + throw new InvalidPathException(path, + "Trailing char <" + lastC + ">", + off - 1); + sb.append(path, start, off); + off = nextNonSlash(path, off, len); + if (off != len) //no slash at the end of normalized path + sb.append('\\'); + start = off; + } else { + if (isInvalidPathChar(c)) + throw new InvalidPathException(path, + "Illegal char <" + c + ">", + off); + lastC = c; + off++; + } + } + if (start != off) { + if (lastC == ' ') + throw new InvalidPathException(path, + "Trailing char <" + lastC + ">", + off - 1); + sb.append(path, start, off); + } + return sb.toString(); + } + + private static final boolean isSlash(char c) { + return (c == '\\') || (c == '/'); + } + + private static final int nextNonSlash(String path, int off, int end) { + while (off < end && isSlash(path.charAt(off))) { off++; } + return off; + } + + private static final int nextSlash(String path, int off, int end) { + char c; + while (off < end && !isSlash(c=path.charAt(off))) { + if (isInvalidPathChar(c)) + throw new InvalidPathException(path, + "Illegal character [" + c + "] in path", + off); + off++; + } + return off; + } + + private static final boolean isLetter(char c) { + return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')); + } + + // Reserved characters for window path name + private static final String reservedChars = "<>:\"|?*"; + private static final boolean isInvalidPathChar(char ch) { + return ch < '\u0020' || reservedChars.indexOf(ch) != -1; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java new file mode 100644 index 00000000000..ae3651f1f2d --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPathType.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +/** + * A type safe enum of Windows path types. + */ + +enum WindowsPathType { + ABSOLUTE, // C:\foo + UNC, // \\server\share\foo + RELATIVE, // foo + DIRECTORY_RELATIVE, // \foo + DRIVE_RELATIVE // C:foo +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java new file mode 100644 index 00000000000..9d44257b5ad --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurity.java @@ -0,0 +1,123 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Security related utility methods. + */ + +class WindowsSecurity { + private WindowsSecurity() { } + + // opens process token for given access + private static long openProcessToken(int access) { + try { + return OpenProcessToken(GetCurrentProcess(), access); + } catch (WindowsException x) { + return 0L; + } + } + + /** + * Returns the access token for this process with TOKEN_DUPLICATE access + */ + static final long processTokenWithDuplicateAccess = + openProcessToken(TOKEN_DUPLICATE); + + /** + * Returns the access token for this process with TOKEN_QUERY access + */ + static final long processTokenWithQueryAccess = + openProcessToken(TOKEN_QUERY); + + /** + * Returned by enablePrivilege when code may require a given privilege. + * The drop method should be invoked after the operation completes so as + * to revert the privilege. + */ + static interface Privilege { + void drop(); + } + + /** + * Attempts to enable the given privilege for this method. + */ + static Privilege enablePrivilege(String priv) { + final long pLuid; + try { + pLuid = LookupPrivilegeValue(priv); + } catch (WindowsException x) { + // indicates bug in caller + throw new AssertionError(x); + } + + long hToken = 0L; + boolean impersontating = false; + boolean elevated = false; + try { + hToken = OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES, false); + if (hToken == 0L && processTokenWithDuplicateAccess != 0L) { + hToken = DuplicateTokenEx(processTokenWithDuplicateAccess, + (TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE)); + SetThreadToken(0L, hToken); + impersontating = true; + } + + if (hToken != 0L) { + AdjustTokenPrivileges(hToken, pLuid, SE_PRIVILEGE_ENABLED); + elevated = true; + } + } catch (WindowsException x) { + // nothing to do, privilege not enabled + } + + final long token = hToken; + final boolean stopImpersontating = impersontating; + final boolean needToRevert = elevated; + + return new Privilege() { + @Override + public void drop() { + try { + if (stopImpersontating) { + SetThreadToken(0L, 0L); + } else { + if (needToRevert) { + AdjustTokenPrivileges(token, pLuid, 0); + } + } + } catch (WindowsException x) { + // should not happen + throw new AssertionError(x); + } + } + }; + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java new file mode 100644 index 00000000000..0fa0725c5db --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java @@ -0,0 +1,392 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.ProviderMismatchException; +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; +import sun.misc.Unsafe; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * A SecurityDescriptor for use when setting a file's ACL or creating a file + * with an initial ACL. + */ + +class WindowsSecurityDescriptor { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + /** + * typedef struct _ACL { + * BYTE AclRevision; + * BYTE Sbz1; + * WORD AclSize; + * WORD AceCount; + * WORD Sbz2; + * } ACL; + * + * typedef struct _ACE_HEADER { + * BYTE AceType; + * BYTE AceFlags; + * WORD AceSize; + * } ACE_HEADER; + * + * typedef struct _ACCESS_ALLOWED_ACE { + * ACE_HEADER Header; + * ACCESS_MASK Mask; + * DWORD SidStart; + * } ACCESS_ALLOWED_ACE; + * + * typedef struct _ACCESS_DENIED_ACE { + * ACE_HEADER Header; + * ACCESS_MASK Mask; + * DWORD SidStart; + * } ACCESS_DENIED_ACE; + * + * typedef struct _SECURITY_DESCRIPTOR { + * BYTE Revision; + * BYTE Sbz1; + * SECURITY_DESCRIPTOR_CONTROL Control; + * PSID Owner; + * PSID Group; + * PACL Sacl; + * PACL Dacl; + * } SECURITY_DESCRIPTOR; + */ + private static final short SIZEOF_ACL = 8; + private static final short SIZEOF_ACCESS_ALLOWED_ACE = 12; + private static final short SIZEOF_ACCESS_DENIED_ACE = 12; + private static final short SIZEOF_SECURITY_DESCRIPTOR = 20; + + private static final short OFFSETOF_TYPE = 0; + private static final short OFFSETOF_FLAGS = 1; + private static final short OFFSETOF_ACCESS_MASK = 4; + private static final short OFFSETOF_SID = 8; + + // null security descriptor + private static final WindowsSecurityDescriptor NULL_DESCRIPTOR = + new WindowsSecurityDescriptor(); + + // native resources + private final List sidList; + private final NativeBuffer aclBuffer, sdBuffer; + + /** + * Creates the "null" SecurityDescriptor + */ + private WindowsSecurityDescriptor() { + this.sidList = null; + this.aclBuffer = null; + this.sdBuffer = null; + } + + /** + * Creates a SecurityDescriptor from the given ACL + */ + private WindowsSecurityDescriptor(List acl) throws IOException { + boolean initialized = false; + + // SECURITY: need to copy list in case size changes during processing + acl = new ArrayList(acl); + + // list of SIDs + sidList = new ArrayList(acl.size()); + try { + // initial size of ACL + int size = SIZEOF_ACL; + + // get the SID for each entry + for (AclEntry entry: acl) { + UserPrincipal user = entry.principal(); + if (!(user instanceof WindowsUserPrincipals.User)) + throw new ProviderMismatchException(); + String sidString = ((WindowsUserPrincipals.User)user).sidString(); + try { + long pSid = ConvertStringSidToSid(sidString); + sidList.add(pSid); + + // increase size to allow for entry + size += GetLengthSid(pSid) + + Math.max(SIZEOF_ACCESS_ALLOWED_ACE, SIZEOF_ACCESS_DENIED_ACE); + + } catch (WindowsException x) { + throw new IOException("Failed to get SID for " + user.getName() + + ": " + x.errorString()); + } + } + + // allocate memory for the ACL + aclBuffer = NativeBuffers.getNativeBuffer(size); + sdBuffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR); + + InitializeAcl(aclBuffer.address(), size); + + // Add entry ACE to the ACL + int i = 0; + while (i < acl.size()) { + AclEntry entry = acl.get(i); + long pSid = sidList.get(i); + try { + encode(entry, pSid, aclBuffer.address()); + } catch (WindowsException x) { + throw new IOException("Failed to encode ACE: " + + x.errorString()); + } + i++; + } + + // initialize security descriptor and set DACL + InitializeSecurityDescriptor(sdBuffer.address()); + SetSecurityDescriptorDacl(sdBuffer.address(), aclBuffer.address()); + initialized = true; + } catch (WindowsException x) { + throw new IOException(x.getMessage()); + } finally { + // release resources if not completely initialized + if (!initialized) + release(); + } + } + + /** + * Releases memory associated with SecurityDescriptor + */ + void release() { + if (sdBuffer != null) + sdBuffer.release(); + if (aclBuffer != null) + aclBuffer.release(); + if (sidList != null) { + // release memory for SIDs + for (Long sid: sidList) { + LocalFree(sid); + } + } + } + + /** + * Returns address of SecurityDescriptor + */ + long address() { + return (sdBuffer == null) ? 0L : sdBuffer.address(); + } + + // decode Windows ACE to NFSv4 AclEntry + private static AclEntry decode(long aceAddress) + throws IOException + { + // map type + byte aceType = unsafe.getByte(aceAddress + OFFSETOF_TYPE); + if (aceType != ACCESS_ALLOWED_ACE_TYPE && aceType != ACCESS_DENIED_ACE_TYPE) + return null; + AclEntryType type; + if (aceType == ACCESS_ALLOWED_ACE_TYPE) { + type = AclEntryType.ALLOW; + } else { + type = AclEntryType.DENY; + } + + // map flags + byte aceFlags = unsafe.getByte(aceAddress + OFFSETOF_FLAGS); + Set flags = new HashSet(); + if ((aceFlags & OBJECT_INHERIT_ACE) != 0) + flags.add(AclEntryFlag.FILE_INHERIT); + if ((aceFlags & CONTAINER_INHERIT_ACE) != 0) + flags.add(AclEntryFlag.DIRECTORY_INHERIT); + if ((aceFlags & NO_PROPAGATE_INHERIT_ACE) != 0) + flags.add(AclEntryFlag.NO_PROPAGATE_INHERIT); + if ((aceFlags & INHERIT_ONLY_ACE) != 0) + flags.add(AclEntryFlag.INHERIT_ONLY); + + // map access mask + int mask = unsafe.getInt(aceAddress + OFFSETOF_ACCESS_MASK); + Set perms = new HashSet(); + if ((mask & FILE_READ_DATA) > 0) + perms.add(AclEntryPermission.READ_DATA); + if ((mask & FILE_WRITE_DATA) > 0) + perms.add(AclEntryPermission.WRITE_DATA); + if ((mask & FILE_APPEND_DATA ) > 0) + perms.add(AclEntryPermission.APPEND_DATA); + if ((mask & FILE_READ_EA) > 0) + perms.add(AclEntryPermission.READ_NAMED_ATTRS); + if ((mask & FILE_WRITE_EA) > 0) + perms.add(AclEntryPermission.WRITE_NAMED_ATTRS); + if ((mask & FILE_EXECUTE) > 0) + perms.add(AclEntryPermission.EXECUTE); + if ((mask & FILE_DELETE_CHILD ) > 0) + perms.add(AclEntryPermission.DELETE_CHILD); + if ((mask & FILE_READ_ATTRIBUTES) > 0) + perms.add(AclEntryPermission.READ_ATTRIBUTES); + if ((mask & FILE_WRITE_ATTRIBUTES) > 0) + perms.add(AclEntryPermission.WRITE_ATTRIBUTES); + if ((mask & DELETE) > 0) + perms.add(AclEntryPermission.DELETE); + if ((mask & READ_CONTROL) > 0) + perms.add(AclEntryPermission.READ_ACL); + if ((mask & WRITE_DAC) > 0) + perms.add(AclEntryPermission.WRITE_ACL); + if ((mask & WRITE_OWNER) > 0) + perms.add(AclEntryPermission.WRITE_OWNER); + if ((mask & SYNCHRONIZE) > 0) + perms.add(AclEntryPermission.SYNCHRONIZE); + + // lookup SID to create UserPrincipal + long sidAddress = aceAddress + OFFSETOF_SID; + UserPrincipal user = WindowsUserPrincipals.fromSid(sidAddress); + + return AclEntry.newBuilder() + .setType(type) + .setPrincipal(user) + .setFlags(flags).setPermissions(perms).build(); + } + + // encode NFSv4 AclEntry as Windows ACE to given ACL + private static void encode(AclEntry ace, long sidAddress, long aclAddress) + throws WindowsException + { + // ignore non-allow/deny entries for now + if (ace.type() != AclEntryType.ALLOW && ace.type() != AclEntryType.DENY) + return; + boolean allow = (ace.type() == AclEntryType.ALLOW); + + // map access mask + Set aceMask = ace.permissions(); + int mask = 0; + if (aceMask.contains(AclEntryPermission.READ_DATA)) + mask |= FILE_READ_DATA; + if (aceMask.contains(AclEntryPermission.WRITE_DATA)) + mask |= FILE_WRITE_DATA; + if (aceMask.contains(AclEntryPermission.APPEND_DATA)) + mask |= FILE_APPEND_DATA; + if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS)) + mask |= FILE_READ_EA; + if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS)) + mask |= FILE_WRITE_EA; + if (aceMask.contains(AclEntryPermission.EXECUTE)) + mask |= FILE_EXECUTE; + if (aceMask.contains(AclEntryPermission.DELETE_CHILD)) + mask |= FILE_DELETE_CHILD; + if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES)) + mask |= FILE_READ_ATTRIBUTES; + if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES)) + mask |= FILE_WRITE_ATTRIBUTES; + if (aceMask.contains(AclEntryPermission.DELETE)) + mask |= DELETE; + if (aceMask.contains(AclEntryPermission.READ_ACL)) + mask |= READ_CONTROL; + if (aceMask.contains(AclEntryPermission.WRITE_ACL)) + mask |= WRITE_DAC; + if (aceMask.contains(AclEntryPermission.WRITE_OWNER)) + mask |= WRITE_OWNER; + if (aceMask.contains(AclEntryPermission.SYNCHRONIZE)) + mask |= SYNCHRONIZE; + + // map flags + Set aceFlags = ace.flags(); + byte flags = 0; + if (aceFlags.contains(AclEntryFlag.FILE_INHERIT)) + flags |= OBJECT_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT)) + flags |= CONTAINER_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT)) + flags |= NO_PROPAGATE_INHERIT_ACE; + if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY)) + flags |= INHERIT_ONLY_ACE; + + if (allow) { + AddAccessAllowedAceEx(aclAddress, flags, mask, sidAddress); + } else { + AddAccessDeniedAceEx(aclAddress, flags, mask, sidAddress); + } + } + + /** + * Creates a security descriptor with a DACL representing the given ACL. + */ + static WindowsSecurityDescriptor create(List acl) + throws IOException + { + return new WindowsSecurityDescriptor(acl); + } + + /** + * Processes the array of attributes looking for the attribute "acl:acl". + * Returns security descriptor representing the ACL or the "null" security + * descriptor if the attribute is not in the array. + */ + @SuppressWarnings("unchecked") + static WindowsSecurityDescriptor fromAttribute(FileAttribute... attrs) + throws IOException + { + WindowsSecurityDescriptor sd = NULL_DESCRIPTOR; + for (FileAttribute attr: attrs) { + // if more than one ACL specified then last one wins + if (sd != NULL_DESCRIPTOR) + sd.release(); + if (attr == null) + throw new NullPointerException(); + if (attr.name().equals("acl:acl")) { + List acl = (List)attr.value(); + sd = new WindowsSecurityDescriptor(acl); + } else { + throw new UnsupportedOperationException("'" + attr.name() + + "' not supported as initial attribute"); + } + } + return sd; + } + + /** + * Extracts DACL from security descriptor. + */ + static List getAcl(long pSecurityDescriptor) throws IOException { + // get address of DACL + long aclAddress = GetSecurityDescriptorDacl(pSecurityDescriptor); + + // get ACE count + int aceCount = 0; + if (aclAddress == 0L) { + // no ACEs + aceCount = 0; + } else { + AclInformation aclInfo = GetAclInformation(aclAddress); + aceCount = aclInfo.aceCount(); + } + ArrayList result = new ArrayList(aceCount); + + // decode each of the ACEs to AclEntry objects + for (int i=0; i 2) && (path.charAt(2) == ':')) { + // "/c:/foo" --> "c:/foo" + path = path.substring(1); + } + } + return WindowsPath.parse(fs, path); + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java b/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java new file mode 100644 index 00000000000..db361c97e0d --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java @@ -0,0 +1,342 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.io.IOException; +import java.util.*; +import sun.misc.Unsafe; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/** + * Windows emulation of NamedAttributeView using Alternative Data Streams + */ + +class WindowsUserDefinedFileAttributeView + extends AbstractUserDefinedFileAttributeView +{ + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + // syntax to address named streams + private String join(String file, String name) { + if (name == null) + throw new NullPointerException("'name' is null"); + return file + ":" + name; + } + private String join(WindowsPath file, String name) throws WindowsException { + return join(file.getPathForWin32Calls(), name); + } + + private final WindowsPath file; + private final boolean followLinks; + + WindowsUserDefinedFileAttributeView(WindowsPath file, boolean followLinks) { + this.file = file; + this.followLinks = followLinks; + } + + // enumerates the file streams using FindFirstStream/FindNextStream APIs. + private List listUsingStreamEnumeration() throws IOException { + List list = new ArrayList(); + try { + FirstStream first = FindFirstStream(file.getPathForWin32Calls()); + if (first != null) { + long handle = first.handle(); + try { + // first stream is always ::$DATA for files + String name = first.name(); + if (!name.equals("::$DATA")) { + String[] segs = name.split(":"); + list.add(segs[1]); + } + while ((name = FindNextStream(handle)) != null) { + String[] segs = name.split(":"); + list.add(segs[1]); + } + } finally { + FindClose(handle); + } + } + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } + return Collections.unmodifiableList(list); + } + + // enumerates the file streams by reading the stream headers using + // BackupRead + private List listUsingBackupRead() throws IOException { + long handle = -1L; + try { + int flags = FILE_FLAG_BACKUP_SEMANTICS; + if (!followLinks && file.getFileSystem().supportsLinks()) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + + handle = CreateFile(file.getPathForWin32Calls(), + GENERIC_READ, + FILE_SHARE_READ, // no write as we depend on file size + OPEN_EXISTING, + flags); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } + + // buffer to read stream header and stream name. + final int BUFFER_SIZE = 4096; + NativeBuffer buffer = null; + + // result with names of alternative data streams + final List list = new ArrayList(); + + try { + buffer = NativeBuffers.getNativeBuffer(BUFFER_SIZE); + long address = buffer.address(); + + /** + * typedef struct _WIN32_STREAM_ID { + * DWORD dwStreamId; + * DWORD dwStreamAttributes; + * LARGE_INTEGER Size; + * DWORD dwStreamNameSize; + * WCHAR cStreamName[ANYSIZE_ARRAY]; + * } WIN32_STREAM_ID; + */ + final int SIZEOF_STREAM_HEADER = 20; + final int OFFSETOF_STREAM_ID = 0; + final int OFFSETOF_STREAM_SIZE = 8; + final int OFFSETOF_STREAM_NAME_SIZE = 16; + + long context = 0L; + try { + for (;;) { + // read stream header + BackupResult result = BackupRead(handle, address, + SIZEOF_STREAM_HEADER, false, context); + context = result.context(); + if (result.bytesTransferred() == 0) + break; + + int streamId = unsafe.getInt(address + OFFSETOF_STREAM_ID); + long streamSize = unsafe.getLong(address + OFFSETOF_STREAM_SIZE); + int nameSize = unsafe.getInt(address + OFFSETOF_STREAM_NAME_SIZE); + + // read stream name + if (nameSize > 0) { + result = BackupRead(handle, address, nameSize, false, context); + if (result.bytesTransferred() != nameSize) + break; + } + + // check for alternative data stream + if (streamId == BACKUP_ALTERNATE_DATA) { + char[] nameAsArray = new char[nameSize/2]; + unsafe.copyMemory(null, address, nameAsArray, + Unsafe.ARRAY_CHAR_BASE_OFFSET, nameSize); + + String[] segs = new String(nameAsArray).split(":"); + if (segs.length == 3) + list.add(segs[1]); + } + + // sparse blocks not currently handled as documentation + // is not sufficient on how the spase block can be skipped. + if (streamId == BACKUP_SPARSE_BLOCK) { + throw new IOException("Spare blocks not handled"); + } + + // seek to end of stream + if (streamSize > 0L) { + BackupSeek(handle, streamSize, context); + } + } + } catch (WindowsException x) { + // failed to read or seek + throw new IOException(x.errorString()); + } finally { + // release context + if (context != 0L) { + try { + BackupRead(handle, 0L, 0, true, context); + } catch (WindowsException ignore) { } + } + } + } finally { + if (buffer != null) + buffer.release(); + CloseHandle(handle); + } + return Collections.unmodifiableList(list); + } + + @Override + public List list() throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + // use stream APIs on Windwos Server 2003 and newer + if (file.getFileSystem().supportsStreamEnumeration()) { + return listUsingStreamEnumeration(); + } else { + return listUsingBackupRead(); + } + } + + @Override + public int size(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + // wrap with channel + FileChannel fc = null; + try { + Set opts = new HashSet(); + opts.add(READ); + if (!followLinks) + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); + fc = WindowsChannelFactory + .newFileChannel(join(file, name), null, opts, 0L); + } catch (WindowsException x) { + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + } + try { + long size = fc.size(); + if (size > Integer.MAX_VALUE) + throw new ArithmeticException("Stream too large"); + return (int)size; + } finally { + fc.close(); + } + } + + @Override + public int read(String name, ByteBuffer dst) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), true, false); + + // wrap with channel + FileChannel fc = null; + try { + Set opts = new HashSet(); + opts.add(READ); + if (!followLinks) + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); + fc = WindowsChannelFactory + .newFileChannel(join(file, name), null, opts, 0L); + } catch (WindowsException x) { + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + } + + // read to EOF (nothing we can do if I/O error occurs) + try { + if (fc.size() > dst.remaining()) + throw new IOException("Stream too large"); + int total = 0; + while (dst.hasRemaining()) { + int n = fc.read(dst); + if (n < 0) + break; + total += n; + } + return total; + } finally { + fc.close(); + } + } + + @Override + public int write(String name, ByteBuffer src) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + /** + * Creating a named stream will cause the unnamed stream to be created + * if it doesn't already exist. To avoid this we open the unnamed stream + * for reading and hope it isn't deleted/moved while we create or + * replace the named stream. Opening the file without sharing options + * may cause sharing violations with other programs that are accessing + * the unnamed stream. + */ + long handle = -1L; + try { + int flags = FILE_FLAG_BACKUP_SEMANTICS; + if (!followLinks) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + + handle = CreateFile(file.getPathForWin32Calls(), + GENERIC_READ, + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), + OPEN_EXISTING, + flags); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } + try { + Set opts = new HashSet(); + if (!followLinks) + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); + opts.add(CREATE); + opts.add(WRITE); + opts.add(StandardOpenOption.TRUNCATE_EXISTING); + FileChannel named = null; + try { + named = WindowsChannelFactory + .newFileChannel(join(file, name), null, opts, 0L); + } catch (WindowsException x) { + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); + } + // write value (nothing we can do if I/O error occurs) + try { + int rem = src.remaining(); + while (src.hasRemaining()) { + named.write(src); + } + return rem; + } finally { + named.close(); + } + } finally { + CloseHandle(handle); + } + } + + @Override + public void delete(String name) throws IOException { + if (System.getSecurityManager() != null) + checkAccess(file.getPathForPermissionCheck(), false, true); + + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + String toDelete = join(path, name); + try { + DeleteFile(toDelete); + } catch (WindowsException x) { + x.rethrowAsIOException(toDelete); + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java b/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java new file mode 100644 index 00000000000..caf36f17c12 --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsUserPrincipals.java @@ -0,0 +1,169 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.nio.fs; + +import java.nio.file.attribute.*; +import java.io.IOException; + +import static sun.nio.fs.WindowsConstants.*; +import static sun.nio.fs.WindowsNativeDispatcher.*; + +class WindowsUserPrincipals { + private WindowsUserPrincipals() { } + + static class User implements UserPrincipal { + // String representation of SID + private final String sidString; + + // SID type + private final int sidType; + + // Account name (if available) or SID + private final String accountName; + + User(String sidString, int sidType, String accountName) { + this.sidString = sidString; + this.sidType = sidType; + this.accountName = accountName; + } + + // package-private + String sidString() { + return sidString; + } + + @Override + public String getName() { + return accountName; + } + + @Override + public String toString() { + String type; + switch (sidType) { + case SidTypeUser : type = "User"; break; + case SidTypeGroup : type = "Group"; break; + case SidTypeDomain : type = "Domain"; break; + case SidTypeAlias : type = "Alias"; break; + case SidTypeWellKnownGroup : type = "Well-known group"; break; + case SidTypeDeletedAccount : type = "Deleted"; break; + case SidTypeInvalid : type = "Invalid"; break; + case SidTypeComputer : type = "Computer"; break; + default: type = "Unknown"; + } + return accountName + " (" + type + ")"; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (!(obj instanceof WindowsUserPrincipals.User)) + return false; + WindowsUserPrincipals.User other = (WindowsUserPrincipals.User)obj; + return this.sidString.equals(other.sidString); + } + + @Override + public int hashCode() { + return sidString.hashCode(); + } + } + + static class Group extends User implements GroupPrincipal { + Group(String sidString, int sidType, String accountName) { + super(sidString, sidType, accountName); + } + } + + static UserPrincipal fromSid(long sidAddress) throws IOException { + String sidString; + try { + sidString = ConvertSidToStringSid(sidAddress); + if (sidString == null) { + // pre-Windows XP system? + throw new AssertionError(); + } + } catch (WindowsException x) { + throw new IOException("Unable to convert SID to String: " + + x.errorString()); + } + + // lookup account; if not available then use the SID as the name + Account account = null; + String name; + try { + account = LookupAccountSid(sidAddress); + name = account.domain() + "\\" + account.name(); + } catch (WindowsException x) { + name = sidString; + } + + int sidType = (account == null) ? SidTypeUnknown : account.use(); + if ((sidType == SidTypeGroup) || + (sidType == SidTypeWellKnownGroup) || + (sidType == SidTypeAlias)) // alias for local group + { + return new Group(sidString, sidType, name); + } else { + return new User(sidString, sidType, name); + } + } + + static UserPrincipal lookup(String name) throws IOException { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("lookupUserInformation")); + } + + // invoke LookupAccountName to get buffer size needed for SID + int size = 0; + try { + size = LookupAccountName(name, 0L, 0); + } catch (WindowsException x) { + if (x.lastError() == ERROR_NONE_MAPPED) + throw new UserPrincipalNotFoundException(name); + throw new IOException(name + ": " + x.errorString()); + } + assert size > 0; + + // allocate buffer and re-invoke LookupAccountName get SID + NativeBuffer sidBuffer = NativeBuffers.getNativeBuffer(size); + try { + int newSize = LookupAccountName(name, sidBuffer.address(), size); + if (newSize != size) { + // can this happen? + throw new AssertionError("SID change during lookup"); + } + + // return user principal + return fromSid(sidBuffer.address()); + } catch (WindowsException x) { + throw new IOException(name + ": " + x.errorString()); + } finally { + sidBuffer.release(); + } + } +} diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java new file mode 100644 index 00000000000..6a5190784dc --- /dev/null +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -0,0 +1,582 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.io.IOException; +import java.util.*; +import com.sun.nio.file.ExtendedWatchEventModifier; +import sun.misc.Unsafe; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; + +/* + * Win32 implementation of WatchService based on ReadDirectoryChangesW. + */ + +class WindowsWatchService + extends AbstractWatchService +{ + private final Unsafe unsafe = Unsafe.getUnsafe(); + + // background thread to service I/O completion port + private final Poller poller; + + /** + * Creates an I/O completion port and a daemon thread to service it + */ + WindowsWatchService(WindowsFileSystem fs) throws IOException { + // create I/O completion port + long port = 0L; + try { + port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0); + } catch (WindowsException x) { + throw new IOException(x.getMessage()); + } + + this.poller = new Poller(fs, this, port); + this.poller.start(); + } + + @Override + WatchKey register(Path path, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + throws IOException + { + // delegate to poller + return poller.register(path, events, modifiers); + } + + @Override + void implClose() throws IOException { + // delegate to poller + poller.close(); + } + + /** + * Windows implementation of WatchKey. + */ + private class WindowsWatchKey extends AbstractWatchKey { + // file key (used to detect existing registrations) + private FileKey fileKey; + + // handle to directory + private volatile long handle = INVALID_HANDLE_VALUE; + + // interest events + private Set> events; + + // subtree + private boolean watchSubtree; + + // buffer for change events + private NativeBuffer buffer; + + // pointer to bytes returned (in buffer) + private long countAddress; + + // pointer to overlapped structure (in buffer) + private long overlappedAddress; + + // completion key (used to map I/O completion to WatchKey) + private int completionKey; + + WindowsWatchKey(AbstractWatchService watcher, FileKey fileKey) { + super(watcher); + this.fileKey = fileKey; + } + + WindowsWatchKey init(long handle, + Set> events, + boolean watchSubtree, + NativeBuffer buffer, + long countAddress, + long overlappedAddress, + int completionKey) + { + this.handle = handle; + this.events = events; + this.watchSubtree = watchSubtree; + this.buffer = buffer; + this.countAddress = countAddress; + this.overlappedAddress = overlappedAddress; + this.completionKey = completionKey; + return this; + } + + long handle() { + return handle; + } + + Set> events() { + return events; + } + + void setEvents(Set> events) { + this.events = events; + } + + boolean watchSubtree() { + return watchSubtree; + } + + NativeBuffer buffer() { + return buffer; + } + + long countAddress() { + return countAddress; + } + + long overlappedAddress() { + return overlappedAddress; + } + + FileKey fileKey() { + return fileKey; + } + + int completionKey() { + return completionKey; + } + + // close directory and release buffer + void releaseResources() { + CloseHandle(handle); + buffer.cleaner().clean(); + } + + // Invalidate key by closing directory and releasing buffer + void invalidate() { + releaseResources(); + handle = INVALID_HANDLE_VALUE; + buffer = null; + countAddress = 0; + overlappedAddress = 0; + } + + @Override + public boolean isValid() { + return handle != INVALID_HANDLE_VALUE; + } + + @Override + public void cancel() { + if (isValid()) { + // delegate to poller + poller.cancel(this); + } + } + } + + // file key to unique identify (open) directory + private static class FileKey { + private final int volSerialNumber; + private final int fileIndexHigh; + private final int fileIndexLow; + + FileKey(int volSerialNumber, int fileIndexHigh, int fileIndexLow) { + this.volSerialNumber = volSerialNumber; + this.fileIndexHigh = fileIndexHigh; + this.fileIndexLow = fileIndexLow; + } + + @Override + public int hashCode() { + return volSerialNumber ^ fileIndexHigh ^ fileIndexLow; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (!(obj instanceof FileKey)) + return false; + FileKey other = (FileKey)obj; + if (this.volSerialNumber != other.volSerialNumber) return false; + if (this.fileIndexHigh != other.fileIndexHigh) return false; + if (this.fileIndexLow != other.fileIndexLow) return false; + return true; + } + } + + // all change events + private static final int ALL_FILE_NOTIFY_EVENTS = + FILE_NOTIFY_CHANGE_FILE_NAME | + FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_ATTRIBUTES | + FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_CREATION | + FILE_NOTIFY_CHANGE_SECURITY; + + /** + * Background thread to service I/O completion port. + */ + private class Poller extends AbstractPoller { + /* + * typedef struct _OVERLAPPED { + * DWORD Internal; + * DWORD InternalHigh; + * DWORD Offset; + * DWORD OffsetHigh; + * HANDLE hEvent; + * } OVERLAPPED; + */ + private static final short SIZEOF_DWORD = 4; + private static final short SIZEOF_OVERLAPPED = 32; // 20 on 32-bit + + /* + * typedef struct _FILE_NOTIFY_INFORMATION { + * DWORD NextEntryOffset; + * DWORD Action; + * DWORD FileNameLength; + * WCHAR FileName[1]; + * } FileNameLength; + */ + private static final short OFFSETOF_NEXTENTRYOFFSET = 0; + private static final short OFFSETOF_ACTION = 4; + private static final short OFFSETOF_FILENAMELENGTH = 8; + private static final short OFFSETOF_FILENAME = 12; + + // size of per-directory buffer for events (FIXME - make this configurable) + private static final int CHANGES_BUFFER_SIZE = 16 * 1024; + + private final WindowsFileSystem fs; + private final WindowsWatchService watcher; + private final long port; + + // maps completion key to WatchKey + private final Map int2key; + + // maps file key to WatchKey + private final Map fk2key; + + // unique completion key for each directory + private int lastCompletionKey; + + Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) { + this.fs = fs; + this.watcher = watcher; + this.port = port; + this.int2key = new HashMap(); + this.fk2key = new HashMap(); + this.lastCompletionKey = 0; + } + + @Override + void wakeup() throws IOException { + try { + PostQueuedCompletionStatus(port, 0); + } catch (WindowsException x) { + throw new IOException(x.getMessage()); + } + } + + /** + * Register a directory for changes as follows: + * + * 1. Open directory + * 2. Read its attributes (and check it really is a directory) + * 3. Assign completion key and associated handle with completion port + * 4. Call ReadDirectoryChangesW to start (async) read of changes + * 5. Create or return existing key representing registration + */ + @Override + Object implRegister(Path obj, + Set> events, + WatchEvent.Modifier... modifiers) + { + WindowsPath dir = (WindowsPath)obj; + boolean watchSubtree = false; + + // FILE_TREE modifier allowed + for (WatchEvent.Modifier modifier: modifiers) { + if (modifier == ExtendedWatchEventModifier.FILE_TREE) { + watchSubtree = true; + continue; + } else { + if (modifier == null) + return new NullPointerException(); + if (modifier instanceof com.sun.nio.file.SensitivityWatchEventModifier) + continue; // ignore + return new UnsupportedOperationException("Modifier not supported"); + } + } + + // open directory + long handle = -1L; + try { + handle = CreateFile(dir.getPathForWin32Calls(), + FILE_LIST_DIRECTORY, + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED); + } catch (WindowsException x) { + return x.asIOException(dir); + } + + boolean registered = false; + try { + // read attributes and check file is a directory + WindowsFileAttributes attrs = null; + try { + attrs = WindowsFileAttributes.readAttributes(handle); + } catch (WindowsException x) { + return x.asIOException(dir); + } + if (!attrs.isDirectory()) { + return new NotDirectoryException(dir.getPathForExceptionMessage()); + } + + // check if this directory is already registered + FileKey fk = new FileKey(attrs.volSerialNumber(), + attrs.fileIndexHigh(), + attrs.fileIndexLow()); + WindowsWatchKey existing = fk2key.get(fk); + + // if already registered and we're not changing the subtree + // modifier then simply update the event and return the key. + if (existing != null && watchSubtree == existing.watchSubtree()) { + existing.setEvents(events); + return existing; + } + + // unique completion key (skip 0) + int completionKey = ++lastCompletionKey; + if (completionKey == 0) + completionKey = ++lastCompletionKey; + + // associate handle with completion port + try { + CreateIoCompletionPort(handle, port, completionKey); + } catch (WindowsException x) { + return new IOException(x.getMessage()); + } + + // allocate memory for events, including space for other structures + // needed to do overlapped I/O + int size = CHANGES_BUFFER_SIZE + SIZEOF_DWORD + SIZEOF_OVERLAPPED; + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + + long bufferAddress = buffer.address(); + long overlappedAddress = bufferAddress + size - SIZEOF_OVERLAPPED; + long countAddress = overlappedAddress - SIZEOF_DWORD; + + // start async read of changes to directory + try { + ReadDirectoryChangesW(handle, + bufferAddress, + CHANGES_BUFFER_SIZE, + watchSubtree, + ALL_FILE_NOTIFY_EVENTS, + countAddress, + overlappedAddress); + } catch (WindowsException x) { + buffer.release(); + return new IOException(x.getMessage()); + } + + WindowsWatchKey watchKey; + if (existing == null) { + // not registered so create new watch key + watchKey = new WindowsWatchKey(watcher, fk) + .init(handle, events, watchSubtree, buffer, countAddress, + overlappedAddress, completionKey); + // map file key to watch key + fk2key.put(fk, watchKey); + } else { + // directory already registered so need to: + // 1. remove mapping from old completion key to existing watch key + // 2. release existing key's resources (handle/buffer) + // 3. re-initialize key with new handle/buffer + int2key.remove(existing.completionKey()); + existing.releaseResources(); + watchKey = existing.init(handle, events, watchSubtree, buffer, + countAddress, overlappedAddress, completionKey); + } + // map completion map to watch key + int2key.put(completionKey, watchKey); + + registered = true; + return watchKey; + + } finally { + if (!registered) CloseHandle(handle); + } + } + + // cancel single key + @Override + void implCancelKey(WatchKey obj) { + WindowsWatchKey key = (WindowsWatchKey)obj; + if (key.isValid()) { + fk2key.remove(key.fileKey()); + int2key.remove(key.completionKey()); + key.invalidate(); + } + } + + // close watch service + @Override + void implCloseAll() { + // cancel all keys + for (Map.Entry entry: int2key.entrySet()) { + entry.getValue().invalidate(); + } + fk2key.clear(); + int2key.clear(); + + // close I/O completion port + CloseHandle(port); + } + + // Translate file change action into watch event + private WatchEvent.Kind translateActionToEvent(int action) + { + switch (action) { + case FILE_ACTION_MODIFIED : + return StandardWatchEventKind.ENTRY_MODIFY; + + case FILE_ACTION_ADDED : + case FILE_ACTION_RENAMED_NEW_NAME : + return StandardWatchEventKind.ENTRY_CREATE; + + case FILE_ACTION_REMOVED : + case FILE_ACTION_RENAMED_OLD_NAME : + return StandardWatchEventKind.ENTRY_DELETE; + + default : + return null; // action not recognized + } + } + + // process events (list of FILE_NOTIFY_INFORMATION structures) + private void processEvents(WindowsWatchKey key, int size) { + long address = key.buffer().address(); + + int nextOffset; + do { + int action = unsafe.getInt(address + OFFSETOF_ACTION); + + // map action to event + WatchEvent.Kind kind = translateActionToEvent(action); + if (key.events().contains(kind)) { + // copy the name + int nameLengthInBytes = unsafe.getInt(address + OFFSETOF_FILENAMELENGTH); + if ((nameLengthInBytes % 2) != 0) { + throw new AssertionError("FileNameLength.FileNameLength is not a multiple of 2"); + } + char[] nameAsArray = new char[nameLengthInBytes/2]; + unsafe.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray, + Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes); + + // create FileName and queue event + WindowsPath name = WindowsPath + .createFromNormalizedPath(fs, new String(nameAsArray)); + key.signalEvent(kind, name); + } + + // next event + nextOffset = unsafe.getInt(address + OFFSETOF_NEXTENTRYOFFSET); + address += (long)nextOffset; + } while (nextOffset != 0); + } + + /** + * Poller main loop + */ + @Override + public void run() { + for (;;) { + CompletionStatus info = null; + try { + info = GetQueuedCompletionStatus(port); + } catch (WindowsException x) { + // this should not happen + x.printStackTrace(); + return; + } + + // wakeup + if (info.completionKey() == 0) { + boolean shutdown = processRequests(); + if (shutdown) { + return; + } + continue; + } + + // map completionKey to get WatchKey + WindowsWatchKey key = int2key.get(info.completionKey()); + if (key == null) { + // We get here when a registration is changed. In that case + // the directory is closed which causes an event with the + // old completion key. + continue; + } + + // ReadDirectoryChangesW failed + if (info.error() != 0) { + // buffer overflow + if (info.error() == ERROR_NOTIFY_ENUM_DIR) { + key.signalEvent(StandardWatchEventKind.OVERFLOW, null); + } else { + // other error so cancel key + implCancelKey(key); + key.signal(); + } + continue; + } + + // process the events + if (info.bytesTransferred() > 0) { + processEvents(key, info.bytesTransferred()); + } else { + // insufficient buffer size + key.signalEvent(StandardWatchEventKind.OVERFLOW, null); + } + + // start read for next batch of changes + try { + ReadDirectoryChangesW(key.handle(), + key.buffer().address(), + CHANGES_BUFFER_SIZE, + key.watchSubtree(), + ALL_FILE_NOTIFY_EVENTS, + key.countAddress(), + key.overlappedAddress()); + } catch (WindowsException x) { + // no choice but to cancel key + implCancelKey(key); + key.signal(); + } + } + } + } +} diff --git a/jdk/src/windows/native/sun/awt/splashscreen/splashscreen_sys.c b/jdk/src/windows/native/sun/awt/splashscreen/splashscreen_sys.c index 069cf301d3b..c5b42b9f4b5 100644 --- a/jdk/src/windows/native/sun/awt/splashscreen/splashscreen_sys.c +++ b/jdk/src/windows/native/sun/awt/splashscreen/splashscreen_sys.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,24 +23,21 @@ * have any questions. */ +// copy from awt.h +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif + +// copy from awt.h +#ifndef _WIN32_IE +#define _WIN32_IE 0x0600 +#endif + #include "splashscreen_impl.h" #include #include #include -/* layered windows api prototypes. wouldn't be needed if we could use an updated version of the MS PSDK. */ - -typedef BOOL WINAPI UpdateLayeredWindowT(HWND hwnd, // handle to layered window - HDC hdcDst, // handle to screen DC - POINT * pptDst, // new screen position - SIZE * psize, // new size of the layered window - HDC hdcSrc, // handle to surface DC - POINT * pptSrc, // layer position - COLORREF crKey, // color key - BLENDFUNCTION * pblend, // blend function - DWORD dwFlags // options - ); - #ifndef WS_EX_LAYERED #define WS_EX_LAYERED 0x80000 #endif @@ -57,21 +54,6 @@ typedef BOOL WINAPI UpdateLayeredWindowT(HWND hwnd, // handle to layered win #define AC_SRC_ALPHA 0x01 #endif -static UpdateLayeredWindowT *UpdateLayeredWindow = NULL; - -/* Get/SetWindowLongPtr prototypes, for the case we're compiling with old headers for a 32-bit platform - copied from Component.cpp - FIXME: remove this as soon as the build process is using up-to-date headers */ -#if !defined(__int3264) -#define GetWindowLongPtr GetWindowLong -#define SetWindowLongPtr SetWindowLong -#define GWLP_USERDATA GWL_USERDATA -#define GWLP_WNDPROC GWL_WNDPROC -typedef __int32 LONG_PTR; -typedef unsigned __int32 ULONG_PTR; -#endif // __int3264 - - #define WM_SPLASHUPDATE WM_USER+1 #define WM_SPLASHRECONFIGURE WM_USER+2 @@ -436,16 +418,11 @@ SplashUnlock(Splash * splash) void SplashInitPlatform(Splash * splash) { - HMODULE user32 = LoadLibrary("user32.dll"); HDC hdc; int paletteMode; InitializeCriticalSection(&splash->lock); splash->isLayered = FALSE; - if (user32) { - UpdateLayeredWindow = (UpdateLayeredWindowT *) - GetProcAddress(user32, "UpdateLayeredWindow"); - } hdc = GetDC(NULL); paletteMode = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0; if (UpdateLayeredWindow && !paletteMode) { diff --git a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp index f0838dd5625..bee55638ddd 100644 --- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp @@ -184,7 +184,7 @@ void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter, pMgr = D3DPipelineManager::GetInstance(); RETURN_IF_NULL(pMgr); hMon = pMgr->pd3d9->GetAdapterMonitor(adapter); - gdiScreen = AwtWin32GraphicsDevice::GetScreenFromMHND((MHND)hMon); + gdiScreen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon); JNU_CallStaticMethodByName(env, NULL, "sun/java2d/pipe/hw/AccelDeviceEventNotifier", @@ -194,21 +194,21 @@ void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter, UINT D3DPipelineManager::GetAdapterOrdinalForScreen(jint gdiScreen) { - MHND mHnd = AwtWin32GraphicsDevice::GetMonitor(gdiScreen); - if (mHnd == (MHND)0) { + HMONITOR mHnd = AwtWin32GraphicsDevice::GetMonitor(gdiScreen); + if (mHnd == (HMONITOR)0) { return D3DADAPTER_DEFAULT; } return GetAdapterOrdinalByHmon((HMONITOR)mHnd); } // static -HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pMHNDs, UINT monNum) +HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monNum) { HRESULT res = S_OK; BOOL bResetD3D = FALSE, bFound; D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance(); - RETURN_STATUS_IF_NULL(pMHNDs, E_FAIL); + RETURN_STATUS_IF_NULL(pHMONITORs, E_FAIL); if (pMgr == NULL) { // NULL pMgr is valid when the pipeline is not enabled or if it hasn't // been created yet @@ -234,7 +234,7 @@ HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pMHNDs, UINT monNum) } bFound = FALSE; for (UINT mon = 0; mon < monNum; mon++) { - if (pMHNDs[mon] == hMon) { + if (pHMONITORs[mon] == hMon) { J2dTraceLn3(J2D_TRACE_VERBOSE, " adapter %d: found hmnd[%d]=0x%x", i, mon, hMon); bFound = TRUE; @@ -364,8 +364,8 @@ D3DPipelineManager::CheckOSVersion() HRESULT D3DPipelineManager::GDICheckForBadHardware() { - _DISPLAY_DEVICE dd; - dd.dwSize = sizeof(DISPLAY_DEVICE); + DISPLAY_DEVICE dd; + dd.cb = sizeof(DISPLAY_DEVICE); int failedDevices = 0; int attachedDevices = 0; @@ -379,9 +379,9 @@ D3DPipelineManager::GDICheckForBadHardware() // i<20 is to guard against buggy drivers while (EnumDisplayDevices(NULL, i, &dd, 0) && i < 20) { - if (dd.dwFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { + if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { attachedDevices++; - id = dd.deviceID; + id = dd.DeviceID; if (wcslen(id) > 21) { // get vendor ID wcsncpy(vendorId, id+8, 4); @@ -796,7 +796,7 @@ HWND D3DPipelineManager::CreateDefaultFocusWindow() ZeroMemory(&mi, sizeof(MONITORINFO)); mi.cbSize = sizeof(MONITORINFO); HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal); - if (hMon == 0 || !GetMonitorInfo(hMon, (PMONITOR_INFO)&mi)) { + if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) { J2dRlsTraceLn1(J2D_TRACE_ERROR, "D3DPPLM::CreateDefaultFocusWindow: "\ "error getting monitor info for adapter=%d", adapterOrdinal); diff --git a/jdk/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp b/jdk/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp index e33f1c4e1db..d9222ff8ba3 100644 --- a/jdk/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DRenderQueue.cpp @@ -23,8 +23,8 @@ * have any questions. */ +#include "D3DPipeline.h" #include -#include #include "sun_java2d_pipe_BufferedOpCodes.h" #include "jlong.h" diff --git a/jdk/src/windows/native/sun/java2d/d3d/D3DRenderer.cpp b/jdk/src/windows/native/sun/java2d/d3d/D3DRenderer.cpp index 8da2398ebcf..f9351da4c4e 100644 --- a/jdk/src/windows/native/sun/java2d/d3d/D3DRenderer.cpp +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DRenderer.cpp @@ -23,6 +23,8 @@ * have any questions. */ +#include "D3DPipeline.h" + #include "sun_java2d_d3d_D3DRenderer.h" #include "D3DContext.h" diff --git a/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp b/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp index 0cadb3bd677..9c865dc971b 100644 --- a/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp @@ -23,8 +23,7 @@ * have any questions. */ -#include -#include +#include "D3DPipeline.h" #include #include "D3DSurfaceData.h" #include "D3DPipelineManager.h" diff --git a/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp b/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp index 06d3c5f3fb5..736f39b5860 100644 --- a/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp +++ b/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include #include "gdefs.h" #include "Trace.h" diff --git a/jdk/src/windows/native/sun/java2d/windows/GDIRenderer.cpp b/jdk/src/windows/native/sun/java2d/windows/GDIRenderer.cpp index 5a06df00bcc..b2dc4a0e7af 100644 --- a/jdk/src/windows/native/sun/java2d/windows/GDIRenderer.cpp +++ b/jdk/src/windows/native/sun/java2d/windows/GDIRenderer.cpp @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include "sun_java2d_windows_GDIRenderer.h" #include "java_awt_geom_PathIterator.h" @@ -31,11 +32,8 @@ #include "awt_Pen.h" #include "awt_Brush.h" -#include "jni.h" - #include "GraphicsPrimitiveMgr.h" -#include #include /* for cos(), sin(), etc */ #define MAX_CLAMP_BND (1<<26) diff --git a/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp b/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp index b7032df7b3c..9acabfc66e9 100644 --- a/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp +++ b/jdk/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp @@ -246,7 +246,7 @@ static BOOL GDIWinSD_CheckMonitorArea(GDIWinSDOps *wsdo, } if( numScreens > 1 ) { - MONITOR_INFO *miInfo; + LPMONITORINFO miInfo; RECT rSect ={0,0,0,0}; RECT rView ={bounds->x1, bounds->y1, bounds->x2, bounds->y2}; retCode = FALSE; @@ -258,7 +258,7 @@ static BOOL GDIWinSD_CheckMonitorArea(GDIWinSDOps *wsdo, ::OffsetRect(&rView, (ptOrig.x), (ptOrig.y)); - ::IntersectRect(&rSect,&rView,&(miInfo->rMonitor)); + ::IntersectRect(&rSect,&rView,&(miInfo->rcMonitor)); if( FALSE == ::IsRectEmpty(&rSect) ) { if( TRUE == ::EqualRect(&rSect,&rView) ) { diff --git a/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp b/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp index b7040b8d803..01c0f6d8fc4 100644 --- a/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp +++ b/jdk/src/windows/native/sun/java2d/windows/WindowsFlags.cpp @@ -23,8 +23,6 @@ * have any questions. */ - -#include #include #include "Trace.h" #include "WindowsFlags.h" diff --git a/jdk/src/windows/native/sun/nio/ch/FileChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/FileChannelImpl.c index da96a109a7f..d1056b883b3 100644 --- a/jdk/src/windows/native/sun/nio/ch/FileChannelImpl.c +++ b/jdk/src/windows/native/sun/nio/ch/FileChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,10 +34,6 @@ static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */ - -/* false for 95/98/ME, true for NT/W2K */ -static jboolean onNT = JNI_FALSE; - /************************************************************** * static method to store field ID's in initializers * and retrieve the allocation granularity @@ -47,15 +43,9 @@ Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) { SYSTEM_INFO si; jint align; - OSVERSIONINFO ver; GetSystemInfo(&si); align = si.dwAllocationGranularity; chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) { - onNT = JNI_TRUE; - } return align; } @@ -146,56 +136,6 @@ Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this, return 0; } -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_truncate0(JNIEnv *env, jobject this, - jobject fdo, jlong size) -{ - DWORD lowPos = 0; - long highPos = 0; - BOOL result = 0; - HANDLE h = (HANDLE)(handleval(env, fdo)); - - lowPos = (DWORD)size; - highPos = (long)(size >> 32); - lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN); - if (lowPos == ((DWORD)-1)) { - if (GetLastError() != ERROR_SUCCESS) { - JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); - return IOS_THROWN; - } - } - result = SetEndOfFile(h); - if (result == 0) { - JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); - return IOS_THROWN; - } - return 0; -} - - -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_force0(JNIEnv *env, jobject this, - jobject fdo, jboolean md) -{ - int result = 0; - HANDLE h = (HANDLE)(handleval(env, fdo)); - - if (h != INVALID_HANDLE_VALUE) { - result = FlushFileBuffers(h); - if (result == 0) { - int error = GetLastError(); - if (error != ERROR_ACCESS_DENIED) { - JNU_ThrowIOExceptionWithLastError(env, "Force failed"); - return IOS_THROWN; - } - } - } else { - JNU_ThrowIOExceptionWithLastError(env, "Force failed"); - return IOS_THROWN; - } - return 0; -} - JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, jobject fdo, jlong offset) @@ -220,23 +160,6 @@ Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this, return (((jlong)highPos) << 32) | lowPos; } -JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileChannelImpl_size0(JNIEnv *env, jobject this, jobject fdo) -{ - DWORD sizeLow = 0; - DWORD sizeHigh = 0; - HANDLE h = (HANDLE)(handleval(env, fdo)); - - sizeLow = GetFileSize(h, &sizeHigh); - if (sizeLow == ((DWORD)-1)) { - if (GetLastError() != ERROR_SUCCESS) { - JNU_ThrowIOExceptionWithLastError(env, "Size failed"); - return IOS_THROWN; - } - } - return (((jlong)sizeHigh) << 32) | sizeLow; -} - JNIEXPORT void JNICALL Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) { @@ -257,99 +180,3 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, { return IOS_UNSUPPORTED; } - -JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileChannelImpl_lock0(JNIEnv *env, jobject this, jobject fdo, - jboolean block, jlong pos, jlong size, - jboolean shared) -{ - HANDLE h = (HANDLE)(handleval(env, fdo)); - DWORD lowPos = (DWORD)pos; - long highPos = (long)(pos >> 32); - DWORD lowNumBytes = (DWORD)size; - DWORD highNumBytes = (DWORD)(size >> 32); - jint result = 0; - if (onNT) { - DWORD flags = 0; - OVERLAPPED o; - o.hEvent = 0; - o.Offset = lowPos; - o.OffsetHigh = highPos; - if (block == JNI_FALSE) { - flags |= LOCKFILE_FAIL_IMMEDIATELY; - } - if (shared == JNI_FALSE) { - flags |= LOCKFILE_EXCLUSIVE_LOCK; - } - result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o); - if (result == 0) { - int error = GetLastError(); - if (error != ERROR_LOCK_VIOLATION) { - JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); - return sun_nio_ch_FileChannelImpl_NO_LOCK; - } - if (flags & LOCKFILE_FAIL_IMMEDIATELY) { - return sun_nio_ch_FileChannelImpl_NO_LOCK; - } - JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); - return sun_nio_ch_FileChannelImpl_NO_LOCK; - } - return sun_nio_ch_FileChannelImpl_LOCKED; - } else { - for(;;) { - if (size > 0x7fffffff) { - size = 0x7fffffff; - } - lowNumBytes = (DWORD)size; - highNumBytes = 0; - result = LockFile(h, lowPos, highPos, lowNumBytes, highNumBytes); - if (result != 0) { - if (shared == JNI_TRUE) { - return sun_nio_ch_FileChannelImpl_RET_EX_LOCK; - } else { - return sun_nio_ch_FileChannelImpl_LOCKED; - } - } else { - int error = GetLastError(); - if (error != ERROR_LOCK_VIOLATION) { - JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); - return sun_nio_ch_FileChannelImpl_NO_LOCK; - } - if (block == JNI_FALSE) { - return sun_nio_ch_FileChannelImpl_NO_LOCK; - } - } - Sleep(100); - } - } - return sun_nio_ch_FileChannelImpl_NO_LOCK; -} - -JNIEXPORT void JNICALL -Java_sun_nio_ch_FileChannelImpl_release0(JNIEnv *env, jobject this, - jobject fdo, jlong pos, jlong size) -{ - HANDLE h = (HANDLE)(handleval(env, fdo)); - DWORD lowPos = (DWORD)pos; - long highPos = (long)(pos >> 32); - DWORD lowNumBytes = (DWORD)size; - DWORD highNumBytes = (DWORD)(size >> 32); - jint result = 0; - if (onNT) { - OVERLAPPED o; - o.hEvent = 0; - o.Offset = lowPos; - o.OffsetHigh = highPos; - result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); - } else { - if (size > 0x7fffffff) { - size = 0x7fffffff; - } - lowNumBytes = (DWORD)size; - highNumBytes = 0; - result = UnlockFile(h, lowPos, highPos, lowNumBytes, highNumBytes); - } - if (result == 0) { - JNU_ThrowIOExceptionWithLastError(env, "Release failed"); - } -} diff --git a/jdk/src/windows/native/sun/nio/ch/FileDispatcher.c b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c similarity index 67% rename from jdk/src/windows/native/sun/nio/ch/FileDispatcher.c rename to jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c index a3c3985e7a0..a65ad90e24d 100644 --- a/jdk/src/windows/native/sun/nio/ch/FileDispatcher.c +++ b/jdk/src/windows/native/sun/nio/ch/FileDispatcherImpl.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,18 +28,18 @@ #include "jni_util.h" #include "jvm.h" #include "jlong.h" -#include "sun_nio_ch_FileDispatcher.h" +#include "sun_nio_ch_FileDispatcherImpl.h" #include #include "nio.h" #include "nio_util.h" /************************************************************** - * FileDispatcher.c + * FileDispatcherImpl.c */ JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { DWORD read = 0; @@ -70,7 +70,7 @@ Java_sun_nio_ch_FileDispatcher_read0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { DWORD read = 0; @@ -119,7 +119,7 @@ Java_sun_nio_ch_FileDispatcher_readv0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_pread0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { DWORD read = 0; @@ -182,7 +182,7 @@ Java_sun_nio_ch_FileDispatcher_pread0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { BOOL result = 0; @@ -205,7 +205,7 @@ Java_sun_nio_ch_FileDispatcher_write0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jlong JNICALL -Java_sun_nio_ch_FileDispatcher_writev0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len) { BOOL result = 0; @@ -244,7 +244,7 @@ Java_sun_nio_ch_FileDispatcher_writev0(JNIEnv *env, jclass clazz, jobject fdo, } JNIEXPORT jint JNICALL -Java_sun_nio_ch_FileDispatcher_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, +Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, jlong address, jint len, jlong offset) { BOOL result = 0; @@ -295,6 +295,130 @@ Java_sun_nio_ch_FileDispatcher_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, return convertReturnVal(env, (jint)written, JNI_FALSE); } +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, + jobject fdo, jboolean md) +{ + int result = 0; + HANDLE h = (HANDLE)(handleval(env, fdo)); + + if (h != INVALID_HANDLE_VALUE) { + result = FlushFileBuffers(h); + if (result == 0) { + int error = GetLastError(); + if (error != ERROR_ACCESS_DENIED) { + JNU_ThrowIOExceptionWithLastError(env, "Force failed"); + return IOS_THROWN; + } + } + } else { + JNU_ThrowIOExceptionWithLastError(env, "Force failed"); + return IOS_THROWN; + } + return 0; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, + jobject fdo, jlong size) +{ + DWORD lowPos = 0; + long highPos = 0; + BOOL result = 0; + HANDLE h = (HANDLE)(handleval(env, fdo)); + + lowPos = (DWORD)size; + highPos = (long)(size >> 32); + lowPos = SetFilePointer(h, lowPos, &highPos, FILE_BEGIN); + if (lowPos == ((DWORD)-1)) { + if (GetLastError() != ERROR_SUCCESS) { + JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); + return IOS_THROWN; + } + } + result = SetEndOfFile(h); + if (result == 0) { + JNU_ThrowIOExceptionWithLastError(env, "Truncation failed"); + return IOS_THROWN; + } + return 0; +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) +{ + DWORD sizeLow = 0; + DWORD sizeHigh = 0; + HANDLE h = (HANDLE)(handleval(env, fdo)); + + sizeLow = GetFileSize(h, &sizeHigh); + if (sizeLow == ((DWORD)-1)) { + if (GetLastError() != ERROR_SUCCESS) { + JNU_ThrowIOExceptionWithLastError(env, "Size failed"); + return IOS_THROWN; + } + } + return (((jlong)sizeHigh) << 32) | sizeLow; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, + jboolean block, jlong pos, jlong size, + jboolean shared) +{ + HANDLE h = (HANDLE)(handleval(env, fdo)); + DWORD lowPos = (DWORD)pos; + long highPos = (long)(pos >> 32); + DWORD lowNumBytes = (DWORD)size; + DWORD highNumBytes = (DWORD)(size >> 32); + BOOL result; + DWORD flags = 0; + OVERLAPPED o; + o.hEvent = 0; + o.Offset = lowPos; + o.OffsetHigh = highPos; + if (block == JNI_FALSE) { + flags |= LOCKFILE_FAIL_IMMEDIATELY; + } + if (shared == JNI_FALSE) { + flags |= LOCKFILE_EXCLUSIVE_LOCK; + } + result = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, &o); + if (result == 0) { + int error = GetLastError(); + if (error != ERROR_LOCK_VIOLATION) { + JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); + return sun_nio_ch_FileDispatcherImpl_NO_LOCK; + } + if (flags & LOCKFILE_FAIL_IMMEDIATELY) { + return sun_nio_ch_FileDispatcherImpl_NO_LOCK; + } + JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); + return sun_nio_ch_FileDispatcherImpl_NO_LOCK; + } + return sun_nio_ch_FileDispatcherImpl_LOCKED; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, + jobject fdo, jlong pos, jlong size) +{ + HANDLE h = (HANDLE)(handleval(env, fdo)); + DWORD lowPos = (DWORD)pos; + long highPos = (long)(pos >> 32); + DWORD lowNumBytes = (DWORD)size; + DWORD highNumBytes = (DWORD)(size >> 32); + jint result = 0; + OVERLAPPED o; + o.hEvent = 0; + o.Offset = lowPos; + o.OffsetHigh = highPos; + result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); + if (result == 0) { + JNU_ThrowIOExceptionWithLastError(env, "Release failed"); + } +} + static void closeFile(JNIEnv *env, jlong fd) { HANDLE h = (HANDLE)fd; if (h != INVALID_HANDLE_VALUE) { @@ -305,14 +429,14 @@ static void closeFile(JNIEnv *env, jlong fd) { } JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_close0(JNIEnv *env, jclass clazz, jobject fdo) +Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) { jlong fd = handleval(env, fdo); closeFile(env, fd); } JNIEXPORT void JNICALL -Java_sun_nio_ch_FileDispatcher_closeByHandle(JNIEnv *env, jclass clazz, +Java_sun_nio_ch_FileDispatcherImpl_closeByHandle(JNIEnv *env, jclass clazz, jlong fd) { closeFile(env, fd); diff --git a/jdk/src/windows/native/sun/nio/ch/Iocp.c b/jdk/src/windows/native/sun/nio/ch/Iocp.c new file mode 100644 index 00000000000..9568189ee6b --- /dev/null +++ b/jdk/src/windows/native/sun/nio/ch/Iocp.c @@ -0,0 +1,147 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "nio.h" +#include "nio_util.h" + +#include "sun_nio_ch_Iocp.h" + + +static jfieldID completionStatus_error; +static jfieldID completionStatus_bytesTransferred; +static jfieldID completionStatus_completionKey; +static jfieldID completionStatus_overlapped; + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_Iocp_initIDs(JNIEnv* env, jclass this) +{ + jclass clazz; + + clazz = (*env)->FindClass(env, "sun/nio/ch/Iocp$CompletionStatus"); + if (clazz == NULL) { + return; + } + completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I"); + if (completionStatus_error == NULL) return; + completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); + if (completionStatus_bytesTransferred == NULL) return; + completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I"); + if (completionStatus_completionKey == NULL) return; + completionStatus_overlapped = (*env)->GetFieldID(env, clazz, "overlapped", "J"); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this, + jlong handle, jlong existingPort, jint completionKey, jint concurrency) +{ + HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(handle), + (HANDLE)jlong_to_ptr(existingPort), + (DWORD)completionKey, + (DWORD)concurrency); + if (port == NULL) { + JNU_ThrowIOExceptionWithLastError(env, "CreateIoCompletionPort failed"); + } + return ptr_to_jlong(port); +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_Iocp_close0(JNIEnv* env, jclass this, + jlong handle) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + CloseHandle(h); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_Iocp_getQueuedCompletionStatus(JNIEnv* env, jclass this, + jlong completionPort, jobject obj) +{ + DWORD bytesTransferred; + DWORD completionKey; + OVERLAPPED *lpOverlapped; + BOOL res; + + res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort), + &bytesTransferred, + &completionKey, + &lpOverlapped, + INFINITE); + if (res == 0 && lpOverlapped == NULL) { + JNU_ThrowIOExceptionWithLastError(env, "GetQueuedCompletionStatus failed"); + } else { + DWORD ioResult = (res == 0) ? GetLastError() : 0; + (*env)->SetIntField(env, obj, completionStatus_error, ioResult); + (*env)->SetIntField(env, obj, completionStatus_bytesTransferred, + (jint)bytesTransferred); + (*env)->SetIntField(env, obj, completionStatus_completionKey, + (jint)completionKey); + (*env)->SetLongField(env, obj, completionStatus_overlapped, + ptr_to_jlong(lpOverlapped)); + + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_Iocp_postQueuedCompletionStatus(JNIEnv* env, jclass this, + jlong completionPort, jint completionKey) +{ + BOOL res; + + res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort), + (DWORD)0, + (DWORD)completionKey, + NULL); + if (res == 0) { + JNU_ThrowIOExceptionWithLastError(env, "PostQueuedCompletionStatus"); + } +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_ch_Iocp_getErrorMessage(JNIEnv* env, jclass this, jint errorCode) +{ + WCHAR message[255]; + + DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + (DWORD)errorCode, + 0, + &message[0], + 255, + NULL); + + + if (len == 0) { + return NULL; + } else { + return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message)); + } +} diff --git a/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c new file mode 100644 index 00000000000..d8346ba3e7a --- /dev/null +++ b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousFileChannelImpl.c @@ -0,0 +1,132 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "nio.h" +#include "nio_util.h" + +#include "sun_nio_ch_WindowsAsynchronousFileChannelImpl.h" + + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_readFile(JNIEnv* env, jclass this, + jlong handle, jlong address, jint len, jlong offset, jlong ov) +{ + BOOL res; + DWORD nread = 0; + + OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov); + lpOverlapped->Offset = (DWORD)offset; + lpOverlapped->OffsetHigh = (DWORD)((long)(offset >> 32)); + lpOverlapped->hEvent = NULL; + + res = ReadFile((HANDLE) jlong_to_ptr(handle), + (LPVOID) jlong_to_ptr(address), + (DWORD)len, + &nread, + lpOverlapped); + + if (res == 0) { + int error = GetLastError(); + if (error == ERROR_IO_PENDING) + return IOS_UNAVAILABLE; + if (error == ERROR_HANDLE_EOF) + return IOS_EOF; + JNU_ThrowIOExceptionWithLastError(env, "ReadFile failed"); + return IOS_THROWN; + } + + return (jint)nread; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_writeFile(JNIEnv* env, jclass this, + jlong handle, jlong address, jint len, jlong offset, jlong ov) +{ + BOOL res; + DWORD nwritten = 0; + + OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov); + lpOverlapped->Offset = (DWORD)offset; + lpOverlapped->OffsetHigh = (DWORD)((long)(offset >> 32)); + lpOverlapped->hEvent = NULL; + + res = WriteFile((HANDLE)jlong_to_ptr(handle), + (LPVOID) jlong_to_ptr(address), + (DWORD)len, + &nwritten, + lpOverlapped); + + if (res == 0) { + int error = GetLastError(); + if (error == ERROR_IO_PENDING) { + return IOS_UNAVAILABLE; + } + JNU_ThrowIOExceptionWithLastError(env, "WriteFile failed"); + return IOS_THROWN; + } + return (jint)nwritten; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_lockFile(JNIEnv *env, jobject this, jlong handle, + jlong pos, jlong size, jboolean shared, jlong ov) +{ + BOOL res; + HANDLE h = jlong_to_ptr(handle); + DWORD lowPos = (DWORD)pos; + long highPos = (long)(pos >> 32); + DWORD lowNumBytes = (DWORD)size; + DWORD highNumBytes = (DWORD)(size >> 32); + DWORD flags = (shared == JNI_TRUE) ? 0 : LOCKFILE_EXCLUSIVE_LOCK; + OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov); + + lpOverlapped->Offset = lowPos; + lpOverlapped->OffsetHigh = highPos; + lpOverlapped->hEvent = NULL; + + res = LockFileEx(h, flags, 0, lowNumBytes, highNumBytes, lpOverlapped); + if (res == 0) { + int error = GetLastError(); + if (error == ERROR_IO_PENDING) { + return IOS_UNAVAILABLE; + } + JNU_ThrowIOExceptionWithLastError(env, "WriteFile failed"); + return IOS_THROWN; + } + return 0; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousFileChannelImpl_close0(JNIEnv* env, jclass this, + jlong handle) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + CloseHandle(h); +} diff --git a/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c new file mode 100644 index 00000000000..ba706a4d86b --- /dev/null +++ b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.c @@ -0,0 +1,142 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "nio.h" +#include "nio_util.h" +#include "net_util.h" + +#include "sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl.h" + + +#ifndef WSAID_ACCEPTEX +#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} +#endif + +#ifndef SO_UPDATE_ACCEPT_CONTEXT +#define SO_UPDATE_ACCEPT_CONTEXT 0x700B +#endif + + +typedef BOOL (*AcceptEx_t) +( + SOCKET sListenSocket, + SOCKET sAcceptSocket, + PVOID lpOutputBuffer, + DWORD dwReceiveDataLength, + DWORD dwLocalAddressLength, + DWORD dwRemoteAddressLength, + LPDWORD lpdwBytesReceived, + LPOVERLAPPED lpOverlapped +); + + +static AcceptEx_t AcceptEx_func; + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env, jclass this) { + GUID GuidAcceptEx = WSAID_ACCEPTEX; + SOCKET s; + int rv; + DWORD dwBytes; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + JNU_ThrowIOExceptionWithLastError(env, "socket failed"); + return; + } + rv = WSAIoctl(s, + SIO_GET_EXTENSION_FUNCTION_POINTER, + (LPVOID)&GuidAcceptEx, + sizeof(GuidAcceptEx), + &AcceptEx_func, + sizeof(AcceptEx_func), + &dwBytes, + NULL, + NULL); + if (rv != 0) + JNU_ThrowIOExceptionWithLastError(env, "WSAIoctl failed"); + closesocket(s); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env, jclass this, + jlong listenSocket, jlong acceptSocket, jlong ov, jlong buf) +{ + BOOL res; + SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket); + SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket); + PVOID outputBuffer = (PVOID)jlong_to_ptr(buf); + + DWORD nread = 0; + OVERLAPPED* lpOverlapped = (OVERLAPPED*)jlong_to_ptr(ov); + ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED)); + + res = (*AcceptEx_func)(s1, + s2, + outputBuffer, + 0, + sizeof(SOCKETADDRESS)+16, + sizeof(SOCKETADDRESS)+16, + &nread, + lpOverlapped); + if (res == 0) { + int error = WSAGetLastError(); + if (error == ERROR_IO_PENDING) { + return IOS_UNAVAILABLE; + } + JNU_ThrowIOExceptionWithLastError(env, "AcceptEx failed"); + return IOS_THROWN; + } + + return 0; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_updateAcceptContext(JNIEnv* env, jclass this, + jlong listenSocket, jlong acceptSocket) +{ + SOCKET s1 = (SOCKET)jlong_to_ptr(listenSocket); + SOCKET s2 = (SOCKET)jlong_to_ptr(acceptSocket); + + setsockopt(s2, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&s1, sizeof(s1)); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousServerSocketChannelImpl_closesocket0(JNIEnv* env, jclass this, + jlong socket) +{ + SOCKET s = (SOCKET)jlong_to_ptr(socket); + + if (closesocket(s) == SOCKET_ERROR) + JNU_ThrowIOExceptionWithLastError(env, "closesocket failed"); +} diff --git a/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c new file mode 100644 index 00000000000..97c49f60a71 --- /dev/null +++ b/jdk/src/windows/native/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.c @@ -0,0 +1,222 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "nio.h" +#include "nio_util.h" +#include "net_util.h" + +#include "sun_nio_ch_WindowsAsynchronousSocketChannelImpl.h" + +#ifndef WSAID_CONNECTEX +#define WSAID_CONNECTEX {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}} +#endif + +#ifndef SO_UPDATE_CONNECT_CONTEXT +#define SO_UPDATE_CONNECT_CONTEXT 0x7010 +#endif + +typedef BOOL (*ConnectEx_t) +( + SOCKET s, + const struct sockaddr* name, + int namelen, + PVOID lpSendBuffer, + DWORD dwSendDataLength, + LPDWORD lpdwBytesSent, + LPOVERLAPPED lpOverlapped +); + +static ConnectEx_t ConnectEx_func; + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_initIDs(JNIEnv* env, jclass this) { + GUID GuidConnectEx = WSAID_CONNECTEX; + SOCKET s; + int rv; + DWORD dwBytes; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + JNU_ThrowIOExceptionWithLastError(env, "socket failed"); + return; + } + rv = WSAIoctl(s, + SIO_GET_EXTENSION_FUNCTION_POINTER, + (LPVOID)&GuidConnectEx, + sizeof(GuidConnectEx), + &ConnectEx_func, + sizeof(ConnectEx_func), + &dwBytes, + NULL, + NULL); + if (rv != 0) + JNU_ThrowIOExceptionWithLastError(env, "WSAIoctl failed"); + closesocket(s); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_connect0(JNIEnv* env, jclass this, + jlong socket, jboolean preferIPv6, jobject iao, jint port, jlong ov) +{ + SOCKET s = (SOCKET) jlong_to_ptr(socket); + OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov); + + SOCKETADDRESS sa; + int sa_len; + BOOL res; + + if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) { + return IOS_THROWN; + } + + ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED)); + + res = (*ConnectEx_func)(s, + (struct sockaddr *)&sa, + sa_len, + NULL, + 0, + NULL, + lpOverlapped); + if (res == 0) { + int error = GetLastError(); + if (error == ERROR_IO_PENDING) { + return IOS_UNAVAILABLE; + } + JNU_ThrowIOExceptionWithLastError(env, "ConnectEx failed"); + return IOS_THROWN; + } + return 0; +} + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_updateConnectContext(JNIEnv* env, jclass this, + jlong socket) +{ + SOCKET s = (SOCKET)jlong_to_ptr(socket); + setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_shutdown0(JNIEnv *env, jclass cl, + jlong socket, jint how) +{ + SOCKET s =(SOCKET) jlong_to_ptr(socket); + if (shutdown(s, how) == SOCKET_ERROR) { + JNU_ThrowIOExceptionWithLastError(env, "shutdown failed"); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_closesocket0(JNIEnv* env, jclass this, + jlong socket) +{ + SOCKET s = (SOCKET)jlong_to_ptr(socket); + if (closesocket(s) == SOCKET_ERROR) + JNU_ThrowIOExceptionWithLastError(env, "closesocket failed"); +} + + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_read0(JNIEnv* env, jclass this, + jlong socket, jint count, jlong address, jlong ov) +{ + SOCKET s = (SOCKET) jlong_to_ptr(socket); + WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address); + OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov); + BOOL res; + DWORD nread = 0; + DWORD flags = 0; + + ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED)); + res = WSARecv(s, + lpWsaBuf, + (DWORD)count, + &nread, + &flags, + lpOverlapped, + NULL); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + if (error == WSA_IO_PENDING) { + return IOS_UNAVAILABLE; + } + if (error == WSAESHUTDOWN) { + return 0; // input shutdown + } + JNU_ThrowIOExceptionWithLastError(env, "WSARecv failed"); + return IOS_THROWN; + } + if (nread == 0) { + // Handle graceful close or bytes not yet available cases + // via completion port notification. + return IOS_UNAVAILABLE; + } + return (jint)nread; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_write0(JNIEnv* env, jclass this, + jlong socket, jint count, jlong address, jlong ov) +{ + SOCKET s = (SOCKET) jlong_to_ptr(socket); + WSABUF* lpWsaBuf = (WSABUF*) jlong_to_ptr(address); + OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov); + BOOL res; + DWORD nwritten; + + ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED)); + res = WSASend(s, + lpWsaBuf, + (DWORD)count, + &nwritten, + 0, + lpOverlapped, + NULL); + + if (res == SOCKET_ERROR) { + int error = WSAGetLastError(); + if (error == WSA_IO_PENDING) { + return IOS_UNAVAILABLE; + } + if (error == WSAESHUTDOWN) { + return IOS_EOF; // output shutdown + } + JNU_ThrowIOExceptionWithLastError(env, "WSASend failed"); + return IOS_THROWN; + } + return (jint)nwritten; +} diff --git a/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c b/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c new file mode 100644 index 00000000000..14c7f6af948 --- /dev/null +++ b/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c @@ -0,0 +1,62 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" + +#include "sun_nio_fs_RegistryFileTypeDetector.h" + + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_RegistryFileTypeDetector_queryStringValue(JNIEnv* env, jclass this, + jlong keyAddress, jlong nameAddress) +{ + LPCWSTR lpSubKey= (LPCWSTR)jlong_to_ptr(keyAddress); + LPWSTR lpValueName = (LPWSTR)jlong_to_ptr(nameAddress); + LONG res; + HKEY hKey; + jstring result = NULL; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, lpSubKey, 0, KEY_READ, &hKey); + if (res == ERROR_SUCCESS) { + DWORD type; + BYTE data[255]; + DWORD size = sizeof(data); + + res = RegQueryValueExW(hKey, lpValueName, NULL, &type, (LPBYTE)&data, &size); + if (res == ERROR_SUCCESS) { + if (type == REG_SZ) { + jsize len = wcslen((WCHAR*)data); + result = (*env)->NewString(env, (const jchar*)&data, len); + } + } + + RegCloseKey(hKey); + } + return result; +} diff --git a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c new file mode 100644 index 00000000000..45a3646275c --- /dev/null +++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c @@ -0,0 +1,1345 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" + +#include "sun_nio_fs_WindowsNativeDispatcher.h" + +/** + * jfieldIDs + */ +static jfieldID findFirst_handle; +static jfieldID findFirst_name; + +static jfieldID findStream_handle; +static jfieldID findStream_name; + +static jfieldID volumeInfo_fsName; +static jfieldID volumeInfo_volName; +static jfieldID volumeInfo_volSN; +static jfieldID volumeInfo_flags; + +static jfieldID diskSpace_bytesAvailable; +static jfieldID diskSpace_totalBytes; +static jfieldID diskSpace_totalFree; + +static jfieldID account_domain; +static jfieldID account_name; +static jfieldID account_use; + +static jfieldID aclInfo_aceCount; + +static jfieldID completionStatus_error; +static jfieldID completionStatus_bytesTransferred; +static jfieldID completionStatus_completionKey; + +static jfieldID backupResult_bytesTransferred; +static jfieldID backupResult_context; + + +/** + * Win32 APIs not defined in Visual Studio 2003 header files + */ + +typedef enum { + FindStreamInfoStandard +} MY_STREAM_INFO_LEVELS; + +typedef struct _MY_WIN32_FIND_STREAM_DATA { + LARGE_INTEGER StreamSize; + WCHAR cStreamName[MAX_PATH + 36]; +} MY_WIN32_FIND_STREAM_DATA; + +typedef HANDLE (WINAPI* FindFirstStream_Proc)(LPCWSTR, MY_STREAM_INFO_LEVELS, LPVOID, DWORD); +typedef BOOL (WINAPI* FindNextStream_Proc)(HANDLE, LPVOID); + +typedef BOOLEAN (WINAPI* CreateSymbolicLinkProc) (LPCWSTR, LPCWSTR, DWORD); +typedef BOOL (WINAPI* CreateHardLinkProc) (LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); +typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD); + +typedef BOOL (WINAPI* ConvertSidToStringSidProc) (PSID, LPWSTR*); +typedef BOOL (WINAPI* ConvertStringSidToSidProc) (LPWSTR, PSID*); +typedef DWORD (WINAPI* GetLengthSidProc) (PSID); + +static FindFirstStream_Proc FindFirstStream_func; +static FindNextStream_Proc FindNextStream_func; + +static CreateSymbolicLinkProc CreateSymbolicLink_func; +static CreateHardLinkProc CreateHardLink_func; +static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func; + +static ConvertSidToStringSidProc ConvertSidToStringSid_func; +static ConvertStringSidToSidProc ConvertStringSidToSid_func; +static GetLengthSidProc GetLengthSid_func; + +static void throwWindowsException(JNIEnv* env, DWORD lastError) { + jobject x = JNU_NewObjectByName(env, "sun/nio/fs/WindowsException", + "(I)V", lastError); + if (x != NULL) { + (*env)->Throw(env, x); + } +} + +/** + * Initializes jfieldIDs and get address of Win32 calls that are located + * at runtime. + */ +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this) +{ + jclass clazz; + HMODULE h; + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstFile"); + if (clazz == NULL) { + return; + } + findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); + findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream"); + if (clazz == NULL) { + return; + } + findStream_handle = (*env)->GetFieldID(env, clazz, "handle", "J"); + findStream_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$VolumeInformation"); + if (clazz == NULL) { + return; + } + volumeInfo_fsName = (*env)->GetFieldID(env, clazz, "fileSystemName", "Ljava/lang/String;"); + volumeInfo_volName = (*env)->GetFieldID(env, clazz, "volumeName", "Ljava/lang/String;"); + volumeInfo_volSN = (*env)->GetFieldID(env, clazz, "volumeSerialNumber", "I"); + volumeInfo_flags = (*env)->GetFieldID(env, clazz, "flags", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$DiskFreeSpace"); + if (clazz == NULL) { + return; + } + diskSpace_bytesAvailable = (*env)->GetFieldID(env, clazz, "freeBytesAvailable", "J"); + diskSpace_totalBytes = (*env)->GetFieldID(env, clazz, "totalNumberOfBytes", "J"); + diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account"); + if (clazz == NULL) { + return; + } + account_domain = (*env)->GetFieldID(env, clazz, "domain", "Ljava/lang/String;"); + account_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); + account_use = (*env)->GetFieldID(env, clazz, "use", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$AclInformation"); + if (clazz == NULL) { + return; + } + aclInfo_aceCount = (*env)->GetFieldID(env, clazz, "aceCount", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$CompletionStatus"); + if (clazz == NULL) { + return; + } + completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I"); + completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); + completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I"); + + clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult"); + if (clazz == NULL) { + return; + } + backupResult_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I"); + backupResult_context = (*env)->GetFieldID(env, clazz, "context", "J"); + + + h = LoadLibrary("kernel32"); + if (h != INVALID_HANDLE_VALUE) { + FindFirstStream_func = + (FindFirstStream_Proc)GetProcAddress(h, "FindFirstStreamW"); + FindNextStream_func = + (FindNextStream_Proc)GetProcAddress(h, "FindNextStreamW"); + CreateSymbolicLink_func = + (CreateSymbolicLinkProc)GetProcAddress(h, "CreateSymbolicLinkW"); + CreateHardLink_func = + (CreateHardLinkProc)GetProcAddress(h, "CreateHardLinkW"); + GetFinalPathNameByHandle_func = + (GetFinalPathNameByHandleProc)GetProcAddress(h, "GetFinalPathNameByHandleW"); + FreeLibrary(h); + } + + h = LoadLibrary("advapi32"); + if (h != INVALID_HANDLE_VALUE) { + ConvertSidToStringSid_func = + (ConvertSidToStringSidProc)GetProcAddress(h, "ConvertSidToStringSidW"); + ConvertStringSidToSid_func = + (ConvertStringSidToSidProc)GetProcAddress(h, "ConvertStringSidToSidW"); + GetLengthSid_func = + (GetLengthSidProc)GetProcAddress(h, "GetLengthSid"); + FreeLibrary(h); + } + +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) { + WCHAR message[255]; + + DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + (DWORD)errorCode, + 0, + &message[0], + 255, + NULL); + + + if (len == 0) { + return NULL; + } else { + return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message)); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_LocalFree(JNIEnv* env, jclass this, jlong address) +{ + HLOCAL hMem = (HLOCAL)jlong_to_ptr(address); + LocalFree(hMem); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateFile0(JNIEnv* env, jclass this, + jlong address, jint dwDesiredAccess, jint dwShareMode, jlong sdAddress, + jint dwCreationDisposition, jint dwFlagsAndAttributes) +{ + HANDLE handle; + LPCWSTR lpFileName = jlong_to_ptr(address); + + SECURITY_ATTRIBUTES securityAttributes; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress); + + + if (lpSecurityDescriptor == NULL) { + lpSecurityAttributes = NULL; + } else { + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor; + securityAttributes.bInheritHandle = FALSE; + lpSecurityAttributes = &securityAttributes; + } + + handle = CreateFileW(lpFileName, + (DWORD)dwDesiredAccess, + (DWORD)dwShareMode, + lpSecurityAttributes, + (DWORD)dwCreationDisposition, + (DWORD)dwFlagsAndAttributes, + NULL); + if (handle == INVALID_HANDLE_VALUE) { + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(handle); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlSetSparse(JNIEnv* env, jclass this, + jlong handle) +{ + DWORD bytesReturned; + HANDLE h = (HANDLE)jlong_to_ptr(handle); + if (DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesReturned, NULL) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_DeviceIoControlGetReparsePoint(JNIEnv* env, jclass this, + jlong handle, jlong bufferAddress, jint bufferSize) +{ + DWORD bytesReturned; + HANDLE h = (HANDLE)jlong_to_ptr(handle); + LPVOID outBuffer = (LPVOID)jlong_to_ptr(bufferAddress); + + if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, outBuffer, (DWORD)bufferSize, + &bytesReturned, NULL) == 0) + { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_DeleteFile0(JNIEnv* env, jclass this, jlong address) +{ + LPCWSTR lpFileName = jlong_to_ptr(address); + if (DeleteFileW(lpFileName) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateDirectory0(JNIEnv* env, jclass this, + jlong address, jlong sdAddress) +{ + LPCWSTR lpFileName = jlong_to_ptr(address); + + SECURITY_ATTRIBUTES securityAttributes; + LPSECURITY_ATTRIBUTES lpSecurityAttributes; + PSECURITY_DESCRIPTOR lpSecurityDescriptor = jlong_to_ptr(sdAddress); + + + if (lpSecurityDescriptor == NULL) { + lpSecurityAttributes = NULL; + } else { + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = lpSecurityDescriptor; + securityAttributes.bInheritHandle = FALSE; + lpSecurityAttributes = &securityAttributes; + } + + if (CreateDirectoryW(lpFileName, lpSecurityAttributes) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_RemoveDirectory0(JNIEnv* env, jclass this, jlong address) +{ + LPCWSTR lpFileName = jlong_to_ptr(address); + if (RemoveDirectoryW(lpFileName) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CloseHandle(JNIEnv* env, jclass this, + jlong handle) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + CloseHandle(h); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this, + jlong address, jobject obj) +{ + WIN32_FIND_DATAW data; + LPCWSTR lpFileName = jlong_to_ptr(address); + + HANDLE handle = FindFirstFileW(lpFileName, &data); + if (handle != INVALID_HANDLE_VALUE) { + jstring name = (*env)->NewString(env, data.cFileName, wcslen(data.cFileName)); + if (name == NULL) + return; + (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle)); + (*env)->SetObjectField(env, obj, findFirst_name, name); + } else { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this, + jlong pathAddress, jlong dataAddress) +{ + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress); + + HANDLE handle = FindFirstFileW(lpFileName, data); + if (handle == INVALID_HANDLE_VALUE) { + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(handle); +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this, + jlong handle, jlong dataAddress) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress); + + if (FindNextFileW(h, data) != 0) { + return (*env)->NewString(env, data->cFileName, wcslen(data->cFileName)); + } else { + if (GetLastError() != ERROR_NO_MORE_FILES) + throwWindowsException(env, GetLastError()); + return NULL; + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass this, + jlong address, jobject obj) +{ + MY_WIN32_FIND_STREAM_DATA data; + LPCWSTR lpFileName = jlong_to_ptr(address); + HANDLE handle; + + if (FindFirstStream_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return; + } + + handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0); + if (handle != INVALID_HANDLE_VALUE) { + jstring name = (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName)); + if (name == NULL) + return; + (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle)); + (*env)->SetObjectField(env, obj, findStream_name, name); + } else { + if (GetLastError() == ERROR_HANDLE_EOF) { + (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle)); + } else { + throwWindowsException(env, GetLastError()); + } + } + +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this, + jlong handle) +{ + MY_WIN32_FIND_STREAM_DATA data; + HANDLE h = (HANDLE)jlong_to_ptr(handle); + + if (FindNextStream_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return NULL; + } + + if ((*FindNextStream_func)(h, &data) != 0) { + return (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName)); + } else { + if (GetLastError() != ERROR_HANDLE_EOF) + throwWindowsException(env, GetLastError()); + return NULL; + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_FindClose(JNIEnv* env, jclass this, + jlong handle) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + if (FindClose(h) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFileInformationByHandle(JNIEnv* env, jclass this, + jlong handle, jlong address) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + BY_HANDLE_FILE_INFORMATION* info = + (BY_HANDLE_FILE_INFORMATION*)jlong_to_ptr(address); + if (GetFileInformationByHandle(h, info) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CopyFileEx0(JNIEnv* env, jclass this, + jlong existingAddress, jlong newAddress, jint flags, jlong cancelAddress) +{ + LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress); + LPCWSTR lpNewFileName = jlong_to_ptr(newAddress); + LPBOOL cancel = (LPBOOL)jlong_to_ptr(cancelAddress); + if (CopyFileExW(lpExistingFileName, lpNewFileName, NULL, NULL, cancel, + (DWORD)flags) == 0) + { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_MoveFileEx0(JNIEnv* env, jclass this, + jlong existingAddress, jlong newAddress, jint flags) +{ + LPCWSTR lpExistingFileName = jlong_to_ptr(existingAddress); + LPCWSTR lpNewFileName = jlong_to_ptr(newAddress); + if (MoveFileExW(lpExistingFileName, lpNewFileName, (DWORD)flags) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetLogicalDrives(JNIEnv* env, jclass this) +{ + DWORD res = GetLogicalDrives(); + if (res == 0) { + throwWindowsException(env, GetLastError()); + } + return (jint)res; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributes0(JNIEnv* env, jclass this, + jlong address) +{ + LPCWSTR lpFileName = jlong_to_ptr(address); + DWORD value = GetFileAttributesW(lpFileName); + + if (value == INVALID_FILE_ATTRIBUTES) { + throwWindowsException(env, GetLastError()); + } + return (jint)value; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetFileAttributes0(JNIEnv* env, jclass this, + jlong address, jint value) +{ + LPCWSTR lpFileName = jlong_to_ptr(address); + if (SetFileAttributesW(lpFileName, (DWORD)value) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFileAttributesEx0(JNIEnv* env, jclass this, + jlong pathAddress, jlong dataAddress) +{ + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + WIN32_FILE_ATTRIBUTE_DATA* data = (WIN32_FILE_ATTRIBUTE_DATA*)jlong_to_ptr(dataAddress); + + BOOL res = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, (LPVOID)data); + if (res == 0) + throwWindowsException(env, GetLastError()); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetFileTime(JNIEnv* env, jclass this, + jlong handle, jlong createTime, jlong lastAccessTime, jlong lastWriteTime) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + + if (SetFileTime(h, + (createTime == (jlong)0) ? NULL : (CONST FILETIME *)&createTime, + (lastAccessTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastAccessTime, + (lastWriteTime == (jlong)0) ? NULL : (CONST FILETIME *)&lastWriteTime) == 0) + { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetEndOfFile(JNIEnv* env, jclass this, + jlong handle) +{ + HANDLE h = (HANDLE)jlong_to_ptr(handle); + + if (SetEndOfFile(h) == 0) + throwWindowsException(env, GetLastError()); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumeInformation0(JNIEnv* env, jclass this, + jlong address, jobject obj) +{ + WCHAR volumeName[MAX_PATH+1]; + DWORD volumeSerialNumber; + DWORD maxComponentLength; + DWORD flags; + WCHAR fileSystemName[MAX_PATH+1]; + LPCWSTR lpFileName = jlong_to_ptr(address); + jstring str; + + BOOL res = GetVolumeInformationW(lpFileName, + &volumeName[0], + MAX_PATH+1, + &volumeSerialNumber, + &maxComponentLength, + &flags, + &fileSystemName[0], + MAX_PATH+1); + if (res == 0) { + throwWindowsException(env, GetLastError()); + return; + } + + str = (*env)->NewString(env, (const jchar *)fileSystemName, (jsize)wcslen(fileSystemName)); + if (str == NULL) return; + (*env)->SetObjectField(env, obj, volumeInfo_fsName, str); + + str = (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName)); + if (str == NULL) return; + (*env)->SetObjectField(env, obj, volumeInfo_volName, str); + + (*env)->SetIntField(env, obj, volumeInfo_volSN, (jint)volumeSerialNumber); + (*env)->SetIntField(env, obj, volumeInfo_flags, (jint)flags); +} + + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0(JNIEnv* env, jclass this, jlong address) { + LPCWSTR lpRootPathName = jlong_to_ptr(address); + return (jint)GetDriveTypeW(lpRootPathName); +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpaceEx0(JNIEnv* env, jclass this, + jlong address, jobject obj) +{ + ULARGE_INTEGER freeBytesAvailable; + ULARGE_INTEGER totalNumberOfBytes; + ULARGE_INTEGER totalNumberOfFreeBytes; + LPCWSTR lpDirName = jlong_to_ptr(address); + + + BOOL res = GetDiskFreeSpaceExW(lpDirName, + &freeBytesAvailable, + &totalNumberOfBytes, + &totalNumberOfFreeBytes); + if (res == 0) { + throwWindowsException(env, GetLastError()); + return; + } + + (*env)->SetLongField(env, obj, diskSpace_bytesAvailable, + long_to_jlong(freeBytesAvailable.QuadPart)); + (*env)->SetLongField(env, obj, diskSpace_totalBytes, + long_to_jlong(totalNumberOfBytes.QuadPart)); + (*env)->SetLongField(env, obj, diskSpace_totalFree, + long_to_jlong(totalNumberOfFreeBytes.QuadPart)); +} + + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this, + jlong address) +{ + WCHAR volumeName[MAX_PATH+1]; + LPCWSTR lpFileName = jlong_to_ptr(address); + + + BOOL res = GetVolumePathNameW(lpFileName, + &volumeName[0], + MAX_PATH+1); + if (res == 0) { + throwWindowsException(env, GetLastError()); + return NULL; + } else { + return (*env)->NewString(env, (const jchar *)volumeName, (jsize)wcslen(volumeName)); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_InitializeSecurityDescriptor(JNIEnv* env, jclass this, + jlong address) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = + (PSECURITY_DESCRIPTOR)jlong_to_ptr(address); + + if (InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_InitializeAcl(JNIEnv* env, jclass this, + jlong address, jint size) +{ + PACL pAcl = (PACL)jlong_to_ptr(address); + + if (InitializeAcl(pAcl, (DWORD)size, ACL_REVISION) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetFileSecurity0(JNIEnv* env, jclass this, + jlong pathAddress, jint requestedInformation, jlong descAddress) +{ + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress); + DWORD lengthNeeded = 0; + + BOOL res = SetFileSecurityW(lpFileName, + (SECURITY_INFORMATION)requestedInformation, + pSecurityDescriptor); + + if (res == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFileSecurity0(JNIEnv* env, jclass this, + jlong pathAddress, jint requestedInformation, jlong descAddress, jint nLength) +{ + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress); + DWORD lengthNeeded = 0; + + BOOL res = GetFileSecurityW(lpFileName, + (SECURITY_INFORMATION)requestedInformation, + pSecurityDescriptor, + (DWORD)nLength, + &lengthNeeded); + + if (res == 0) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + return (jint)lengthNeeded; + } else { + throwWindowsException(env, GetLastError()); + return 0; + } + } else { + return (jint)nLength; + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorOwner(JNIEnv* env, + jclass this, jlong address) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address); + PSID pOwner; + BOOL bOwnerDefaulted; + + + if (GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwner, &bOwnerDefaulted) == 0) { + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(pOwner); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorOwner(JNIEnv* env, + jclass this, jlong descAddress, jlong ownerAddress) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(descAddress); + PSID pOwner = jlong_to_ptr(ownerAddress); + + if (SetSecurityDescriptorOwner(pSecurityDescriptor, pOwner, FALSE) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetSecurityDescriptorDacl(JNIEnv* env, + jclass this, jlong address) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = jlong_to_ptr(address); + BOOL bDaclPresent; + PACL pDacl; + BOOL bDaclDefaulted; + + if (GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted) == 0) { + throwWindowsException(env, GetLastError()); + return (jlong)0; + } else { + return (bDaclPresent) ? ptr_to_jlong(pDacl) : (jlong)0; + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetSecurityDescriptorDacl(JNIEnv* env, + jclass this, jlong descAddress, jlong aclAddress) +{ + PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR)jlong_to_ptr(descAddress); + PACL pAcl = (PACL)jlong_to_ptr(aclAddress); + + if (SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pAcl, FALSE) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetAclInformation0(JNIEnv* env, + jclass this, jlong address, jobject obj) +{ + PACL pAcl = (PACL)jlong_to_ptr(address); + ACL_SIZE_INFORMATION acl_size_info; + + if (GetAclInformation(pAcl, (void *) &acl_size_info, sizeof(acl_size_info), AclSizeInformation) == 0) { + throwWindowsException(env, GetLastError()); + } else { + (*env)->SetIntField(env, obj, aclInfo_aceCount, (jint)acl_size_info.AceCount); + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetAce(JNIEnv* env, jclass this, jlong address, + jint aceIndex) +{ + PACL pAcl = (PACL)jlong_to_ptr(address); + LPVOID pAce; + + if (GetAce(pAcl, (DWORD)aceIndex, &pAce) == 0) { + throwWindowsException(env, GetLastError()); + return (jlong)0; + } else { + return ptr_to_jlong(pAce); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessAllowedAceEx(JNIEnv* env, + jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress) +{ + PACL pAcl = (PACL)jlong_to_ptr(aclAddress); + PSID pSid = (PSID)jlong_to_ptr(sidAddress); + + if (AddAccessAllowedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_AddAccessDeniedAceEx(JNIEnv* env, + jclass this, jlong aclAddress, jint flags, jint mask, jlong sidAddress) +{ + PACL pAcl = (PACL)jlong_to_ptr(aclAddress); + PSID pSid = (PSID)jlong_to_ptr(sidAddress); + + if (AddAccessDeniedAceEx(pAcl, ACL_REVISION, (DWORD)flags, (DWORD)mask, pSid) == 0) { + throwWindowsException(env, GetLastError()); + } +} + + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountSid0(JNIEnv* env, + jclass this, jlong address, jobject obj) +{ + WCHAR domain[255]; + WCHAR name[255]; + DWORD domainLen = sizeof(domain); + DWORD nameLen = sizeof(name); + SID_NAME_USE use; + PSID sid = jlong_to_ptr(address); + jstring s; + + if (LookupAccountSidW(NULL, sid, &name[0], &nameLen, &domain[0], &domainLen, &use) == 0) { + throwWindowsException(env, GetLastError()); + return; + } + + s = (*env)->NewString(env, (const jchar *)domain, (jsize)wcslen(domain)); + if (s == NULL) + return; + (*env)->SetObjectField(env, obj, account_domain, s); + + s = (*env)->NewString(env, (const jchar *)name, (jsize)wcslen(name)); + if (s == NULL) + return; + (*env)->SetObjectField(env, obj, account_name, s); + (*env)->SetIntField(env, obj, account_use, (jint)use); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_LookupAccountName0(JNIEnv* env, + jclass this, jlong nameAddress, jlong sidAddress, jint cbSid) +{ + + LPCWSTR accountName = jlong_to_ptr(nameAddress); + PSID sid = jlong_to_ptr(sidAddress); + WCHAR domain[255]; + DWORD domainLen = sizeof(domain); + SID_NAME_USE use; + + if (LookupAccountNameW(NULL, accountName, sid, (LPDWORD)&cbSid, + &domain[0], &domainLen, &use) == 0) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + throwWindowsException(env, GetLastError()); + } + } + + return cbSid; +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetLengthSid(JNIEnv* env, + jclass this, jlong address) +{ + PSID sid = jlong_to_ptr(address); + + if (GetLengthSid_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return 0; + } + return (jint)(*GetLengthSid_func)(sid); +} + + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_ConvertSidToStringSid(JNIEnv* env, + jclass this, jlong address) +{ + PSID sid = jlong_to_ptr(address); + LPWSTR string; + + if (ConvertSidToStringSid_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return NULL; + } + + if ((*ConvertSidToStringSid_func)(sid, &string) == 0) { + throwWindowsException(env, GetLastError()); + return NULL; + } else { + jstring s = (*env)->NewString(env, (const jchar *)string, + (jsize)wcslen(string)); + LocalFree(string); + return s; + } +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_ConvertStringSidToSid0(JNIEnv* env, + jclass this, jlong address) +{ + LPWSTR lpStringSid = jlong_to_ptr(address); + PSID pSid; + + if (ConvertStringSidToSid_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return (jlong)0; + } + + if ((*ConvertStringSidToSid_func)(lpStringSid, &pSid) == 0) + throwWindowsException(env, GetLastError()); + + return ptr_to_jlong(pSid); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentProcess(JNIEnv* env, jclass this) { + HANDLE hProcess = GetCurrentProcess(); + return ptr_to_jlong(hProcess); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetCurrentThread(JNIEnv* env, jclass this) { + HANDLE hThread = GetCurrentThread(); + return ptr_to_jlong(hThread); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_OpenProcessToken(JNIEnv* env, + jclass this, jlong process, jint desiredAccess) +{ + HANDLE hProcess = (HANDLE)jlong_to_ptr(process); + HANDLE hToken; + + if (OpenProcessToken(hProcess, (DWORD)desiredAccess, &hToken) == 0) + throwWindowsException(env, GetLastError()); + return ptr_to_jlong(hToken); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_OpenThreadToken(JNIEnv* env, + jclass this, jlong thread, jint desiredAccess, jboolean openAsSelf) +{ + HANDLE hThread = (HANDLE)jlong_to_ptr(thread); + HANDLE hToken; + BOOL bOpenAsSelf = (openAsSelf == JNI_TRUE) ? TRUE : FALSE; + + if (OpenThreadToken(hThread, (DWORD)desiredAccess, bOpenAsSelf, &hToken) == 0) { + if (GetLastError() == ERROR_NO_TOKEN) + return (jlong)0; + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(hToken); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_DuplicateTokenEx(JNIEnv* env, + jclass this, jlong token, jint desiredAccess) +{ + HANDLE hToken = (HANDLE)jlong_to_ptr(token); + HANDLE resultToken; + BOOL res; + + res = DuplicateTokenEx(hToken, + (DWORD)desiredAccess, + NULL, + SecurityImpersonation, + TokenImpersonation, + &resultToken); + if (res == 0) + throwWindowsException(env, GetLastError()); + return ptr_to_jlong(resultToken); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_SetThreadToken(JNIEnv* env, + jclass this, jlong thread, jlong token) +{ + HANDLE hThread = (HANDLE)jlong_to_ptr(thread); + HANDLE hToken = (HANDLE)jlong_to_ptr(token); + + if (SetThreadToken(hThread, hToken) == 0) + throwWindowsException(env, GetLastError()); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetTokenInformation(JNIEnv* env, + jclass this, jlong token, jint tokenInfoClass, jlong tokenInfo, jint tokenInfoLength) +{ + BOOL res; + DWORD lengthNeeded; + HANDLE hToken = (HANDLE)jlong_to_ptr(token); + LPVOID result = (LPVOID)jlong_to_ptr(tokenInfo); + + res = GetTokenInformation(hToken, (TOKEN_INFORMATION_CLASS)tokenInfoClass, (LPVOID)result, + tokenInfoLength, &lengthNeeded); + if (res == 0) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + return (jint)lengthNeeded; + } else { + throwWindowsException(env, GetLastError()); + return 0; + } + } else { + return tokenInfoLength; + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_AdjustTokenPrivileges(JNIEnv* env, + jclass this, jlong token, jlong luid, jint attributes) +{ + TOKEN_PRIVILEGES privs[1]; + HANDLE hToken = (HANDLE)jlong_to_ptr(token); + PLUID pLuid = (PLUID)jlong_to_ptr(luid); + + privs[0].PrivilegeCount = 1; + privs[0].Privileges[0].Luid = *pLuid; + privs[0].Privileges[0].Attributes = (DWORD)attributes; + + if (AdjustTokenPrivileges(hToken, FALSE, &privs[0], 1, NULL, NULL) == 0) + throwWindowsException(env, GetLastError()); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_LookupPrivilegeValue0(JNIEnv* env, + jclass this, jlong name) +{ + LPCWSTR lpName = (LPCWSTR)jlong_to_ptr(name); + PLUID pLuid = LocalAlloc(0, sizeof(LUID)); + + if (pLuid == NULL) { + JNU_ThrowInternalError(env, "Unable to allocate LUID structure"); + } else { + if (LookupPrivilegeValueW(NULL, lpName, pLuid) == 0) + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(pLuid); +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_BuildTrusteeWithSid(JNIEnv* env, + jclass this, jlong sid) +{ + PSID pSid = (HANDLE)jlong_to_ptr(sid); + PTRUSTEE_W pTrustee = LocalAlloc(0, sizeof(TRUSTEE_W)); + + if (pTrustee == NULL) { + JNU_ThrowInternalError(env, "Unable to allocate TRUSTEE_W structure"); + } else { + BuildTrusteeWithSidW(pTrustee, pSid); + } + return ptr_to_jlong(pTrustee); +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetEffectiveRightsFromAcl(JNIEnv* env, + jclass this, jlong acl, jlong trustee) +{ + ACCESS_MASK access; + PACL pAcl = (PACL)jlong_to_ptr(acl); + PTRUSTEE pTrustee = (PTRUSTEE)jlong_to_ptr(trustee); + + if (GetEffectiveRightsFromAcl(pAcl, pTrustee, &access) != ERROR_SUCCESS) { + throwWindowsException(env, GetLastError()); + } + return (jint)access; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateSymbolicLink0(JNIEnv* env, + jclass this, jlong linkAddress, jlong targetAddress, jint flags) +{ + LPCWSTR link = jlong_to_ptr(linkAddress); + LPCWSTR target = jlong_to_ptr(targetAddress); + + if (CreateSymbolicLink_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return; + } + + /* On Windows 64-bit this appears to succeed even when there is insufficient privileges */ + if ((*CreateSymbolicLink_func)(link, target, (DWORD)flags) == 0) + throwWindowsException(env, GetLastError()); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateHardLink0(JNIEnv* env, + jclass this, jlong newFileAddress, jlong existingFileAddress) +{ + LPCWSTR newFile = jlong_to_ptr(newFileAddress); + LPCWSTR existingFile = jlong_to_ptr(existingFileAddress); + + if (CreateHardLink_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return; + } + if ((*CreateHardLink_func)(newFile, existingFile, NULL) == 0) + throwWindowsException(env, GetLastError()); +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFullPathName0(JNIEnv *env, + jclass clz, + jlong pathAddress) +{ + jstring rv = NULL; + WCHAR *lpBuf = NULL; + WCHAR buf[MAX_PATH]; + DWORD len; + LPCWSTR lpFileName = jlong_to_ptr(pathAddress); + + len = GetFullPathNameW(lpFileName, MAX_PATH, buf, NULL); + if (len > 0) { + if (len < MAX_PATH) { + rv = (*env)->NewString(env, buf, len); + } else { + len += 1; /* return length does not include terminator */ + lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR)); + if (lpBuf != NULL) { + len = GetFullPathNameW(lpFileName, len, lpBuf, NULL); + if (len > 0) { + rv = (*env)->NewString(env, lpBuf, len); + } else { + JNU_ThrowInternalError(env, "GetFullPathNameW failed"); + } + free(lpBuf); + } + } + } + if (len == 0) + throwWindowsException(env, GetLastError()); + + return rv; +} + +JNIEXPORT jstring JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env, + jclass this, jlong handle) +{ + jstring rv = NULL; + WCHAR *lpBuf = NULL; + WCHAR path[MAX_PATH]; + HANDLE h = (HANDLE)jlong_to_ptr(handle); + DWORD len; + + if (GetFinalPathNameByHandle_func == NULL) { + JNU_ThrowInternalError(env, "Should not get here"); + return NULL; + } + + len = (*GetFinalPathNameByHandle_func)(h, path, MAX_PATH, 0); + if (len > 0) { + if (len < MAX_PATH) { + rv = (*env)->NewString(env, (const jchar *)path, (jsize)len); + } else { + len += 1; /* return length does not include terminator */ + lpBuf = (WCHAR*)malloc(len * sizeof(WCHAR)); + if (lpBuf != NULL) { + len = (*GetFinalPathNameByHandle_func)(h, lpBuf, len, 0); + if (len > 0) { + rv = (*env)->NewString(env, (const jchar *)lpBuf, (jsize)len); + } else { + JNU_ThrowInternalError(env, "GetFinalPathNameByHandleW failed"); + } + free(lpBuf); + } + } + } + + if (len == 0) + throwWindowsException(env, GetLastError()); + + return rv; +} + +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this, + jlong fileHandle, jlong existingPort, jint completionKey) +{ + HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle), + (HANDLE)jlong_to_ptr(existingPort), + (DWORD)completionKey, + 0); + if (port == NULL) { + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(port); +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jclass this, + jlong completionPort, jobject obj) +{ + DWORD bytesTransferred; + DWORD completionKey; + OVERLAPPED *lpOverlapped; + BOOL res; + + res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort), + &bytesTransferred, + &completionKey, + &lpOverlapped, + INFINITE); + if (res == 0 && lpOverlapped == NULL) { + throwWindowsException(env, GetLastError()); + } else { + DWORD ioResult = (res == 0) ? GetLastError() : 0; + (*env)->SetIntField(env, obj, completionStatus_error, ioResult); + (*env)->SetIntField(env, obj, completionStatus_bytesTransferred, + (jint)bytesTransferred); + (*env)->SetIntField(env, obj, completionStatus_completionKey, + (jint)completionKey); + + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this, + jlong completionPort, jint completionKey) +{ + BOOL res; + + res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort), + (DWORD)0, /* dwNumberOfBytesTransferred */ + (DWORD)completionKey, + NULL); /* lpOverlapped */ + if (res == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this, + jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter, + jlong bytesReturnedAddress, jlong pOverlapped) +{ + BOOL res; + BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE; + + ((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL; + res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory), + (LPVOID)jlong_to_ptr(bufferAddress), + (DWORD)bufferLength, + subtree, + (DWORD)filter, + (LPDWORD)jlong_to_ptr(bytesReturnedAddress), + (LPOVERLAPPED)jlong_to_ptr(pOverlapped), + NULL); + if (res == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_BackupRead0(JNIEnv* env, jclass this, + jlong hFile, jlong bufferAddress, jint bufferSize, jboolean abort, + jlong context, jobject obj) +{ + BOOL res; + DWORD bytesTransferred; + BOOL a = (abort == JNI_TRUE) ? TRUE : FALSE; + VOID* pContext = (VOID*)jlong_to_ptr(context); + + res = BackupRead((HANDLE)jlong_to_ptr(hFile), + (LPBYTE)jlong_to_ptr(bufferAddress), + (DWORD)bufferSize, + &bytesTransferred, + a, + FALSE, + &pContext); + if (res == 0) { + throwWindowsException(env, GetLastError()); + } else { + (*env)->SetIntField(env, obj, backupResult_bytesTransferred, + bytesTransferred); + (*env)->SetLongField(env, obj, backupResult_context, + ptr_to_jlong(pContext)); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_BackupSeek(JNIEnv* env, jclass this, + jlong hFile, jlong bytesToSeek, jlong context) +{ + BOOL res; + jint lowBytesToSeek = (jint)bytesToSeek; + jint highBytesToSeek = (jint)(bytesToSeek >> 32); + DWORD lowBytesSeeked; + DWORD highBytesSeeked; + VOID* pContext = jlong_to_ptr(context); + + res = BackupSeek((HANDLE)jlong_to_ptr(hFile), + (DWORD)lowBytesToSeek, + (DWORD)highBytesToSeek, + &lowBytesSeeked, + &highBytesSeeked, + &pContext); + if (res == 0) { + throwWindowsException(env, GetLastError()); + } +} diff --git a/jdk/src/windows/native/sun/security/krb5/WindowsDirectory.c b/jdk/src/windows/native/sun/security/krb5/WindowsDirectory.c index dc96bad91ab..7b11163863d 100644 --- a/jdk/src/windows/native/sun/security/krb5/WindowsDirectory.c +++ b/jdk/src/windows/native/sun/security/krb5/WindowsDirectory.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#define UNICODE #include #include #include @@ -30,22 +31,20 @@ /* * Class: sun_security_krb5_Config * Method: getWindowsDirectory - * Signature: ()Ljava/lang/String; + * Signature: (Z)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_sun_security_krb5_Config_getWindowsDirectory( - JNIEnv* env, jclass configClass) { - LPTSTR lpPath = NULL; - UINT uLength ; - jstring path = NULL; - - if (uLength = GetWindowsDirectory(lpPath, 0)) { - lpPath = (LPTSTR)malloc(sizeof(TCHAR) * uLength); - if (lpPath != NULL) { - if (GetWindowsDirectory(lpPath, uLength)) { - path = (*env)->NewStringUTF(env, lpPath); - } - free(lpPath); - } + JNIEnv* env, jclass configClass, jboolean isSystem) { + TCHAR lpPath[MAX_PATH+1]; + UINT len; + if (isSystem) { + len = GetSystemWindowsDirectory(lpPath, MAX_PATH); + } else { + len = GetWindowsDirectory(lpPath, MAX_PATH); + } + if (len) { + return (*env)->NewString(env, lpPath, len); + } else { + return NULL; } - return path; } diff --git a/jdk/src/windows/native/sun/windows/ComCtl32Util.cpp b/jdk/src/windows/native/sun/windows/ComCtl32Util.cpp index a36ac6df9fc..ac69cf3af60 100644 --- a/jdk/src/windows/native/sun/windows/ComCtl32Util.cpp +++ b/jdk/src/windows/native/sun/windows/ComCtl32Util.cpp @@ -23,54 +23,26 @@ * have any questions. */ +#include "awt.h" #include "ComCtl32Util.h" ComCtl32Util::ComCtl32Util() { - hModComCtl32 = NULL; - m_bNewSubclassing = FALSE; - - m_lpfnSetWindowSubclass = NULL; - m_lpfnRemoveWindowSubclass = NULL; - m_lpfnDefSubclassProc = NULL; } ComCtl32Util::~ComCtl32Util() { - DASSERT(hModComCtl32 == NULL); } void ComCtl32Util::InitLibraries() { - if (hModComCtl32 == NULL) { - hModComCtl32 = ::LoadLibrary(TEXT("comctl32.dll")); - if (hModComCtl32 != NULL) { - m_lpfnSetWindowSubclass = (PFNSETWINDOWSUBCLASS)::GetProcAddress(hModComCtl32, "SetWindowSubclass"); - m_lpfnRemoveWindowSubclass = (PFNREMOVEWINDOWSUBCLASS)::GetProcAddress(hModComCtl32, "RemoveWindowSubclass"); - m_lpfnDefSubclassProc = (PFNDEFSUBCLASSPROC)::GetProcAddress(hModComCtl32, "DefSubclassProc"); - - m_bNewSubclassing = (m_lpfnSetWindowSubclass != NULL) && - (m_lpfnRemoveWindowSubclass != NULL) && - (m_lpfnDefSubclassProc != NULL); - - fn_InitCommonControlsEx = (ComCtl32Util::InitCommonControlsExType)::GetProcAddress(hModComCtl32, "InitCommonControlsEx"); - InitCommonControls(); - } - } -} - -void ComCtl32Util::FreeLibraries() { - if (hModComCtl32 != NULL) { - m_lpfnSetWindowSubclass = NULL; - m_lpfnRemoveWindowSubclass = NULL; - m_lpfnDefSubclassProc = NULL; - ::FreeLibrary(hModComCtl32); - hModComCtl32 = NULL; - } + INITCOMMONCONTROLSEX iccex; + memset(&iccex, 0, sizeof(INITCOMMONCONTROLSEX)); + iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); + ::InitCommonControlsEx(&iccex); } WNDPROC ComCtl32Util::SubclassHWND(HWND hwnd, WNDPROC _WindowProc) { - if (m_bNewSubclassing) { - DASSERT(hModComCtl32 != NULL); + if (IS_WINXP) { const SUBCLASSPROC p = SharedWindowProc; // let compiler check type of SharedWindowProc - m_lpfnSetWindowSubclass(hwnd, p, (UINT_PTR)_WindowProc, NULL); // _WindowProc is used as subclass ID + ::SetWindowSubclass(hwnd, p, (UINT_PTR)_WindowProc, NULL); // _WindowProc is used as subclass ID return NULL; } else { return (WNDPROC)::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)_WindowProc); @@ -78,21 +50,17 @@ WNDPROC ComCtl32Util::SubclassHWND(HWND hwnd, WNDPROC _WindowProc) { } void ComCtl32Util::UnsubclassHWND(HWND hwnd, WNDPROC _WindowProc, WNDPROC _DefWindowProc) { - if (m_bNewSubclassing) { - DASSERT(hModComCtl32 != NULL); - DASSERT(_DefWindowProc == NULL); + if (IS_WINXP) { const SUBCLASSPROC p = SharedWindowProc; // let compiler check type of SharedWindowProc - m_lpfnRemoveWindowSubclass(hwnd, p, (UINT_PTR)_WindowProc); // _WindowProc is used as subclass ID + ::RemoveWindowSubclass(hwnd, p, (UINT_PTR)_WindowProc); // _WindowProc is used as subclass ID } else { ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)_DefWindowProc); } } LRESULT ComCtl32Util::DefWindowProc(WNDPROC _DefWindowProc, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (m_bNewSubclassing) { - DASSERT(hModComCtl32 != NULL); - DASSERT(_DefWindowProc == NULL); - return m_lpfnDefSubclassProc(hwnd, msg, wParam, lParam); + if (IS_WINXP) { + return ::DefSubclassProc(hwnd, msg, wParam, lParam); } else if (_DefWindowProc != NULL) { return ::CallWindowProc(_DefWindowProc, hwnd, msg, wParam, lParam); } else { @@ -111,15 +79,3 @@ LRESULT ComCtl32Util::SharedWindowProc(HWND hwnd, UINT msg, CATCH_BAD_ALLOC_RET(0); } - -void ComCtl32Util::InitCommonControls() -{ - if (fn_InitCommonControlsEx == NULL) { - return; - } - - INITCOMMONCONTROLSEX iccex; - memset(&iccex, 0, sizeof(INITCOMMONCONTROLSEX)); - iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); - fn_InitCommonControlsEx(&iccex); -} diff --git a/jdk/src/windows/native/sun/windows/ComCtl32Util.h b/jdk/src/windows/native/sun/windows/ComCtl32Util.h index 888a14db1ba..e137b43d0df 100644 --- a/jdk/src/windows/native/sun/windows/ComCtl32Util.h +++ b/jdk/src/windows/native/sun/windows/ComCtl32Util.h @@ -30,20 +30,6 @@ #ifndef _COMCTL32UTIL_H #define _COMCTL32UTIL_H - -/* - * comctl32.dll version 6 subclassing - taken from PlatformSDK/Include/commctrl.h - */ -typedef LRESULT (CALLBACK *SUBCLASSPROC)(HWND hWnd, UINT uMsg, WPARAM wParam, \ - LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); - -typedef BOOL (WINAPI *PFNSETWINDOWSUBCLASS)(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uIdSubclass, \ - DWORD_PTR dwRefData); -typedef BOOL (WINAPI *PFNREMOVEWINDOWSUBCLASS)(HWND hWnd, SUBCLASSPROC pfnSubclass, \ - UINT_PTR uIdSubclass); - -typedef LRESULT (WINAPI *PFNDEFSUBCLASSPROC)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - class ComCtl32Util { public: @@ -52,21 +38,8 @@ class ComCtl32Util return theInstance; } - // loads comctl32.dll and checks if required routines are available - // called from AwtToolkit::AwtToolkit() void InitLibraries(); - // unloads comctl32.dll - // called from AwtToolkit::Dispose() - void FreeLibraries(); - //-- comctl32.dll version 6 subclassing API --// - - INLINE BOOL IsNewSubclassing() { - return m_bNewSubclassing; - } - - // if comctl32.dll version 6 is used returns NULL, otherwise - // returns default window proc WNDPROC SubclassHWND(HWND hwnd, WNDPROC _WindowProc); // DefWindowProc is the same as returned from SubclassHWND void UnsubclassHWND(HWND hwnd, WNDPROC _WindowProc, WNDPROC _DefWindowProc); @@ -77,19 +50,6 @@ class ComCtl32Util ComCtl32Util(); ~ComCtl32Util(); - HMODULE hModComCtl32; - - PFNSETWINDOWSUBCLASS m_lpfnSetWindowSubclass; - PFNREMOVEWINDOWSUBCLASS m_lpfnRemoveWindowSubclass; - PFNDEFSUBCLASSPROC m_lpfnDefSubclassProc; - - typedef BOOL (WINAPI * InitCommonControlsExType)(const LPINITCOMMONCONTROLSEX lpInitCtrls); - InitCommonControlsExType fn_InitCommonControlsEx; - - void InitCommonControls(); - - BOOL m_bNewSubclassing; - // comctl32.dll version 6 window proc static LRESULT CALLBACK SharedWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, diff --git a/jdk/src/windows/native/sun/windows/Devices.cpp b/jdk/src/windows/native/sun/windows/Devices.cpp index 8bcee15b877..79b36b3f1a8 100644 --- a/jdk/src/windows/native/sun/windows/Devices.cpp +++ b/jdk/src/windows/native/sun/windows/Devices.cpp @@ -83,9 +83,83 @@ #include "Devices.h" #include "Trace.h" -#include "awt_Multimon.h" #include "D3DPipelineManager.h" + +/* Some helper functions (from awt_MMStub.h/cpp) */ + +int g_nMonitorCounter; +int g_nMonitorLimit; +HMONITOR* g_hmpMonitors; + +// Callback for CountMonitors below +BOOL WINAPI clb_fCountMonitors(HMONITOR hMon, HDC hDC, LPRECT rRect, LPARAM lP) +{ + g_nMonitorCounter ++; + return TRUE; +} + +int WINAPI CountMonitors(void) +{ + g_nMonitorCounter = 0; + ::EnumDisplayMonitors(NULL, NULL, clb_fCountMonitors, 0L); + return g_nMonitorCounter; + +} + +// Callback for CollectMonitors below +BOOL WINAPI clb_fCollectMonitors(HMONITOR hMon, HDC hDC, LPRECT rRect, LPARAM lP) +{ + + if ((g_nMonitorCounter < g_nMonitorLimit) && (NULL != g_hmpMonitors)) { + g_hmpMonitors[g_nMonitorCounter] = hMon; + g_nMonitorCounter ++; + } + + return TRUE; +} + +int WINAPI CollectMonitors(HMONITOR* hmpMonitors, int nNum) +{ + int retCode = 0; + + if (NULL != hmpMonitors) { + + g_nMonitorCounter = 0; + g_nMonitorLimit = nNum; + g_hmpMonitors = hmpMonitors; + + ::EnumDisplayMonitors(NULL, NULL, clb_fCollectMonitors, 0L); + + retCode = g_nMonitorCounter; + + g_nMonitorCounter = 0; + g_nMonitorLimit = 0; + g_hmpMonitors = NULL; + + } + return retCode; +} + +BOOL WINAPI MonitorBounds(HMONITOR hmMonitor, RECT* rpBounds) +{ + BOOL retCode = FALSE; + + if ((NULL != hmMonitor) && (NULL != rpBounds)) { + MONITORINFOEX miInfo; + + memset((void*)(&miInfo), 0, sizeof(MONITORINFOEX)); + miInfo.cbSize = sizeof(MONITORINFOEX); + + if (TRUE == (retCode = ::GetMonitorInfo(hmMonitor, &miInfo))) { + (*rpBounds) = miInfo.rcMonitor; + } + } + return retCode; +} + +/* End of helper functions */ + Devices* Devices::theInstance = NULL; CriticalSection Devices::arrayLock; @@ -113,9 +187,9 @@ BOOL Devices::UpdateInstance(JNIEnv *env) { J2dTraceLn(J2D_TRACE_INFO, "Devices::UpdateInstance"); - int numScreens = ::CountMonitors(); - MHND *monHds = (MHND *)safe_Malloc(numScreens * sizeof(MHND)); - if (numScreens != ::CollectMonitors(monHds, numScreens)) { + int numScreens = CountMonitors(); + HMONITOR *monHds = (HMONITOR *)safe_Malloc(numScreens * sizeof(HMONITOR)); + if (numScreens != CollectMonitors(monHds, numScreens)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "Devices::UpdateInstance: Failed to get all "\ "monitor handles."); diff --git a/jdk/src/windows/native/sun/windows/Devices.h b/jdk/src/windows/native/sun/windows/Devices.h index 949bfdb2d26..34e359aa446 100644 --- a/jdk/src/windows/native/sun/windows/Devices.h +++ b/jdk/src/windows/native/sun/windows/Devices.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,4 +70,8 @@ static CriticalSection arrayLock; }; +// Some helper functions (from awt_MMStub.h/cpp) + +BOOL WINAPI MonitorBounds (HMONITOR, RECT*); + #endif _DEVICES_H_ diff --git a/jdk/src/windows/native/sun/windows/GDIHashtable.cpp b/jdk/src/windows/native/sun/windows/GDIHashtable.cpp index a3bc8ebe7b6..25c0dac4507 100644 --- a/jdk/src/windows/native/sun/windows/GDIHashtable.cpp +++ b/jdk/src/windows/native/sun/windows/GDIHashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #include "GDIHashtable.h" #include "awt_GDIObject.h" -#include "awt_dlls.h" GDIHashtable::BatchDestructionManager GDIHashtable::manager; @@ -46,7 +45,6 @@ void GDIHashtable::release(void* key) { DASSERT(value != NULL); m_deleteProc(value); } - manager.update(); } void GDIHashtable::flush() { @@ -128,9 +126,6 @@ void GDIHashtable::List::clear() { } } -#undef GFSR_GDIRESOURCES -#define GFSR_GDIRESOURCES 0x0001 - GDIHashtable::BatchDestructionManager::BatchDestructionManager(UINT nFirstThreshold, UINT nSecondThreshold, UINT nDestroyPeriod) : @@ -138,48 +133,6 @@ GDIHashtable::BatchDestructionManager::BatchDestructionManager(UINT nFirstThresh m_nSecondThreshold(nSecondThreshold), m_nDestroyPeriod(nDestroyPeriod), m_nCounter(0), - m_bBatchingEnabled(TRUE) { - load_rsrc32_procs(); -} - -void GDIHashtable::BatchDestructionManager::update() { - - if (get_free_system_resources != NULL) { - - CriticalSection::Lock l(m_managerLock); - - if (m_nCounter < 0) { - UINT nFreeResources = (*get_free_system_resources)(GFSR_GDIRESOURCES); - /* - * If m_bBatchingEnabled is FALSE there is no need - * to flush since we have been destroying all - * GDI resources as soon as they were released. - */ - if (m_bBatchingEnabled) { - if (nFreeResources < m_nFirstThreshold) { - flushAll(); - nFreeResources = (*get_free_system_resources)(GFSR_GDIRESOURCES); - } - } - if (nFreeResources < m_nSecondThreshold) { - m_bBatchingEnabled = FALSE; - m_nCounter = m_nDestroyPeriod; - } else { - m_bBatchingEnabled = TRUE; - /* - * The frequency of checks must depend on the currect amount - * of free space in GDI heaps. Otherwise we can run into the - * Resource Meter warning dialog when GDI resources are low. - * This is a heuristic rule that provides this dependency. - * These numbers have been chosen because: - * Resource Meter posts a warning dialog when less than 10% - * of GDI resources are free. - * 5 pens/brushes take 1%. So 3 is the upper bound. - * When changing this rule you should check that performance - * isn't affected (with Caffeine Mark and JMark). - */ - m_nCounter = (nFreeResources - 10) * 3; - } - } - } + m_bBatchingEnabled(TRUE) +{ } diff --git a/jdk/src/windows/native/sun/windows/GDIHashtable.h b/jdk/src/windows/native/sun/windows/GDIHashtable.h index 406a59e230a..a324fd97e24 100644 --- a/jdk/src/windows/native/sun/windows/GDIHashtable.h +++ b/jdk/src/windows/native/sun/windows/GDIHashtable.h @@ -1,5 +1,5 @@ /* - * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,12 +151,6 @@ class GDIHashtable : public Hashtable { */ INLINE void decrementCounter() { m_nCounter--; } - /** - * Depending on the amount of free space in GDI heaps flushes - * all GDIHashtables and sets the initial counter value. - */ - void update(); - INLINE CriticalSection& getLock() { return m_managerLock; } }; diff --git a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp index 7ed24aadb8a..3baf5bcf9b9 100644 --- a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp +++ b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,17 +31,27 @@ // This file should stand independent of AWT and should ultimately be // put into its own DLL. #include -#endif +#else +// Include jni_util.h first, so JNU_* macros can be redefined +#include "jni_util.h" +// Borrow some macros from awt.h +#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast(x), static_cast(_tcslen(x))) +#define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast(env->GetStringChars(x, y)) +#define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast(y)) +#endif // DEBUG #include #include #include -#include "jni_util.h" #include "jlong.h" #include "alloc.h" #include "stdhdrs.h" -#include "UnicowsLoader.h" + +// Copy from shlguid.h which is no longer in PlatformSDK +#ifndef DEFINE_SHLGUID +#define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0, 0, 0, 0, 0, 0, 0, 0x46) +#endif // {93F2F68C-1D1B-11d3-A30E-00C04F79ABD1} DEFINE_GUID(IID_IShellFolder2, 0x93f2f68c, 0x1d1b, 0x11d3, 0xa3, 0xe, 0x0, 0xc0, 0x4f, 0x79, 0xab, 0xd1); @@ -86,13 +96,15 @@ static jfieldID FID_folderType; static IMalloc* pMalloc; static IShellFolder* pDesktop; -static BOOL isXP; - -// copied from awt.h, because it is not included in release -#if defined (WIN32) - #define IS_WINVISTA (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion())) >= 6) -#else - #define IS_WINVISTA FALSE +// Some macros from awt.h, because it is not included in release +#ifndef IS_WIN2000 +#define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5) +#endif +#ifndef IS_WINXP +#define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5) +#endif +#ifndef IS_WINVISTA +#define IS_WINVISTA (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion())) >= 6) #endif @@ -103,7 +115,6 @@ static BOOL initShellProcs() static HMODULE libShell32 = NULL; static HMODULE libUser32 = NULL; static HMODULE libComCtl32 = NULL; - static HMODULE libUnicows = UnicowsLoader::GetModuleHandle(); // If already initialized, return TRUE if (libShell32 != NULL && libUser32 != NULL) { return TRUE; @@ -130,7 +141,7 @@ static BOOL initShellProcs() // Set up procs - libShell32 fn_FindExecutable = (FindExecutableType)GetProcAddress( - (libUnicows ? libUnicows : libShell32), "FindExecutableW"); + libShell32, "FindExecutableW"); if (fn_FindExecutable == NULL) { return FALSE; } @@ -140,7 +151,7 @@ static BOOL initShellProcs() return FALSE; } fn_SHGetFileInfo = (SHGetFileInfoType)GetProcAddress( - (libUnicows ? libUnicows : libShell32), "SHGetFileInfoW"); + libShell32, "SHGetFileInfoW"); if (fn_SHGetFileInfo == NULL) { return FALSE; } @@ -154,7 +165,7 @@ static BOOL initShellProcs() return FALSE; } fn_SHGetPathFromIDList = (SHGetPathFromIDListType)GetProcAddress( - (libUnicows ? libUnicows : libShell32), "SHGetPathFromIDListW"); + libShell32, "SHGetPathFromIDListW"); if (fn_SHGetPathFromIDList == NULL) { return FALSE; } @@ -181,19 +192,19 @@ static BOOL initShellProcs() static jstring jstringFromSTRRET(JNIEnv* env, LPITEMIDLIST pidl, STRRET* pStrret) { switch (pStrret->uType) { case STRRET_CSTR : - return JNU_NewStringPlatform(env, pStrret->cStr); + return JNU_NewStringPlatform(env, reinterpret_cast(pStrret->cStr)); case STRRET_OFFSET : // Note : this may need to be WCHAR instead return JNU_NewStringPlatform(env, (CHAR*)pidl + pStrret->uOffset); case STRRET_WSTR : - return env->NewString(pStrret->pOleStr, + return env->NewString(reinterpret_cast(pStrret->pOleStr), static_cast(wcslen(pStrret->pOleStr))); } return NULL; } // restoring the original definition -#define JNU_NewStringPlatform(env, x) env->NewString(x, static_cast(_tcslen(x))) +#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast(x), static_cast(_tcslen(x))) /* * Class: sun_awt_shell_Win32ShellFolder2 @@ -212,13 +223,6 @@ JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initIDs MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V"); FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;"); FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;"); - - // Find out if we are on XP or later - long version = GetVersion(); - isXP = (!(version & 0x80000000) && - (LOBYTE(LOWORD(version)) == 5 && - HIBYTE(LOWORD(version)) >= 1) || - LOBYTE(LOWORD(version)) > 5); } static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) { @@ -669,46 +673,24 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation if (!CoInit(doCoUninit)) { return 0; } - if (IS_NT) { - IShellLinkW* psl; - hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl); + IShellLinkW* psl; + hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl); + if (SUCCEEDED(hres)) { + IPersistFile* ppf; + hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); if (SUCCEEDED(hres)) { - IPersistFile* ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + hres = ppf->Load(wstr, STGM_READ); if (SUCCEEDED(hres)) { - hres = ppf->Load(wstr, STGM_READ); - if (SUCCEEDED(hres)) { - if (resolve) { - hres = psl->Resolve(NULL, 0); - // Ignore failure - } - pidl = (LPITEMIDLIST)NULL; - hres = psl->GetIDList(&pidl); + if (resolve) { + hres = psl->Resolve(NULL, 0); + // Ignore failure } - ppf->Release(); + pidl = (LPITEMIDLIST)NULL; + hres = psl->GetIDList(&pidl); } - psl->Release(); - } - } else { - IShellLinkA* psl; - hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (LPVOID *)&psl); - if (SUCCEEDED(hres)) { - IPersistFile* ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Load(wstr, STGM_READ); - if (SUCCEEDED(hres)) { - if (resolve) { - hres = psl->Resolve(NULL, 0); - // Ignore failure - } - pidl = (LPITEMIDLIST)NULL; - hres = psl->GetIDList(&pidl); - } - ppf->Release(); - } - psl->Release(); + ppf->Release(); } + psl->Release(); } if (doCoUninit) { ::CoUninitialize(); @@ -742,10 +724,10 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_parseDisplayName0 int nLength = env->GetStringLength(jname); jchar* wszPath = new jchar[nLength + 1]; const jchar* strPath = env->GetStringChars(jname, NULL); - wcsncpy(wszPath, strPath, nLength); + wcsncpy(reinterpret_cast(wszPath), reinterpret_cast(strPath), nLength); wszPath[nLength] = 0; HRESULT res = pIShellFolder->ParseDisplayName(NULL, NULL, - const_cast(wszPath), NULL, &pIDL, NULL); + reinterpret_cast(wszPath), NULL, &pIDL, NULL); if (res != S_OK) { JNU_ThrowIOException(env, "Could not parse name"); pIDL = 0; @@ -804,7 +786,7 @@ JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getExecutableType (JNIEnv* env, jobject folder, jstring path) { TCHAR szBuf[MAX_PATH]; - LPCTSTR szPath = (LPCTSTR)JNU_GetStringPlatformChars(env, path, NULL); + LPCTSTR szPath = JNU_GetStringPlatformChars(env, path, NULL); if (szPath == NULL) { return NULL; } @@ -827,7 +809,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIcon { HICON hIcon = NULL; SHFILEINFO fileInfo; - LPCTSTR pathStr = (LPCTSTR)JNU_GetStringPlatformChars(env, absolutePath, NULL); + LPCTSTR pathStr = JNU_GetStringPlatformChars(env, absolutePath, NULL); if (fn_SHGetFileInfo(pathStr, 0L, &fileInfo, sizeof(fileInfo), SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)) != 0) { hIcon = fileInfo.hIcon; @@ -890,52 +872,27 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon } HRESULT hres; - if (IS_NT) { - IExtractIconW* pIcon; - hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast(&pidl), + IExtractIconW* pIcon; + hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast(&pidl), IID_IExtractIconW, NULL, (void**)&pIcon); + if (SUCCEEDED(hres)) { + WCHAR szBuf[MAX_PATH]; + INT index; + UINT flags; + hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags); if (SUCCEEDED(hres)) { - WCHAR szBuf[MAX_PATH]; - INT index; - UINT flags; - hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags); + HICON hIconLarge; + hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32); if (SUCCEEDED(hres)) { - HICON hIconLarge; - hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32); - if (SUCCEEDED(hres)) { - if (getLargeIcon) { - fn_DestroyIcon((HICON)hIcon); - hIcon = hIconLarge; - } else { - fn_DestroyIcon((HICON)hIconLarge); - } + if (getLargeIcon) { + fn_DestroyIcon((HICON)hIcon); + hIcon = hIconLarge; + } else { + fn_DestroyIcon((HICON)hIconLarge); } } - pIcon->Release(); - } - } else { - IExtractIconA* pIcon; - hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast(&pidl), - IID_IExtractIconA, NULL, (void**)&pIcon); - if (SUCCEEDED(hres)) { - CHAR szBuf[MAX_PATH]; - INT index; - UINT flags; - hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags); - if (SUCCEEDED(hres)) { - HICON hIconLarge; - hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32); - if (SUCCEEDED(hres)) { - if (getLargeIcon) { - fn_DestroyIcon((HICON)hIcon); - hIcon = hIconLarge; - } else { - fn_DestroyIcon((HICON)hIconLarge); - } - } - } - pIcon->Release(); } + pIcon->Release(); } if (doCoUninit) { ::CoUninitialize(); @@ -987,7 +944,7 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits // XP supports alpha in some icons, and depending on device. // This should take precedence over the icon mask bits. BOOL hasAlpha = FALSE; - if (isXP) { + if (IS_WINXP) { for (int i = 0; i < nBits; i++) { if ((colorBits[i] & 0xff000000) != 0) { hasAlpha = TRUE; @@ -1127,9 +1084,9 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource (JNIEnv* env, jclass cls, jstring libName, jint iconID, jint cxDesired, jint cyDesired, jboolean useVGAColors) { - HINSTANCE libHandle = LoadLibrary(env->GetStringChars(libName, NULL)); + HINSTANCE libHandle = LoadLibrary(JNU_GetStringPlatformChars(env, libName, NULL)); if (libHandle != NULL) { - UINT fuLoad = (useVGAColors && !isXP) ? LR_VGACOLOR : 0; + UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0; return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID), IMAGE_ICON, cxDesired, cyDesired, fuLoad)); diff --git a/jdk/src/windows/native/sun/windows/UnicowsLoader.cpp b/jdk/src/windows/native/sun/windows/UnicowsLoader.cpp deleted file mode 100644 index 7e147e209e6..00000000000 --- a/jdk/src/windows/native/sun/windows/UnicowsLoader.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#include -#include "alloc.h" -#include "UnicowsLoader.h" - -/* - * Support functions for the Microsoft Layer for Unicode (MSLU). - * - * The MSLU maps the wide char version of Windows APIs with strings - * to their ANSI version equivalent on Win98/ME platforms. - * - * For more details on the MSLU, please refer to the MSDN webpage at: - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mslu/winprog/microsoft_layer_for_unicode_on_windows_95_98_me_systems.asp - */ - -// The MSLU module handle. Only initialized on Win9x/ME. -HMODULE UnicowsLoader::hmodUnicows = NULL; - -// MSLU loader entry point, which is called when the module -// is initialized. -extern "C" HMODULE (__stdcall *_PfnLoadUnicows)(void) = - &UnicowsLoader::LoadUnicows; - -// Overriede APIs that are not supported by MSLU. -extern "C" FARPROC Unicows_GetPrinterW = - (FARPROC)&UnicowsLoader::GetPrinterWImpl; -extern "C" FARPROC Unicows_EnumPrintersW = - (FARPROC)&UnicowsLoader::EnumPrintersWImpl; - -HMODULE __stdcall UnicowsLoader::LoadUnicows(void) -{ - if (hmodUnicows != NULL) { - return hmodUnicows; - } - - // Unfortunately, some DLLs that are loaded in conjunction with - // unicows.dll may blow the FPU's control word. So save it here. - unsigned int fpu_cw = _CW_DEFAULT; - fpu_cw = _control87(0, 0); - - // Loads the DLL, assuming that the DLL resides in the same directory - // as the AWT(_G).DLL. We cannot use "sun.boot.library.path" system - // property since there is no way to issue JNI calls at this point - // (JNI_OnLoad is not yet called so it cannot obtain JavaVM structure) - // - // To obtain the AWT module handle, call GetModuleHandleA() directly, - // instead of AwtToolkit.GetModuleHandle(). Otherwise it could cause - // an infinite loop if some W call were made inside AwtToolkit class - // initialization. - HMODULE hmodAWT = GetModuleHandleA("awt"); - LPSTR abspath = (LPSTR)safe_Malloc(MAX_PATH); - if (abspath != NULL) { - GetModuleFileNameA(hmodAWT, abspath, MAX_PATH); - *strrchr(abspath, '\\') = '\0'; - strcat(abspath, "\\unicows.dll"); - hmodUnicows = LoadLibraryA(abspath); - free(abspath); - } - - // Restore the FPU control word if needed. - if ( _control87(0, 0) != fpu_cw) { - _control87(fpu_cw, 0xfffff); - } - - return hmodUnicows; -} - -HMODULE UnicowsLoader::GetModuleHandle(void) -{ - return hmodUnicows; -} - - -// Convenient functions to convert DEVMODEA -> DEVMODEW -void UnicowsLoader::DevModeA2DevModeW( - const DEVMODEA * dma, - DEVMODEW * dmw) -{ - // convert string portions - ::MultiByteToWideChar(CP_ACP, 0, (CHAR *)dma->dmDeviceName, CCHDEVICENAME, - dmw->dmDeviceName, CCHDEVICENAME); - ::MultiByteToWideChar(CP_ACP, 0, (CHAR *)dma->dmFormName, CCHDEVICENAME, - dmw->dmFormName, CCHDEVICENAME); - - // copy driver specific data if exists - if (dma->dmDriverExtra != 0) { - PBYTE pExtraA = (PBYTE)(dma + 1); - PBYTE pExtraW = (PBYTE)(dmw + 1); - memcpy(pExtraW, pExtraA, dma->dmDriverExtra); - } - - // copy normal struct members - dmw->dmSpecVersion = dma->dmSpecVersion; - dmw->dmDriverVersion = dma->dmDriverVersion; - dmw->dmSize = dma->dmSize; - dmw->dmDriverExtra = dma->dmDriverExtra; - dmw->dmFields = dma->dmFields; - dmw->dmPosition = dma->dmPosition; - dmw->dmScale = dma->dmScale; - dmw->dmCopies = dma->dmCopies; - dmw->dmDefaultSource = dma->dmDefaultSource; - dmw->dmPrintQuality = dma->dmPrintQuality; - dmw->dmColor = dma->dmColor; - dmw->dmDuplex = dma->dmDuplex; - dmw->dmYResolution = dma->dmYResolution; - dmw->dmTTOption = dma->dmTTOption; - dmw->dmCollate = dma->dmCollate; - dmw->dmLogPixels = dma->dmLogPixels; - dmw->dmBitsPerPel = dma->dmBitsPerPel; - dmw->dmPelsWidth = dma->dmPelsWidth; - dmw->dmPelsHeight = dma->dmPelsHeight; - dmw->dmDisplayFlags = dma->dmDisplayFlags; - dmw->dmDisplayFrequency = dma->dmDisplayFrequency; -#if(WINVER >= 0x0400) - dmw->dmICMMethod = dma->dmICMMethod; - dmw->dmICMIntent = dma->dmICMIntent; - dmw->dmMediaType = dma->dmMediaType; - dmw->dmDitherType = dma->dmDitherType; - dmw->dmReserved1 = dma->dmReserved1; - dmw->dmReserved2 = dma->dmReserved2; -#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400) - dmw->dmPanningWidth = dma->dmPanningWidth; - dmw->dmPanningHeight = dma->dmPanningHeight; -#endif -#endif /* WINVER >= 0x0400 */ -} - -// PRINTER_INFO_1 struct converter -void UnicowsLoader::PrinterInfo1A2W( - const LPPRINTER_INFO_1A pi1A, - LPPRINTER_INFO_1W pi1W, - const DWORD num) -{ - LPWSTR pwstrbuf = (LPWSTR)(pi1W + num); - DWORD current; - - // loop through all structures - for (current = 0; current < num; current ++) { - LPPRINTER_INFO_1A curPi1A = pi1A + current; - LPPRINTER_INFO_1W curPi1W = pi1W + current; - - // copy the structure itself - memcpy(curPi1W, curPi1A, sizeof(_PRINTER_INFO_1W)); - - // copy string members - StringA2W(curPi1A->pDescription, &(curPi1W->pDescription), &pwstrbuf); - StringA2W(curPi1A->pName, &(curPi1W->pName), &pwstrbuf); - StringA2W(curPi1A->pComment, &(curPi1W->pComment), &pwstrbuf); - } -} - -// PRINTER_INFO_2 struct converter -void UnicowsLoader::PrinterInfo2A2W( - const LPPRINTER_INFO_2A pi2A, - LPPRINTER_INFO_2W pi2W, - const DWORD num) -{ - PBYTE pbytebuf = (PBYTE)(pi2W + num); - DWORD current; - - // loop through all structures - for (current = 0; current < num; current ++) { - LPPRINTER_INFO_2A curPi2A = pi2A + current; - LPPRINTER_INFO_2W curPi2W = pi2W + current; - // copy the structure itself - memcpy(curPi2W, curPi2A, sizeof(_PRINTER_INFO_2W)); - - // copy string members - StringA2W(curPi2A->pServerName, &(curPi2W->pServerName), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pPrinterName, &(curPi2W->pPrinterName), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pShareName, &(curPi2W->pShareName), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pPortName, &(curPi2W->pPortName), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pDriverName, &(curPi2W->pDriverName), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pComment, &(curPi2W->pComment), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pLocation, &(curPi2W->pLocation), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pSepFile, &(curPi2W->pSepFile), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pPrintProcessor, &(curPi2W->pPrintProcessor), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pDatatype, &(curPi2W->pDatatype), (LPWSTR *)&pbytebuf); - StringA2W(curPi2A->pParameters, &(curPi2W->pParameters), (LPWSTR *)&pbytebuf); - - // copy DEVMODE structure - if (curPi2A->pDevMode != NULL) { - curPi2W->pDevMode = (LPDEVMODEW)pbytebuf; - DevModeA2DevModeW(curPi2A->pDevMode, curPi2W->pDevMode); - pbytebuf += sizeof(DEVMODEW) + curPi2A->pDevMode->dmDriverExtra; - } - } -} - -// PRINTER_INFO_5 struct converter -void UnicowsLoader::PrinterInfo5A2W( - const LPPRINTER_INFO_5A pi5A, - LPPRINTER_INFO_5W pi5W, - const DWORD num) -{ - LPWSTR pbuf = (LPWSTR)(pi5W + num); - DWORD current; - - // loop through all structures - for (current = 0; current < num; current ++) { - LPPRINTER_INFO_5A curPi5A = pi5A + current; - LPPRINTER_INFO_5W curPi5W = pi5W + current; - - // copy the structure itself - memcpy(curPi5W, curPi5A, sizeof(_PRINTER_INFO_5W)); - - // copy string members - StringA2W(curPi5A->pPrinterName, &(curPi5W->pPrinterName), &pbuf); - StringA2W(curPi5A->pPortName, &(curPi5W->pPortName), &pbuf); - } -} - -// PRINTER_INFO_* struct converter. Supported levels are 1, 2, and 5. -void UnicowsLoader::PrinterInfoA2W( - const PVOID piA, - PVOID piW, - const DWORD Level, - const DWORD num) -{ - switch (Level) { - case 1: - PrinterInfo1A2W((LPPRINTER_INFO_1A)piA, (LPPRINTER_INFO_1W)piW, num); - break; - - case 2: - PrinterInfo2A2W((LPPRINTER_INFO_2A)piA, (LPPRINTER_INFO_2W)piW, num); - break; - - case 5: - PrinterInfo5A2W((LPPRINTER_INFO_5A)piA, (LPPRINTER_INFO_5W)piW, num); - break; - } -} - -// converts string members in PRINTER_INFO_* struct. -void UnicowsLoader::StringA2W( - LPCSTR pSrcA, - LPWSTR * ppwstrDest, - LPWSTR * ppwstrbuf) -{ - if (pSrcA != NULL) { - DWORD cchWideChar = ::MultiByteToWideChar(CP_ACP, 0, pSrcA, -1, NULL, 0); - *ppwstrDest = *ppwstrbuf; - ::MultiByteToWideChar(CP_ACP, 0, pSrcA, -1, *ppwstrbuf, cchWideChar); - *ppwstrbuf += cchWideChar; - } else { - *ppwstrDest = NULL; - } -} - -// GetPrinterW implementation. Level 1, 2, and 5 are the only supported levels. -BOOL __stdcall UnicowsLoader::GetPrinterWImpl( - HANDLE hPrinter, - DWORD Level, - LPBYTE pPrinter, - DWORD cbBuf, - LPDWORD pcbNeeded) -{ - if ((Level != 1) && (Level != 2) && (Level != 5)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - - DWORD cbBufA = (cbBuf != 0 ? cbBuf / 2 : 0); // dirty estimation... - LPBYTE pPrinterA = NULL; - DWORD cbNeededA = 0; - BOOL ret; - - if (cbBufA != 0) { - pPrinterA = (LPBYTE)safe_Malloc(cbBufA); - memset(pPrinterA, 0, cbBufA); - } - - ret = ::GetPrinterA(hPrinter, Level, pPrinterA, cbBufA, &cbNeededA); - *pcbNeeded = cbNeededA * 2; // dirty estimation... - - if (pPrinterA != NULL) { - if (ret) { - PrinterInfoA2W(pPrinterA, pPrinter, Level, 1); - } - free(pPrinterA); - } - - return ret; -} - -// EnumPrintersW implementation. Level 1, 2, and 5 are the only supported levels. -BOOL __stdcall UnicowsLoader::EnumPrintersWImpl( - DWORD Flags, - LPWSTR Name, - DWORD Level, - LPBYTE pPrinterEnum, - DWORD cbBuf, - LPDWORD pcbNeeded, - LPDWORD pcReturned) -{ - if ((Level != 1) && (Level != 2) && (Level != 5)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - - LPSTR pNameA = NULL; - DWORD cbBufA = (cbBuf != 0 ? cbBuf / 2 : 0); // dirty estimation... - LPBYTE pPrinterEnumA = NULL; - DWORD cbNeededA = 0; - BOOL ret; - - if (Name != NULL) { - DWORD len = static_cast(wcslen(Name)) + 1; - pNameA = (LPSTR)safe_Malloc(len); - ::WideCharToMultiByte(CP_ACP, 0, Name, -1, pNameA, len, NULL, NULL); - } - - if (cbBufA != 0) { - pPrinterEnumA = (LPBYTE)safe_Malloc(cbBufA); - memset(pPrinterEnumA, 0, cbBufA); - } - - ret = ::EnumPrintersA(Flags, pNameA, Level, pPrinterEnumA, - cbBufA, &cbNeededA, pcReturned); - *pcbNeeded = cbNeededA * 2; // dirty estimation... - - if (pPrinterEnumA != NULL) { - if (ret) { - PrinterInfoA2W(pPrinterEnumA, pPrinterEnum, Level, *pcReturned); - } - free(pPrinterEnumA); - } - - if (pNameA != NULL) { - free(pNameA); - } - - return ret; -} - -// wchar CRT implementations that VC6 does not support on Win9x. -// These implementations are used on both Win9x/ME *and* WinNT/2K/XP. -#undef _waccess -#undef _wchmod -#undef _wfullpath -#undef _wremove -#undef _wrename -#undef _wstat -#undef _wstati64 -#undef _wstat64 -#undef _wunlink -#undef _wfopen -#undef _wfreopen -#undef _wfsopen -#undef _wcreat -#undef _wopen -#undef _wsopen -#undef _wfindfirst -#undef _wfindfirst64 -#undef _wfindnext -#undef _wfindnext64 -#undef _wsystem -#undef _wexcel -#undef _wexcele -#undef _wexelp -#undef _wexelpe -#undef _wexecv -#undef _wexecve -#undef _wexecvp -#undef _wexecvpe -#undef _wpopen -#undef _wputenv -#undef _wspawnl -#undef _wspawnle -#undef _wspawnlp -#undef _wspawnlpe -#undef _wspawnv -#undef _wspawnve -#undef _wspawnvp -#undef _wspawnvpe - -// _wfullpath implementation -wchar_t * __cdecl UnicowsLoader::_wfullpathImpl( - wchar_t * absPath, - const wchar_t * relPath, - size_t maxLength) -{ - if (IS_NT) { - return _wfullpath(absPath, relPath, maxLength); - } else { - wchar_t * ret = NULL; - char * absPathA = (char *)safe_Malloc(maxLength); - char * relPathA = (char *)safe_Malloc(maxLength); - ::WideCharToMultiByte(CP_ACP, 0, relPath, -1, relPathA, - static_cast(maxLength), NULL, NULL); - - char * retA = _fullpath(absPathA, relPathA, maxLength); - - if (retA != NULL) { - ::MultiByteToWideChar(CP_ACP, 0, absPathA, -1, - absPath, static_cast(maxLength)); - ret = absPath; - } - - free(absPathA); - free(relPathA); - - return ret; - } -} diff --git a/jdk/src/windows/native/sun/windows/UnicowsLoader.h b/jdk/src/windows/native/sun/windows/UnicowsLoader.h deleted file mode 100644 index 50c48ca91a2..00000000000 --- a/jdk/src/windows/native/sun/windows/UnicowsLoader.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#ifndef UNICOWSLOADER_H -#define UNICOWSLOADER_H - -#if !defined(UNICODE) || !defined(_UNICODE) -#error UnicowsLoader module needs UNICODE and _UNICODE flags to be set on compiling -#endif - -#include - -// A class to load the Microsoft Layer for Unicode (unicows.dll) -class UnicowsLoader { -public: - // this is called when the client DLL (this case, AWT) is loaded - static HMODULE __stdcall LoadUnicows(void); - - // this is provided to pass the MSLU module handle - static HMODULE GetModuleHandle(void); - - // member functions that implements functions that MSLU does not support - static BOOL __stdcall GetPrinterWImpl(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD); - static BOOL __stdcall EnumPrintersWImpl(DWORD, LPWSTR, DWORD, LPBYTE, - DWORD, LPDWORD, LPDWORD); - - // member functions that implements functions that VC6 CRT does not support - // on Win9x - static wchar_t * __cdecl _wfullpathImpl(wchar_t *, const wchar_t *, size_t); - -private: - // The module handle - static HMODULE hmodUnicows; - - // utility member functions - static void DevModeA2DevModeW(const DEVMODEA *, DEVMODEW *); - static void PrinterInfo1A2W(const LPPRINTER_INFO_1A, LPPRINTER_INFO_1W, const DWORD); - static void PrinterInfo2A2W(const LPPRINTER_INFO_2A, LPPRINTER_INFO_2W, const DWORD); - static void PrinterInfo5A2W(const LPPRINTER_INFO_5A, LPPRINTER_INFO_5W, const DWORD); - static void PrinterInfoA2W(const PVOID, PVOID, DWORD, DWORD); - static void StringA2W(LPCSTR, LPWSTR *, LPWSTR *); -}; - -#ifndef AWT_H -// copied from awt.h -#if defined (WIN32) - #define IS_WIN32 TRUE -#else - #define IS_WIN32 FALSE -#endif -#define IS_NT (IS_WIN32 && !(::GetVersion() & 0x80000000)) -#endif // AWT_H - -// Now the platform encoding is Unicode (UTF-16), re-define JNU_ functions -// to proper JNI functions. -#define JNU_NewStringPlatform(env, x) env->NewString(x, static_cast(_tcslen(x))) -#define JNU_GetStringPlatformChars(env, x, y) (LPWSTR)env->GetStringChars(x, y) -#define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, y) - -// The following Windows W-APIs are not supported by the MSLU. -// You need to implement a stub to use these APIs. Or, if it is -// apparent that the API is used only on WindowsNT/2K/XP, wrap -// the call site with #undef - #define, e.g: -// -// #undef SomeFunctionW -// call SomeFunctionW -// #define SomeFunctionW NotSupportedByMSLU - -#define AcquireCredentialsHandleW NotSupportedByMSLU -#define CreateNamedPipeW NotSupportedByMSLU -#define CryptAcquireContextW NotSupportedByMSLU -#define CryptEnumProvidersW NotSupportedByMSLU -#define CryptEnumProviderTypesW NotSupportedByMSLU -#define CryptGetDefaultProviderW NotSupportedByMSLU -#define CryptSetProviderW NotSupportedByMSLU -#define CryptSetProviderExW NotSupportedByMSLU -#define CryptSignHashW NotSupportedByMSLU -#define CryptVerifySignatureW NotSupportedByMSLU -#define EnumerateSecurityPackagesW NotSupportedByMSLU -#define EnumMonitorsW NotSupportedByMSLU -#define EnumPortsW NotSupportedByMSLU -#define EnumPrinterDriversW NotSupportedByMSLU -//#define EnumPrintersW NotSupportedByMSLU -#define EnumPrintProcessorDatatypesW NotSupportedByMSLU -#define EnumPrintProcessorsW NotSupportedByMSLU -#define FreeContextBufferW NotSupportedByMSLU -#define GetCharABCWidthsFloatW NotSupportedByMSLU -#define GetJobW NotSupportedByMSLU -#define GetOpenFileNamePreviewW NotSupportedByMSLU -//#define GetPrinterW NotSupportedByMSLU -#define GetPrinterDataW NotSupportedByMSLU -#define GetPrinterDriverW NotSupportedByMSLU -#define GetSaveFileNamePreviewW NotSupportedByMSLU -#define InitializeSecurityContextW NotSupportedByMSLU -#define mciSendCommandW NotSupportedByMSLU -#define mixerGetControlDetailsW NotSupportedByMSLU -#define mixerGetLineControlsW NotSupportedByMSLU -#define mixerGetLineInfoW NotSupportedByMSLU -#define mmioInstallIOProcW NotSupportedByMSLU -#define OleUIChangeSourceW NotSupportedByMSLU -#define OleUIConvertW NotSupportedByMSLU -#define OleUIEditLinksW NotSupportedByMSLU -#define OleUIInsertObjectW NotSupportedByMSLU -#define OleUIObjectPropertiesW NotSupportedByMSLU -#define OleUIPasteSpecialW NotSupportedByMSLU -#define OleUIPromptUserW NotSupportedByMSLU -#define OleUIUpdateLinksW NotSupportedByMSLU -#define PolyTextOutW NotSupportedByMSLU -#define QueryContextAttributesW NotSupportedByMSLU -#define QueryCredentialsAttributesW NotSupportedByMSLU -#define QuerySecurityPackageInfoW NotSupportedByMSLU -#define RasDeleteSubEntryW NotSupportedByMSLU -#define RasSetSubEntryPropertiesW NotSupportedByMSLU -#define ResetPrinterW NotSupportedByMSLU - -// The following Shell COM interfaces are not supported by the MSLU. -// See ShellFolder2.cpp -#define IID_IFileViewerW NotSupportedByMSLU -#define IID_IShellLinkW NotSupportedByMSLU -#define IID_IExtractIconW NotSupportedByMSLU -#define IID_IShellCopyHookW NotSupportedByMSLU -#define IID_IShellExecuteHookW NotSupportedByMSLU -#define IID_INewShortcutHookW NotSupportedByMSLU - -// The following CRT functions should fail on compiling, as it does not work on -// Win9x/ME platform. If you need these CRTs, write a wrapper for ANSI version -// equivalents, in which it converts to/from Unicode using WideCharToMultiByte. -// -// Or, if it is apparent that the function is used only on WindowsNT/2K/XP, wrap -// the call site with #undef - #define, e.g: -// -// #undef _wsomefunc -// call _wsomefunc -// #define _wsomefunc NotSupportedOnWin9X - -#define _waccess NotSupportedOnWin9X -#define _wchmod NotSupportedOnWin9X -#define _wfullpath UnicowsLoader::_wfullpathImpl -#define _wremove NotSupportedOnWin9X -#define _wrename NotSupportedOnWin9X -#define _wstat NotSupportedOnWin9X -#define _wstati64 NotSupportedOnWin9X -#define _wstat64 NotSupportedOnWin9X -#define _wunlink NotSupportedOnWin9X -#define _wfopen NotSupportedOnWin9X -#define _wfreopen NotSupportedOnWin9X -#define _wfsopen NotSupportedOnWin9X -#define _wcreat NotSupportedOnWin9X -#define _wopen NotSupportedOnWin9X -#define _wsopen NotSupportedOnWin9X -#define _wfindfirst NotSupportedOnWin9X -#define _wfindfirst64 NotSupportedOnWin9X -#define _wfindnext NotSupportedOnWin9X -#define _wfindnext64 NotSupportedOnWin9X -#define _wsystem NotSupportedOnWin9X -#define _wexcel NotSupportedOnWin9X -#define _wexcele NotSupportedOnWin9X -#define _wexelp NotSupportedOnWin9X -#define _wexelpe NotSupportedOnWin9X -#define _wexecv NotSupportedOnWin9X -#define _wexecve NotSupportedOnWin9X -#define _wexecvp NotSupportedOnWin9X -#define _wexecvpe NotSupportedOnWin9X -#define _wpopen NotSupportedOnWin9X -#define _wputenv NotSupportedOnWin9X -#define _wspawnl NotSupportedOnWin9X -#define _wspawnle NotSupportedOnWin9X -#define _wspawnlp NotSupportedOnWin9X -#define _wspawnlpe NotSupportedOnWin9X -#define _wspawnv NotSupportedOnWin9X -#define _wspawnve NotSupportedOnWin9X -#define _wspawnvp NotSupportedOnWin9X -#define _wspawnvpe NotSupportedOnWin9X - - -#endif // UNICOWSLOADER_H diff --git a/jdk/src/windows/native/sun/windows/WPrinterJob.cpp b/jdk/src/windows/native/sun/windows/WPrinterJob.cpp index 33395e43a49..d64a8e314f2 100644 --- a/jdk/src/windows/native/sun/windows/WPrinterJob.cpp +++ b/jdk/src/windows/native/sun/windows/WPrinterJob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,14 @@ * have any questions. */ +#include "awt.h" + #include "stdhdrs.h" #include #include #include #include -#include "awt.h" -#include "awt_dlls.h" #include "awt_Toolkit.h" #include "awt_PrintControl.h" @@ -74,7 +74,6 @@ Java_sun_print_Win32PrintServiceLookup_getDefaultPrinterName(JNIEnv *env, TRY; TCHAR cBuffer[250]; - BOOL bFlag; OSVERSIONINFO osv; PRINTER_INFO_2 *ppi2 = NULL; DWORD dwNeeded = 0; @@ -86,39 +85,8 @@ Java_sun_print_Win32PrintServiceLookup_getDefaultPrinterName(JNIEnv *env, osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osv); - // If Windows 95 or 98, use EnumPrinters... - if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { - - // The first EnumPrinters() tells you how big our buffer should - // be in order to hold ALL of PRINTER_INFO_2. Note that this will - // usually return FALSE. This only means that the buffer (the 4th - // parameter) was not filled in. You don't want it filled in here... - - EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, - NULL, 0, &dwNeeded, &dwReturned); - if (dwNeeded == 0) { - return NULL; - } - - // Allocate enough space for PRINTER_INFO_2... - ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded); - if (!ppi2) { - return NULL; - } - - // The second EnumPrinters() will fill in all the current information. - bFlag = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, - (LPBYTE)ppi2, dwNeeded, &dwNeeded, &dwReturned); - if (!bFlag) { - GlobalFree(ppi2); - return NULL; - } - - jPrinterName = JNU_NewStringPlatform(env, ppi2->pPrinterName); - GlobalFree(ppi2); - return jPrinterName; - - } else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) { + // If Windows 2000, XP, Vista + if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) { // Retrieve the default string from Win.ini (the registry). // String will be in form "printername,drivername,portname". @@ -165,62 +133,32 @@ Java_sun_print_Win32PrintServiceLookup_getAllPrinterNames(JNIEnv *env, jobjectArray nameArray; try { - if (IS_NT) { - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - NULL, 4, NULL, 0, &cbNeeded, &cReturned); - pPrinterEnum = new BYTE[cbNeeded]; - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded, - &cReturned); + ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + NULL, 4, NULL, 0, &cbNeeded, &cReturned); + pPrinterEnum = new BYTE[cbNeeded]; + ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded, + &cReturned); - if (cReturned > 0) { - nameArray = env->NewObjectArray(cReturned, clazz, NULL); - if (nameArray == NULL) { - throw std::bad_alloc(); - } - } else { - nameArray = NULL; - } - - - for (DWORD i = 0; i < cReturned; i++) { - PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) - (pPrinterEnum + i * sizeof(PRINTER_INFO_4)); - utf_str = JNU_NewStringPlatform(env, info4->pPrinterName); - if (utf_str == NULL) { - throw std::bad_alloc(); - } - env->SetObjectArrayElement(nameArray, i, utf_str); - env->DeleteLocalRef(utf_str); + if (cReturned > 0) { + nameArray = env->NewObjectArray(cReturned, clazz, NULL); + if (nameArray == NULL) { + throw std::bad_alloc(); } } else { - ::EnumPrinters(PRINTER_ENUM_LOCAL, - NULL, 5, NULL, 0, &cbNeeded, &cReturned); - pPrinterEnum = new BYTE[cbNeeded]; - ::EnumPrinters(PRINTER_ENUM_LOCAL, - NULL, 5, pPrinterEnum, cbNeeded, &cbNeeded, - &cReturned); + nameArray = NULL; + } - if (cReturned > 0) { - nameArray = env->NewObjectArray(cReturned, clazz, NULL); - if (nameArray == NULL) { - throw std::bad_alloc(); - } - } else { - nameArray = NULL; - } - - - for (DWORD i = 0; i < cReturned; i++) { - PRINTER_INFO_5 *info5 = (PRINTER_INFO_5 *) - (pPrinterEnum + i * sizeof(PRINTER_INFO_5)); - utf_str = JNU_NewStringPlatform(env, info5->pPrinterName); - if (utf_str == NULL) { - throw std::bad_alloc(); - } - env->SetObjectArrayElement(nameArray, i, utf_str); - env->DeleteLocalRef(utf_str); + + for (DWORD i = 0; i < cReturned; i++) { + PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) + (pPrinterEnum + i * sizeof(PRINTER_INFO_4)); + utf_str = JNU_NewStringPlatform(env, info4->pPrinterName); + if (utf_str == NULL) { + throw std::bad_alloc(); } + env->SetObjectArrayElement(nameArray, i, utf_str); + env->DeleteLocalRef(utf_str); } } catch (std::bad_alloc&) { delete [] pPrinterEnum; @@ -872,7 +810,7 @@ Java_sun_print_Win32PrintService_getDefaultSettings(JNIEnv *env, int numSizes = ::DeviceCapabilities(printerName, printerPort, DC_PAPERS, NULL, NULL); if (numSizes > 0) { - LPWORD papers = (LPWORD)safe_Malloc(numSizes * sizeof(WORD)); + LPTSTR papers = (LPTSTR)safe_Malloc(numSizes * sizeof(WORD)); if (papers != NULL && ::DeviceCapabilities(printerName, printerPort, DC_PAPERS, papers, NULL) != -1) { diff --git a/jdk/src/windows/native/sun/windows/awt.h b/jdk/src/windows/native/sun/windows/awt.h index 389aba67db3..cd4791fd257 100644 --- a/jdk/src/windows/native/sun/windows/awt.h +++ b/jdk/src/windows/native/sun/windows/awt.h @@ -26,10 +26,21 @@ #ifndef _AWT_H_ #define _AWT_H_ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif + +#ifndef _WIN32_IE +#define _WIN32_IE 0x0600 +#endif + +//#ifndef NTDDI_VERSION +//#define NTDDI_VERSION NTDDI_LONGHORN +//#endif + #include "stdhdrs.h" #include "alloc.h" #include "awt_Debug.h" -#include "UnicowsLoader.h" extern COLORREF DesktopColor2RGB(int colorIndex); @@ -129,40 +140,23 @@ typedef AwtObject* PDATA; /* /NEW JNI */ /* - * IS_NT returns TRUE on NT, 2000, XP - * IS_WIN2000 returns TRUE on 2000, XP - * IS_WINXP returns TRUE on XP - * IS_WIN95 returns TRUE on 95, 98, ME - * IS_WIN98 returns TRUE on 98, ME - * IS_WINME returns TRUE on ME - * IS_WIN32 returns TRUE on 32-bit Pentium and - * 64-bit Itanium. * IS_WIN64 returns TRUE on 64-bit Itanium - * - * uname -s returns Windows_95 on 95 - * uname -s returns Windows_98 on 98 and ME - * uname -s returns Windows_NT on NT and 2000 and XP */ -#if defined (WIN32) - #define IS_WIN32 TRUE -#else - #define IS_WIN32 FALSE -#endif #if defined (_WIN64) #define IS_WIN64 TRUE #else #define IS_WIN64 FALSE #endif -#define IS_NT (IS_WIN32 && !(::GetVersion() & 0x80000000)) -#define IS_WIN2000 (IS_NT && LOBYTE(LOWORD(::GetVersion())) >= 5) -#define IS_WIN2003 (IS_NT && LOBYTE(LOWORD(::GetVersion())) == 5 && HIBYTE(LOWORD(::GetVersion())) >= 2) -#define IS_WINXP (IS_NT && (IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5) -#define IS_WINVISTA (IS_NT && LOBYTE(LOWORD(::GetVersion())) >= 6) -#define IS_WIN32S (IS_WIN32 && !IS_NT && LOBYTE(LOWORD(::GetVersion())) < 4) -#define IS_WIN95 (IS_WIN32 && !IS_NT && LOBYTE(LOWORD(::GetVersion())) >= 4) -#define IS_WIN98 (IS_WIN95 && HIBYTE(LOWORD(::GetVersion())) >= 10) -#define IS_WINME (IS_WIN95 && HIBYTE(LOWORD(::GetVersion())) >= 90) -#define IS_WIN4X (IS_WIN32 && LOBYTE(::GetVersion()) >= 4) + +/* + * IS_WIN2000 returns TRUE on 2000, XP and Vista + * IS_WINXP returns TRUE on XP and Vista + * IS_WINVISTA returns TRUE on Vista + */ +#define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5) +#define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5) +#define IS_WINVISTA (LOBYTE(LOWORD(::GetVersion())) >= 6) + #define IS_WINVER_ATLEAST(maj, min) \ ((maj) < LOBYTE(LOWORD(::GetVersion())) || \ (maj) == LOBYTE(LOWORD(::GetVersion())) && \ @@ -177,6 +171,12 @@ typedef AwtObject* PDATA; extern JavaVM *jvm; +// Platform encoding is Unicode (UTF-16), re-define JNU_ functions +// to proper JNI functions. +#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast(x), static_cast(_tcslen(x))) +#define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast(env->GetStringChars(x, y)) +#define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast(y)) + /* * Itanium symbols needed for 64-bit compilation. * These are defined in winuser.h in the August 2001 MSDN update. @@ -211,17 +211,12 @@ extern JavaVM *jvm; * NOTE: float.h must be defined if using these macros */ #define SAVE_CONTROLWORD \ - unsigned int fpu_cw = _CW_DEFAULT; \ - if (IS_WIN95) { \ - fpu_cw = _control87(0, 0); \ - } + unsigned int fpu_cw = _control87(0, 0); -#define RESTORE_CONTROLWORD \ - if (IS_WIN95) { \ - if ( _control87(0, 0) != fpu_cw) { \ - _control87(fpu_cw, 0xfffff); \ - } \ - } +#define RESTORE_CONTROLWORD \ + if (_control87(0, 0) != fpu_cw) { \ + _control87(fpu_cw, 0xffffffff); \ + } /* * checks if the current thread is/isn't the toolkit thread diff --git a/jdk/src/windows/native/sun/windows/awt_Button.cpp b/jdk/src/windows/native/sun/windows/awt_Button.cpp index e4895915df0..3764655cba4 100644 --- a/jdk/src/windows/native/sun/windows/awt_Button.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Button.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * have any questions. */ -#include +#include "awt.h" #include "awt_Object.h" /* wop_pDataID */ #include "awt_Toolkit.h" @@ -106,7 +106,7 @@ AwtButton* AwtButton::Create(jobject self, jobject parent) if (label == NULL) { labelStr = L""; } else { - labelStr = env->GetStringChars(label, JNI_FALSE); + labelStr = JNU_GetStringPlatformChars(env, label, JNI_FALSE); } style = 0; @@ -128,7 +128,7 @@ AwtButton* AwtButton::Create(jobject self, jobject parent) c->m_backgroundColorSet = TRUE; // suppress inheriting parent's color c->UpdateBackground(env, target); if (label != NULL) - env->ReleaseStringChars(label, labelStr); + JNU_ReleaseStringPlatformChars(env, label, labelStr); } catch (...) { env->DeleteLocalRef(target); if (label != NULL) diff --git a/jdk/src/windows/native/sun/windows/awt_Checkbox.cpp b/jdk/src/windows/native/sun/windows/awt_Checkbox.cpp index b0a73679d0b..2e8cf9923db 100644 --- a/jdk/src/windows/native/sun/windows/awt_Checkbox.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Checkbox.cpp @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include "awt_Toolkit.h" #include "awt_Checkbox.h" #include "awt_KeyboardFocusManager.h" @@ -106,7 +107,7 @@ AwtCheckbox* AwtCheckbox::Create(jobject peer, jobject parent) label = (jstring)env->GetObjectField(target, AwtCheckbox::labelID); if (label != NULL) { - labelStr = env->GetStringChars(label, 0); + labelStr = JNU_GetStringPlatformChars(env, label, 0); } if (labelStr != 0) { jint x = env->GetIntField(target, AwtComponent::xID); @@ -123,7 +124,7 @@ AwtCheckbox* AwtCheckbox::Create(jobject peer, jobject parent) peer); if (labelStr != defaultLabelStr) { - env->ReleaseStringChars(label, labelStr); + JNU_ReleaseStringPlatformChars(env, label, labelStr); } } else { throw std::bad_alloc(); diff --git a/jdk/src/windows/native/sun/windows/awt_Choice.cpp b/jdk/src/windows/native/sun/windows/awt_Choice.cpp index 27145ea6e6c..ca7adb0ed6e 100644 --- a/jdk/src/windows/native/sun/windows/awt_Choice.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Choice.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -206,7 +206,7 @@ int AwtChoice::GetFieldHeight() fieldHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)-1, 0); // add top and bottom border lines; border size is different for // Win 4.x (3d edge) vs 3.x (1 pixel line) - borderHeight = ::GetSystemMetrics(IS_WIN4X ? SM_CYEDGE : SM_CYBORDER); + borderHeight = ::GetSystemMetrics(SM_CYEDGE); fieldHeight += borderHeight*2; return fieldHeight; } @@ -424,6 +424,9 @@ AwtChoice::WmKillFocus(HWND hWndGotFocus) case mrPassAlong: return AwtComponent::WmKillFocus(hWndGotFocus); } + + DASSERT(false); // must never reach here + return mrDoDefault; } MsgRouting diff --git a/jdk/src/windows/native/sun/windows/awt_Color.cpp b/jdk/src/windows/native/sun/windows/awt_Color.cpp index b1c6cb90548..bc9b2f13f32 100644 --- a/jdk/src/windows/native/sun/windows/awt_Color.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Color.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,7 @@ Java_sun_awt_windows_WColor_getDefaultColor(JNIEnv *env, jclass cls, iColor = COLOR_MENUTEXT; break; case sun_awt_windows_WColor_BUTTON_BKGND: - iColor = (IS_NT) ? COLOR_BTNFACE : COLOR_3DFACE; + iColor = COLOR_BTNFACE; break; case sun_awt_windows_WColor_BUTTON_TEXT: iColor = COLOR_BTNTEXT; diff --git a/jdk/src/windows/native/sun/windows/awt_Component.cpp b/jdk/src/windows/native/sun/windows/awt_Component.cpp index 5b017c97810..6f0df2e449f 100644 --- a/jdk/src/windows/native/sun/windows/awt_Component.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp @@ -23,7 +23,8 @@ * have any questions. */ -#include "windows.h" +#include "awt.h" + #include #include @@ -42,7 +43,6 @@ #include "awt_MouseEvent.h" #include "awt_Palette.h" #include "awt_Toolkit.h" -#include "awt_Unicode.h" #include "awt_Window.h" #include "awt_Win32GraphicsDevice.h" #include "Hashtable.h" @@ -67,30 +67,10 @@ #include // Begin -- Win32 SDK include files -#include #include #include // End -- Win32 SDK include files -#ifndef GET_KEYSTATE_WPARAM // defined for (_WIN32_WINNT >= 0x0400) -#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) -#endif - -#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500) -#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam)) -#endif - -// -#if !defined(__int3264) -#define GetWindowLongPtr GetWindowLong -#define SetWindowLongPtr SetWindowLong -#define GWLP_USERDATA GWL_USERDATA -#define GWLP_WNDPROC GWL_WNDPROC -typedef __int32 LONG_PTR; -typedef unsigned __int32 ULONG_PTR; -#endif // __int3264 -// - #include LPCTSTR szAwtComponentClassName = TEXT("SunAwtComponent"); @@ -207,9 +187,7 @@ LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0)); UINT AwtComponent::m_CodePage = AwtComponent::LangToCodePage(m_idLang); -BOOL AwtComponent::m_isWin95 = IS_WIN95; -BOOL AwtComponent::m_isWin2000 = IS_WIN2000; -BOOL AwtComponent::m_isWinNT = IS_NT; +jint *AwtComponent::masks; static BOOL bLeftShiftIsDown = false; static BOOL bRightShiftIsDown = false; @@ -544,7 +522,7 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title, jobject createError = NULL; if (dw == ERROR_OUTOFMEMORY) { - jstring errorMsg = env->NewStringUTF("too many window handles"); + jstring errorMsg = JNU_NewStringPlatform(env, L"too many window handles"); createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "(Ljava/lang/String;)V", errorMsg); @@ -1201,6 +1179,9 @@ void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) { WIN_MSG(WM_MBUTTONDOWN) WIN_MSG(WM_MBUTTONUP) WIN_MSG(WM_MBUTTONDBLCLK) + WIN_MSG(WM_XBUTTONDBLCLK) + WIN_MSG(WM_XBUTTONDOWN) + WIN_MSG(WM_XBUTTONUP) WIN_MSG(WM_MOUSEWHEEL) WIN_MSG(WM_PARENTNOTIFY) WIN_MSG(WM_ENTERMENULOOP) @@ -1347,17 +1328,9 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) return (LRESULT)TRUE; } - UINT switchMessage; - if (IS_WIN95 && !IS_WIN98 && message == Wheel95GetMsg()) { - // Wheel message is generated dynamically on 95. A quick swap and - // we're good to go. - DTRACE_PRINTLN1("got wheel event on 95. msg is %i\n", message); - switchMessage = WM_MOUSEWHEEL; - } - else { - switchMessage = message; - } + DWORD curPos = 0; + UINT switchMessage = message; switch (switchMessage) { case WM_AWT_GETDC: { @@ -1644,67 +1617,87 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP: + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: case WM_MOUSEMOVE: case WM_MOUSEWHEEL: case WM_AWT_MOUSEENTER: case WM_AWT_MOUSEEXIT: - { - DWORD curPos = ::GetMessagePos(); + curPos = ::GetMessagePos(); POINT myPos; myPos.x = GET_X_LPARAM(curPos); myPos.y = GET_Y_LPARAM(curPos); ::ScreenToClient(GetHWnd(), &myPos); switch(switchMessage) { case WM_AWT_MOUSEENTER: - mr = WmMouseEnter(static_cast(wParam), myPos.x, myPos.y); break; + mr = WmMouseEnter(static_cast(wParam), myPos.x, myPos.y); + break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: - mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, - LEFT_BUTTON); break; - case WM_LBUTTONUP: - mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, - LEFT_BUTTON); break; - case WM_MOUSEMOVE: - mr = WmMouseMove(static_cast(wParam), myPos.x, myPos.y); break; - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, - MIDDLE_BUTTON); break; - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, - RIGHT_BUTTON); break; - case WM_RBUTTONUP: - mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, - RIGHT_BUTTON); - break; - case WM_MBUTTONUP: - mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, - MIDDLE_BUTTON); - break; - case WM_AWT_MOUSEEXIT: - mr = WmMouseExit(static_cast(wParam), myPos.x, myPos.y); - break; - case WM_MOUSEWHEEL: - if (IS_WIN95 && !IS_WIN98) { - // On 95, the wParam doesn't contain the keystate flags, just - // the wheel rotation. The keystates are fetched in WmMouseWheel - // using GetJavaModifiers(). - mr = WmMouseWheel(0, - GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), - (int)wParam); - return FALSE; - } - else { + mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, + LEFT_BUTTON); + break; + case WM_LBUTTONUP: + mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, + LEFT_BUTTON); + break; + case WM_MOUSEMOVE: + mr = WmMouseMove(static_cast(wParam), myPos.x, myPos.y); + break; + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, + MIDDLE_BUTTON); + break; + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { + if (HIWORD(wParam) == 1) { + mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, + X1_BUTTON); + } + if (HIWORD(wParam) == 2) { + mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, + X2_BUTTON); + } + } + break; + case WM_XBUTTONUP: + if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { + if (HIWORD(wParam) == 1) { + mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, + X1_BUTTON); + } + if (HIWORD(wParam) == 2) { + mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, + X2_BUTTON); + } + } + break; + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + mr = WmMouseDown(static_cast(wParam), myPos.x, myPos.y, + RIGHT_BUTTON); + break; + case WM_RBUTTONUP: + mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, + RIGHT_BUTTON); + break; + case WM_MBUTTONUP: + mr = WmMouseUp(static_cast(wParam), myPos.x, myPos.y, + MIDDLE_BUTTON); + break; + case WM_AWT_MOUSEEXIT: + mr = WmMouseExit(static_cast(wParam), myPos.x, myPos.y); + break; + case WM_MOUSEWHEEL: mr = WmMouseWheel(GET_KEYSTATE_WPARAM(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), GET_WHEEL_DELTA_WPARAM(wParam)); + break; } break; - } - } - break; - case WM_SETCURSOR: mr = mrDoDefault; if (LOWORD(lParam) == HTCLIENT) { @@ -2589,8 +2582,12 @@ MsgRouting AwtComponent::WmMouseMove(UINT flags, int x, int y) lastComp = this; lastX = x; lastY = y; - - if ( (flags & ALL_MK_BUTTONS) != 0 ) { + BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled(); + if (((flags & (ALL_MK_BUTTONS)) != 0) || + (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0)) +// if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) || +// ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) )) + { // 6404008 : if Dragged event fired we shouldn't fire // Clicked event: m_firstDragSent set to TRUE. // This is a partial backout of 5039416 fix. @@ -2649,21 +2646,10 @@ MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y, jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA); MSG msg; - - if (IS_WIN95 && !IS_WIN98) { - // 95 doesn't understand the SPI_GETWHEELSCROLLLINES - get the user - // preference by other means - DTRACE_PRINTLN("WmMouseWheel: using 95 branch"); - platformLines = Wheel95GetScrLines(); - result = true; - InitMessage(&msg, lastMessage, wheelRotation, MAKELPARAM(x, y)); - } - else { - result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, - &platformLines, 0); - InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation), - MAKELPARAM(x, y)); - } + result = ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, + &platformLines, 0); + InitMessage(&msg, lastMessage, MAKEWPARAM(flags, wheelRotation), + MAKELPARAM(x, y)); if (result) { if (platformLines == WHEEL_PAGESCROLL) { @@ -2743,156 +2729,21 @@ jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags) "AwtComponent::GetShiftKeyLocation vkey = %d = 0x%x scan = %d", vkey, vkey, keyScanCode); - if (m_isWinNT) { - leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0); - rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0); + leftShiftScancode = ::MapVirtualKey(VK_LSHIFT, 0); + rightShiftScancode = ::MapVirtualKey(VK_RSHIFT, 0); - if (keyScanCode == leftShiftScancode) { - return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } - if (keyScanCode == rightShiftScancode) { - return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } - - DASSERT(false); - // Note: the above should not fail on NT (or 2000), - // but just in case it does, try the more complicated method - // we use for Win9x below. + if (keyScanCode == leftShiftScancode) { + return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; + } + if (keyScanCode == rightShiftScancode) { + return java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; } - // "Transition" bit = 0 if keyPressed, 1 if keyReleased - BOOL released = ((1<<15) & flags); + DASSERT(false); + // Note: the above should not fail on NT (or 2000) - DTRACE_PRINTLN2( - "AwtComponent::GetShiftKeyLocation bLeftShiftIsDown = %d bRightShiftIsDown == %d", - bLeftShiftIsDown, bRightShiftIsDown); - DTRACE_PRINTLN2( - "AwtComponent::GetShiftKeyLocation lastShiftKeyPressed = %d released = %d", - lastShiftKeyPressed, released); - - jint keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN; - - // It is possible for somebody to hold down one or both - // Shift keys, causing repeat key events. We need to - // handle all the cases. - // - // Just a side-note: if two or more keys are being held down, - // and then one key is released, whether more key presses are - // generated for the keys that are still held down depends on - // which keys they are, and whether you released the right or - // the left shift/ctrl/etc. key first. This also differs - // between Win9x and NT. Just plain screwy. - // - // Note: on my PC, the repeat count is always 1. Yup, we need - // 16 bits to handle that, all right. - - // Handle the case where only one of the Shift keys - // was down before this event took place - if (bLeftShiftIsDown && !bRightShiftIsDown) { - if (released) { - // This is a left Shift release - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } else { - // This is a right Shift press - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } - } else if (!bLeftShiftIsDown && bRightShiftIsDown) { - if (released) { - // This is a right Shift release - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } else { - // This is a left Shift press - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } - } - - // Handle the case where neither of the Shift keys - // were down before this event took place - if (!bLeftShiftIsDown && !bRightShiftIsDown) { - DASSERT(!released); - if (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) { - // This is a left Shift press - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } else if (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) { - // This is a right Shift press - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } else { - DASSERT(false); - } - } - - // Handle the case where both Shift keys were down before - // this event took place - if (bLeftShiftIsDown && bRightShiftIsDown) { - // If this is a key release event, we can just check to see - // what the keyboard state is after the event - if (released) { - if (HIBYTE(::GetKeyState(VK_RSHIFT)) == 0) { - // This is a right Shift release - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } else if (HIBYTE(::GetKeyState(VK_LSHIFT)) == 0) { - // This is a left Shift release - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } else { - DASSERT(false); - } - } else { - // If this is a key press event, and both Shift keys were - // already down, this is going to be a repeat of the last - // Shift press - if (lastShiftKeyPressed == VK_LSHIFT) { - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } else if (lastShiftKeyPressed == VK_RSHIFT) { - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } else { - DASSERT(false); - } - } - } - - if (keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN) { - // Nothing we tried above worked for some reason. Sigh. - // Make a last-ditch effort to guess what happened: - // guess that the Shift scancodes are usually the same - // from system to system, even though this isn't guaranteed. - DTRACE_PRINTLN("Last-ditch effort at guessing Shift keyLocation"); - - // Tested on a couple of Windows keyboards: these are standard values - leftShiftScancode = 42; - rightShiftScancode = 54; - - if (keyScanCode == leftShiftScancode) { - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_LEFT; - } else if (keyScanCode == rightShiftScancode) { - keyLocation = java_awt_event_KeyEvent_KEY_LOCATION_RIGHT; - } - } - - // Set the Shift flags with the new key state. - bLeftShiftIsDown = (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0); - bRightShiftIsDown = (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0); - - // Update lastShiftKeyPressed - if (released) { - // At most one shift key is down now, so just check which one - if (bLeftShiftIsDown) { - lastShiftKeyPressed = VK_LSHIFT; - DASSERT(!bRightShiftIsDown); - } else if (bRightShiftIsDown) { - lastShiftKeyPressed = VK_RSHIFT; - } else { - lastShiftKeyPressed = 0; - } - } else { - // It was a press, so at least one shift key is down now - if (keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_LEFT) { - lastShiftKeyPressed = VK_LSHIFT; - } else if (keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_RIGHT) { - lastShiftKeyPressed = VK_RSHIFT; - } - } - - return keyLocation; + // default value + return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; } /* Returns Java extended InputEvent modifieres. @@ -2914,7 +2765,7 @@ AwtComponent::GetJavaModifiers() modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK; } if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) { - modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; + modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; } if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) { modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK; @@ -2922,6 +2773,13 @@ AwtComponent::GetJavaModifiers() if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) { modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK; } + + if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) { + modifiers |= masks[3]; + } + if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) { + modifiers |= masks[4]; + } return modifiers; } @@ -2936,6 +2794,11 @@ AwtComponent::GetButton(int mouseButton) return java_awt_event_MouseEvent_BUTTON2; case RIGHT_BUTTON: return java_awt_event_MouseEvent_BUTTON3; + case X1_BUTTON: //16 : + //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now + return 4; + case X2_BUTTON: //32 + return 5; } return java_awt_event_MouseEvent_NOBUTTON; } @@ -2950,6 +2813,10 @@ AwtComponent::GetButtonMK(int mouseButton) return MK_MBUTTON; case RIGHT_BUTTON: return MK_RBUTTON; + case X1_BUTTON: + return MK_XBUTTON1; + case X2_BUTTON: + return MK_XBUTTON2; } return 0; } @@ -2967,6 +2834,14 @@ AwtComponent::GetButtonMK(int mouseButton) #define VK_NONCONVERT 0x1D #endif +#ifndef VK_XBUTTON1 +#define VK_XBUTTON1 0x05 +#endif + +#ifndef VK_XBUTTON2 +#define VK_XBUTTON2 0x06 +#endif + typedef struct { UINT javaKey; UINT windowsKey; @@ -3786,22 +3661,6 @@ MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags, // via WM_AWT_FORWARD_BYTE, but the Edit classes don't seem to // like that. - // Begin pollution - if (!m_isWinNT && IsDBCSLeadByteEx(GetCodePage(), BYTE(character))) { - if (GetDBCSEditHandle() != NULL) { - return mrDoDefault; - } else { - // Kludge: Some Chinese IMEs, e.g. QuanPin, sends two WM_CHAR - // messages for some punctuations (e.g. full stop) without sending - // WM_IME_CHAR message beforehand. - if (m_PendingLeadByte == 0) { - m_PendingLeadByte = character; - return mrConsume; - } - } - } - // End pollution - // We will simply create Java events here. UINT message = system ? WM_SYSCHAR : WM_CHAR; @@ -3861,43 +3720,8 @@ MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags, MsgRouting AwtComponent::WmForwardChar(WCHAR character, LPARAM lParam, BOOL synthetic) { - if (m_isWinNT) { - // just post WM_CHAR with unicode key value - DefWindowProc(WM_CHAR, (WPARAM)character, lParam); - return mrConsume; - } - - // This message is sent from the Java key event handler. - CHAR mbChar[2] = {'\0', '\0'}; - - int cBytes = ::WideCharToMultiByte(GetCodePage(), 0, &character, 1, mbChar, 2, NULL, NULL); - if (cBytes!=1 && cBytes!=2) return mrConsume; - - HWND hDBCSEditHandle = GetDBCSEditHandle(); - - if (hDBCSEditHandle != NULL && cBytes==2) - { - // The first WM_CHAR message will get handled by the WmChar, but - // the second WM_CHAR message will get picked off by the Edit class. - // WmChar will never see it. - // If an Edit class gets a lead byte, it immediately calls PeekMessage - // and pulls the trail byte out of the message queue. - ::PostMessage(hDBCSEditHandle, WM_CHAR, mbChar[0] & 0x00ff, lParam); - ::PostMessage(hDBCSEditHandle, WM_CHAR, mbChar[1] & 0x00ff, lParam); - } - else - { - MSG* pMsg; - pMsg = CreateMessage(WM_CHAR, mbChar[0] & 0x00ff, lParam); - ::PostMessage(GetHWnd(), WM_AWT_FORWARD_BYTE, (WPARAM)synthetic, - (LPARAM)pMsg); - if (mbChar[1]) - { - pMsg = CreateMessage(WM_CHAR, mbChar[1] & 0x00ff, lParam); - ::PostMessage(GetHWnd(), WM_AWT_FORWARD_BYTE, (WPARAM)synthetic, - (LPARAM)pMsg); - } - } + // just post WM_CHAR with unicode key value + DefWindowProc(WM_CHAR, (WPARAM)character, lParam); return mrConsume; } @@ -3929,7 +3753,7 @@ void AwtComponent::OpenCandidateWindow(int x, int y) SetCandidateWindow(iCandType, x-rc.left, y-rc.top); } if (m_bitsCandType != 0) { - DefWindowProc(WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType); + ::DefWindowProc(GetHWnd(), WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType); } } @@ -4543,7 +4367,7 @@ MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags) // Special case for components with a sunken border. Windows does not // print the border correctly on PCL printers, so we have to do it ourselves. - if (IS_WIN4X && (GetStyleEx() & WS_EX_CLIENTEDGE)) { + if (GetStyleEx() & WS_EX_CLIENTEDGE) { RECT r; VERIFY(::GetWindowRect(GetHWnd(), &r)); VERIFY(::OffsetRect(&r, -r.left, -r.top)); @@ -4559,7 +4383,7 @@ MsgRouting AwtComponent::WmPrint(HDC hDC, LPARAM flags) * We will first print the non-client area with the original offset, * then the client area with a corrected offset. */ - if (IS_WIN4X && (GetStyleEx() & WS_EX_CLIENTEDGE)) { + if (GetStyleEx() & WS_EX_CLIENTEDGE) { int nEdgeWidth = ::GetSystemMetrics(SM_CXEDGE); int nEdgeHeight = ::GetSystemMetrics(SM_CYEDGE); @@ -5305,7 +5129,12 @@ void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) { wLow |= MK_MBUTTON; } - + if (modifiers & X1_BUTTON) { + wLow |= GetButtonMK(X1_BUTTON); + } + if (modifiers & X2_BUTTON) { + wLow |= GetButtonMK(X2_BUTTON); + } wheelAmt = (jint)JNU_CallMethodByName(env, NULL, @@ -5319,18 +5148,8 @@ void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) // convert Java wheel amount value to Win32 wheelAmt *= -1 * WHEEL_DELTA; - if (IS_WIN95 && !IS_WIN98) { - // 95 doesn't understand WM_MOUSEWHEEL, so plug in value of - // mouse wheel event on 95 - DTRACE_PRINTLN("awt_C::synthmm - 95 case"); - DASSERT(Wheel95GetMsg() != NULL); - message = Wheel95GetMsg(); - wParam = wheelAmt; - } - else { - message = WM_MOUSEWHEEL; - wParam = MAKEWPARAM(wLow, wheelAmt); - } + message = WM_MOUSEWHEEL; + wParam = MAKEWPARAM(wLow, wheelAmt); break; default: @@ -5445,45 +5264,6 @@ void AwtComponent::Enable(BOOL bEnable) VerifyState(); } -/* Initialization of MouseWheel support on Windows 95 */ -void AwtComponent::Wheel95Init() { - DASSERT(IS_WIN95 && !IS_WIN98); - - HWND mwHWND = NULL; - UINT wheelMSG = WM_NULL; - UINT suppMSG = WM_NULL; - UINT linesMSG = WM_NULL; - BOOL wheelActive; - INT lines; - - mwHWND = HwndMSWheel(&wheelMSG, &suppMSG, &linesMSG, &wheelActive, &lines); - if (mwHWND != WM_NULL) { - sm_95WheelMessage = wheelMSG; - sm_95WheelSupport = suppMSG; - } -} - -/* Win95 only - * Return the user's preferred number of lines of test to scroll when the - * mouse wheel is rotated. - */ -UINT AwtComponent::Wheel95GetScrLines() { - DASSERT(IS_WIN95 && !IS_WIN98); - DASSERT(sm_95WheelSupport != NULL); - - HWND mwHWND = NULL; - UINT linesMSG = WM_NULL; - INT numLines = 3; - - linesMSG = RegisterWindowMessage(MSH_SCROLL_LINES); - mwHWND = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); - - if (mwHWND && linesMSG) { - numLines = (INT)::SendMessage(mwHWND, linesMSG, 0, 0); - } - return numLines; -} - /* * associate an AwtDropTarget with this AwtComponent */ @@ -5983,7 +5763,7 @@ void AwtComponent::_SetFont(void *param) { AwtFont *awtFont = (AwtFont *)env->GetLongField(font, AwtFont::pDataID); if (awtFont == NULL) { - /*arguments of AwtFont::Create are changed for multifont component */ + /*arguments of AwtFont::Create are changed for multifont component */ awtFont = AwtFont::Create(env, font); } env->SetLongField(font, AwtFont::pDataID, (jlong)awtFont); @@ -6334,30 +6114,36 @@ void AwtComponent::_SetRectangularShape(void *param) c = (AwtComponent *)pData; if (::IsWindow(c->GetHWnd())) { - RGNDATA *pRgnData = NULL; - RGNDATAHEADER *pRgnHdr; + HRGN hRgn = NULL; - /* reserving memory for the worst case */ - size_t worstBufferSize = size_t(((x2 - x1) / 2 + 1) * (y2 - y1)); - pRgnData = (RGNDATA *) safe_Malloc(sizeof(RGNDATAHEADER) + - sizeof(RECT_T) * worstBufferSize); - pRgnHdr = (RGNDATAHEADER *) pRgnData; + if (region || x1 || x2 || y1 || y2) { + // If all the params are zeros, the shape must be simply reset. + // Otherwise, convert it into a region. + RGNDATA *pRgnData = NULL; + RGNDATAHEADER *pRgnHdr; - pRgnHdr->dwSize = sizeof(RGNDATAHEADER); - pRgnHdr->iType = RDH_RECTANGLES; - pRgnHdr->nRgnSize = 0; - pRgnHdr->rcBound.top = 0; - pRgnHdr->rcBound.left = 0; - pRgnHdr->rcBound.bottom = LONG(y2 - y1); - pRgnHdr->rcBound.right = LONG(x2 - x1); + /* reserving memory for the worst case */ + size_t worstBufferSize = size_t(((x2 - x1) / 2 + 1) * (y2 - y1)); + pRgnData = (RGNDATA *) safe_Malloc(sizeof(RGNDATAHEADER) + + sizeof(RECT_T) * worstBufferSize); + pRgnHdr = (RGNDATAHEADER *) pRgnData; - RECT_T * pRect = (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)); - pRgnHdr->nCount = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, &pRect, worstBufferSize); + pRgnHdr->dwSize = sizeof(RGNDATAHEADER); + pRgnHdr->iType = RDH_RECTANGLES; + pRgnHdr->nRgnSize = 0; + pRgnHdr->rcBound.top = 0; + pRgnHdr->rcBound.left = 0; + pRgnHdr->rcBound.bottom = LONG(y2 - y1); + pRgnHdr->rcBound.right = LONG(x2 - x1); - HRGN hRgn = ::ExtCreateRegion(NULL, - sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData); + RECT_T * pRect = (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)); + pRgnHdr->nCount = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, &pRect, worstBufferSize); - free(pRgnData); + hRgn = ::ExtCreateRegion(NULL, + sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, pRgnData); + + free(pRgnData); + } ::SetWindowRgn(c->GetHWnd(), hRgn, TRUE); } @@ -6451,6 +6237,18 @@ JNIEXPORT void JNICALL Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) { TRY; + jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent"); + jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I"); + jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID); + jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE); + + jsize len = env->GetArrayLength(obj); + AwtComponent::masks = new jint[len]; + for (int i = 0; i < len; i++) { + AwtComponent::masks[i] = tmp[i]; + } + env->ReleaseIntArrayElements(obj, tmp, 0); + env->DeleteLocalRef(obj); /* class ids */ jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer"); @@ -7025,20 +6823,6 @@ Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env, CATCH_BAD_ALLOC_RET(NULL); } -/* - * Class: sun_awt_windows_WComponentPeer - * Method: wheelInit - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_sun_awt_windows_WComponentPeer_wheelInit(JNIEnv *env, jclass cls) -{ - // Only necessary on Win95 - if (IS_WIN95 && !IS_WIN98) { - AwtComponent::Wheel95Init(); - } -} - JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WComponentPeer_processSynchronousLightweightTransfer(JNIEnv *env, jclass cls, jobject heavyweight, @@ -7217,7 +7001,9 @@ void AwtComponent::VerifyState() "getName", "()Ljava/lang/String;").l; DASSERT(!safe_ExceptionOccurred(env)); - printf("\t%S\n", TO_WSTRING(targetStr)); + LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL); + printf("\t%S\n", targetStrW); + JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW); } printf("\twas: [%d,%d,%dx%d]\n", x, y, width, height); if (!fSizeValid) { diff --git a/jdk/src/windows/native/sun/windows/awt_Component.h b/jdk/src/windows/native/sun/windows/awt_Component.h index f73980c28b4..0c18961ed49 100644 --- a/jdk/src/windows/native/sun/windows/awt_Component.h +++ b/jdk/src/windows/native/sun/windows/awt_Component.h @@ -53,6 +53,22 @@ const UINT MAX_ACP_STR_LEN = 7; // ANSI CP identifiers are no longer than this #define MIDDLE_BUTTON 2 #define RIGHT_BUTTON 4 #define DBL_CLICK 8 +#define X1_BUTTON 16 +#define X2_BUTTON 32 + +#ifndef MK_XBUTTON1 +#define MK_XBUTTON1 0x0020 +#endif + +#ifndef MK_XBUTTON2 +#define MK_XBUTTON2 0x0040 +#endif + +// combination of standard mouse button flags +const int ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON; +const int X_BUTTONS = MK_XBUTTON1|MK_XBUTTON2; + + // Whether to check for embedded frame and adjust location #define CHECK_EMBEDDED 0 @@ -81,11 +97,6 @@ enum MsgRouting { class AwtComponent : public AwtObject { public: - enum { - // combination of all mouse button flags - ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON - }; - /* java.awt.Component fields and method IDs */ static jfieldID peerID; static jfieldID xID; @@ -112,6 +123,7 @@ public: static jmethodID replaceSurfaceDataLaterMID; static const UINT WmAwtIsComponent; + static jint * masks; //InputEvent mask array AwtComponent(); virtual ~AwtComponent(); @@ -675,10 +687,6 @@ public: static HWND sm_focusOwner; static HWND sm_focusedWindow; - static BOOL m_isWin95; - static BOOL m_isWin2000; - static BOOL m_isWinNT; - static BOOL sm_bMenuLoop; static INLINE BOOL isMenuLoopActive() { return sm_bMenuLoop; diff --git a/jdk/src/windows/native/sun/windows/awt_Cursor.cpp b/jdk/src/windows/native/sun/windows/awt_Cursor.cpp index f524a465c01..c1f3d84e077 100644 --- a/jdk/src/windows/native/sun/windows/awt_Cursor.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Cursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,10 +79,6 @@ AwtCursor::AwtCursor(JNIEnv *env, HCURSOR hCur, jobject jCur, int xH, int yH, custom = TRUE; dirty = FALSE; - - if (IsWin95Cursor()) { - customCursors.Add(this); - } } AwtCursor::~AwtCursor() @@ -96,9 +92,6 @@ void AwtCursor::Dispose() if (custom) { ::DestroyIcon(hCursor); - if (IsWin95Cursor()) { - customCursors.Remove(this); - } } JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -256,16 +249,6 @@ void AwtCursor::UpdateCursor(AwtComponent *comp) { env->DeleteLocalRef(jcomp); } -void AwtCursor::DirtyAllCustomCursors() { - if (IsWin95Cursor()) { - AwtObjectListItem *cur = customCursors.m_head; - while (cur != NULL) { - ((AwtCursor *)(cur->obj))->dirty = TRUE; - cur = cur->next; - } - } -} - void AwtCursor::Rebuild() { if (!dirty) { return; @@ -294,23 +277,6 @@ void AwtCursor::Rebuild() { dirty = FALSE; } -/* Bug fix for 4205805: - Custom cursor on WIN95 needs more effort, the same API works fine on NT - and WIN98. On Win95, DDB has to be passed in when calling createIconIndirect - Since DDB depends on the DISPLAY, we have to rebuild all the custom cursors - when user changes the display settings. -*/ -BOOL AwtCursor::IsWin95Cursor() { - static BOOL val; - static BOOL known = FALSE; - if (!known) { - val = (IS_WIN32 && !IS_NT && LOBYTE(LOWORD(::GetVersion())) == 4 && - HIBYTE(LOWORD(::GetVersion())) == 0); - known = TRUE; - } - return val; -} - extern "C" { /************************************************************************ diff --git a/jdk/src/windows/native/sun/windows/awt_Cursor.h b/jdk/src/windows/native/sun/windows/awt_Cursor.h index 7e59a899dcd..69c2931a2b8 100644 --- a/jdk/src/windows/native/sun/windows/awt_Cursor.h +++ b/jdk/src/windows/native/sun/windows/awt_Cursor.h @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,6 @@ public: } static AwtCursor * CreateSystemCursor(jobject jCursor); static void UpdateCursor(AwtComponent *comp); - static void DirtyAllCustomCursors(); static HCURSOR GetCursor(JNIEnv *env, AwtComponent *comp); static void setPData(jobject cursor, jlong pdata) { @@ -76,7 +75,6 @@ public: private: void Rebuild(); - static BOOL IsWin95Cursor(); HCURSOR hCursor; jweak jCursor; diff --git a/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp b/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp index 8cd5be4542e..b7225d1151f 100644 --- a/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DataTransferer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,11 @@ */ #include "awt.h" -#include "awt_dlls.h" #include "awt_DataTransferer.h" #include "awt_DnDDT.h" #include "awt_TextComponent.h" -#include "awt_Unicode.h" #include +#include #include #include @@ -271,9 +270,7 @@ Java_sun_awt_windows_WDataTransferer_dragQueryFile hdrop = (HDROP)bBytes; - load_shell_procs(); - - UINT nFilenames = (*do_drag_query_file)(hdrop, 0xFFFFFFFF, NULL, 0); + UINT nFilenames = ::DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); jclass str_clazz = env->FindClass("java/lang/String"); DASSERT(str_clazz != NULL); @@ -287,12 +284,12 @@ Java_sun_awt_windows_WDataTransferer_dragQueryFile buffer = (LPTSTR)safe_Malloc(bufsize*sizeof(TCHAR)); for (UINT i = 0; i < nFilenames; i++) { - UINT size = (*do_drag_query_file)(hdrop, i, NULL, 0); + UINT size = ::DragQueryFile(hdrop, i, NULL, 0); if (size > bufsize) { bufsize = size; buffer = (LPTSTR)safe_Realloc(buffer, bufsize*sizeof(TCHAR)); } - (*do_drag_query_file)(hdrop, i, buffer, bufsize); + ::DragQueryFile(hdrop, i, buffer, bufsize); jstring name = JNU_NewStringPlatform(env, buffer); if (name == NULL) { @@ -401,7 +398,7 @@ Java_sun_awt_windows_WDataTransferer_platformImageBytesToImageData( case 4: case 8: nColorEntries = (pSrcBmih->biClrUsed != 0) ? - pSrcBmih->biClrUsed : 1 << (pSrcBmih->biBitCount - 1); + pSrcBmih->biClrUsed : (1 << pSrcBmih->biBitCount); break; case 16: case 24: @@ -454,11 +451,6 @@ Java_sun_awt_windows_WDataTransferer_platformImageBytesToImageData( width = p.x; height = -p.y; - // Win9X supports only 16-bit signed coordinates. - if (IS_WIN95) { - if (width > 0x7FFF) { width = 0x7FFF; } - if (height > 0x7FFF) { height = 0x7FFF; } - } free(lpemh); } break; diff --git a/jdk/src/windows/native/sun/windows/awt_Desktop.cpp b/jdk/src/windows/native/sun/windows/awt_Desktop.cpp index f232a728231..4462ca12e4f 100644 --- a/jdk/src/windows/native/sun/windows/awt_Desktop.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Desktop.cpp @@ -23,8 +23,8 @@ * have any questions. */ +#include "awt.h" #include -#include #include #include @@ -40,32 +40,32 @@ extern "C" { JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDesktopPeer_ShellExecute (JNIEnv *env, jclass cls, jstring uri_j, jstring verb_j) { - const WCHAR* uri_c = env->GetStringChars(uri_j, JNI_FALSE); - const WCHAR* verb_c = env->GetStringChars(verb_j, JNI_FALSE); + LPCWSTR uri_c = JNU_GetStringPlatformChars(env, uri_j, JNI_FALSE); + LPCWSTR verb_c = JNU_GetStringPlatformChars(env, verb_j, JNI_FALSE); // 6457572: ShellExecute possibly changes FPU control word - saving it here unsigned oldcontrol87 = _control87(0, 0); - HINSTANCE retval = ShellExecuteW(NULL, verb_c, uri_c, NULL, NULL, SW_SHOWNORMAL); + HINSTANCE retval = ::ShellExecute(NULL, verb_c, uri_c, NULL, NULL, SW_SHOWNORMAL); _control87(oldcontrol87, 0xffffffff); - env->ReleaseStringChars(uri_j, uri_c); - env->ReleaseStringChars(verb_j, verb_c); + JNU_ReleaseStringPlatformChars(env, uri_j, uri_c); + JNU_ReleaseStringPlatformChars(env, verb_j, verb_c); if ((int)retval <= 32) { // ShellExecute failed. - LPVOID buffer; - int len = FormatMessageW( + LPTSTR buffer = NULL; + int len = ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPWSTR) &buffer, + (LPTSTR)&buffer, 0, NULL ); - jstring errmsg = env->NewString((LPCWSTR)buffer, len); + jstring errmsg = JNU_NewStringPlatform(env, buffer, len); LocalFree(buffer); return errmsg; } diff --git a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp index 10c00fe2c29..1475dee38ab 100644 --- a/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DesktopProperties.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,17 @@ * have any questions. */ -#include "stdhdrs.h" +#include "awt.h" #include "mmsystem.h" #include "jlong.h" -#include "awt.h" #include "awt_DesktopProperties.h" -#include "awt_dlls.h" +#include "awt_Toolkit.h" #include "sun_awt_windows_WDesktopProperties.h" #include "java_awt_Font.h" #include "awtmsg.h" -#include "Zmouse.h" -#include "shellapi.h" +#include "zmouse.h" +#include +#include // WDesktopProperties fields jfieldID AwtDesktopProperties::pDataID = 0; @@ -44,10 +44,6 @@ jmethodID AwtDesktopProperties::setColorPropertyID = 0; jmethodID AwtDesktopProperties::setFontPropertyID = 0; jmethodID AwtDesktopProperties::setSoundPropertyID = 0; -typedef VOID (WINAPI *SHGetSettingsType)(LPSHELLFLAGSTATE, DWORD); -static HMODULE libShell32 = NULL; -static SHGetSettingsType fn_SHGetSettings; - AwtDesktopProperties::AwtDesktopProperties(jobject self) { this->self = GetEnv()->NewGlobalRef(self); GetEnv()->SetLongField( self, AwtDesktopProperties::pDataID, @@ -431,14 +427,12 @@ void CheckFontSmoothingSettings(HWND hWnd) { void AwtDesktopProperties::GetColorParameters() { - if (IS_WIN98 || IS_WIN2000) { - SetColorProperty(TEXT("win.frame.activeCaptionGradientColor"), - GetSysColor(COLOR_GRADIENTACTIVECAPTION)); - SetColorProperty(TEXT("win.frame.inactiveCaptionGradientColor"), - GetSysColor(COLOR_GRADIENTINACTIVECAPTION)); - SetColorProperty(TEXT("win.item.hotTrackedColor"), - GetSysColor(COLOR_HOTLIGHT)); - } + SetColorProperty(TEXT("win.frame.activeCaptionGradientColor"), + GetSysColor(COLOR_GRADIENTACTIVECAPTION)); + SetColorProperty(TEXT("win.frame.inactiveCaptionGradientColor"), + GetSysColor(COLOR_GRADIENTINACTIVECAPTION)); + SetColorProperty(TEXT("win.item.hotTrackedColor"), + GetSysColor(COLOR_HOTLIGHT)); SetColorProperty(TEXT("win.3d.darkShadowColor"), GetSysColor(COLOR_3DDKSHADOW)); SetColorProperty(TEXT("win.3d.backgroundColor"), GetSysColor(COLOR_3DFACE)); SetColorProperty(TEXT("win.3d.highlightColor"), GetSysColor(COLOR_3DHIGHLIGHT)); @@ -510,40 +504,18 @@ void AwtDesktopProperties::GetOtherParameters() { // This property is called "win.frame.fullWindowDragsOn" above // This is one of the properties that don't trigger WM_SETTINGCHANGE SetBooleanProperty(TEXT("awt.dynamicLayoutSupported"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS)); - - // 95 MouseWheel support - // More or less copied from the MSH_MOUSEWHEEL MSDN entry - if (IS_WIN95 && !IS_WIN98) { - HWND hdlMSHWHEEL = NULL; - UINT msgMSHWheelSupported = NULL; - BOOL wheelSupported = FALSE; - - msgMSHWheelSupported = RegisterWindowMessage(MSH_WHEELSUPPORT); - hdlMSHWHEEL = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); - if (hdlMSHWHEEL && msgMSHWheelSupported) { - wheelSupported = (BOOL)::SendMessage(hdlMSHWHEEL, - msgMSHWheelSupported, 0, 0); - } - SetBooleanProperty(TEXT("awt.wheelMousePresent"), wheelSupported); - } - else { - SetBooleanProperty(TEXT("awt.wheelMousePresent"), - ::GetSystemMetrics(SM_MOUSEWHEELPRESENT)); - } + SetBooleanProperty(TEXT("awt.wheelMousePresent"), + ::GetSystemMetrics(SM_MOUSEWHEELPRESENT)); // END cross-platform properties - if (IS_WIN98 || IS_WIN2000) { - //DWORD menuShowDelay; - //SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &menuShowDelay, 0); - // SetIntegerProperty(TEXT("win.menu.showDelay"), menuShowDelay); - SetBooleanProperty(TEXT("win.frame.captionGradientsOn"), GetBooleanParameter(SPI_GETGRADIENTCAPTIONS)); - SetBooleanProperty(TEXT("win.item.hotTrackingOn"), GetBooleanParameter(SPI_GETHOTTRACKING)); - } + //DWORD menuShowDelay; + //SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &menuShowDelay, 0); + // SetIntegerProperty(TEXT("win.menu.showDelay"), menuShowDelay); + SetBooleanProperty(TEXT("win.frame.captionGradientsOn"), GetBooleanParameter(SPI_GETGRADIENTCAPTIONS)); + SetBooleanProperty(TEXT("win.item.hotTrackingOn"), GetBooleanParameter(SPI_GETHOTTRACKING)); - if (IS_WIN2000) { - SetBooleanProperty(TEXT("win.menu.keyboardCuesOn"), GetBooleanParameter(SPI_GETKEYBOARDCUES)); - } + SetBooleanProperty(TEXT("win.menu.keyboardCuesOn"), GetBooleanParameter(SPI_GETKEYBOARDCUES)); // High contrast accessibility property HIGHCONTRAST contrast; @@ -557,21 +529,19 @@ void AwtDesktopProperties::GetOtherParameters() { SetBooleanProperty(TEXT("win.highContrast.on"), FALSE); } - if (fn_SHGetSettings != NULL) { - SHELLFLAGSTATE sfs; - fn_SHGetSettings(&sfs, SSF_SHOWALLOBJECTS | SSF_SHOWATTRIBCOL); - if (sfs.fShowAllObjects) { - SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), TRUE); - } - else { - SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), FALSE); - } - if (sfs.fShowAttribCol) { - SetBooleanProperty(TEXT("awt.file.showAttribCol"), TRUE); - } - else { - SetBooleanProperty(TEXT("awt.file.showAttribCol"), FALSE); - } + SHELLFLAGSTATE sfs; + ::SHGetSettings(&sfs, SSF_SHOWALLOBJECTS | SSF_SHOWATTRIBCOL); + if (sfs.fShowAllObjects) { + SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), TRUE); + } + else { + SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), FALSE); + } + if (sfs.fShowAttribCol) { + SetBooleanProperty(TEXT("awt.file.showAttribCol"), TRUE); + } + else { + SetBooleanProperty(TEXT("awt.file.showAttribCol"), FALSE); } LPTSTR value; @@ -667,7 +637,7 @@ UINT AwtDesktopProperties::GetIntegerParameter(UINT spi) { } void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) { - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setStringPropertyID, key, JNU_NewStringPlatform(GetEnv(), value)); @@ -675,7 +645,7 @@ void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) { } void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) { - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setIntegerPropertyID, key, (jint)value); @@ -683,7 +653,7 @@ void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) { } void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) { - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setBooleanPropertyID, key, value ? JNI_TRUE : JNI_FALSE); @@ -691,7 +661,7 @@ void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) { } void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) { - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setColorPropertyID, key, GetRValue(value), GetGValue(value), @@ -743,7 +713,7 @@ void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID, style |= java_awt_Font_ITALIC; } - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); @@ -761,7 +731,7 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon jint pointSize; jint style; - fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName); + fontName = JNU_NewStringPlatform(GetEnv(), const_cast(font.lfFaceName)); #if 0 HDC hdc; @@ -784,7 +754,7 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon style |= java_awt_Font_ITALIC; } - jstring key = JNU_NewStringPlatform(GetEnv(), propName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID, key, fontName, style, pointSize); @@ -793,8 +763,8 @@ void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & fon } void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) { - jstring key = JNU_NewStringPlatform(GetEnv(), propName); - jstring event = JNU_NewStringPlatform(GetEnv(), winEventName); + jstring key = JNU_NewStringPlatform(GetEnv(), const_cast(propName)); + jstring event = JNU_NewStringPlatform(GetEnv(), const_cast(winEventName)); GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setSoundPropertyID, key, event); @@ -805,9 +775,9 @@ void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventNa void AwtDesktopProperties::PlayWindowsSound(LPCTSTR event) { // stop any currently playing sounds - AwtWinMM::PlaySoundWrapper(NULL, NULL, SND_PURGE); + ::PlaySound(NULL, NULL, SND_PURGE); // play the sound for the given event name - AwtWinMM::PlaySoundWrapper(event, NULL, SND_ASYNC|SND_ALIAS|SND_NODEFAULT); + ::PlaySound(event, NULL, SND_ASYNC|SND_ALIAS|SND_NODEFAULT); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -852,16 +822,6 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WDesktopProperties_init(JNIEnv *env, jobject self) { TRY; - // Open shell32.dll, get the symbol for SHGetSettings - libShell32 = LoadLibrary(TEXT("shell32.dll")); - if (libShell32 == NULL) { - fn_SHGetSettings = NULL; - } - else { - fn_SHGetSettings = (SHGetSettingsType)GetProcAddress( - libShell32, "SHGetSettings"); - } - new AwtDesktopProperties(self); CATCH_BAD_ALLOC; diff --git a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp index 948fc0883ed..ecf74549d46 100644 --- a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp @@ -132,14 +132,13 @@ AwtDialog* AwtDialog::Create(jobject peer, jobject parent) dialog = new AwtDialog(); { - int colorId = IS_WIN4X ? COLOR_3DFACE : COLOR_WINDOW; + int colorId = COLOR_3DFACE; DWORD style = WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN; if (hwndParent != NULL) { style |= WS_POPUP; } style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX); - DWORD exStyle = IS_WIN4X ? WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME - : 0; + DWORD exStyle = WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME; if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; @@ -663,7 +662,7 @@ void AwtDialog::_SetIMMOption(void *param) int badAlloc = 0; LPCTSTR coption; - LPTSTR empty = TEXT("InputMethod"); + LPCTSTR empty = TEXT("InputMethod"); AwtDialog *d = NULL; PDATA pData; diff --git a/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp b/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp index 31ee7edcbe3..bb2ac566493 100644 --- a/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DnDDS.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include "jlong.h" #include "awt_DataTransferer.h" #include "awt_DnDDS.h" @@ -36,8 +37,6 @@ #include "sun_awt_dnd_SunDragSourceContextPeer.h" #include "sun_awt_windows_WDragSourceContextPeer.h" -#include -#include #include #include diff --git a/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp b/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp index 8940a30266a..fce80f468b2 100644 --- a/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DnDDT.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,11 +30,8 @@ #include "awt_Toolkit.h" #include "java_awt_dnd_DnDConstants.h" #include "sun_awt_windows_WDropTargetContextPeer.h" -#include "awt_dlls.h" #include "awt_Container.h" -#include -#include #include #include @@ -555,8 +552,7 @@ jobject AwtDropTarget::GetData(jlong fmt) { break; } case TYMED_FILE: { - jobject local = JNU_NewStringPlatform(env, (LPCTSTR) - stgmedium.lpszFileName); + jobject local = JNU_NewStringPlatform(env, stgmedium.lpszFileName); jstring fileName = (jstring)env->NewGlobalRef(local); env->DeleteLocalRef(local); diff --git a/jdk/src/windows/native/sun/windows/awt_DrawingSurface.cpp b/jdk/src/windows/native/sun/windows/awt_DrawingSurface.cpp index d1ef0568494..b7b7913b780 100644 --- a/jdk/src/windows/native/sun/windows/awt_DrawingSurface.cpp +++ b/jdk/src/windows/native/sun/windows/awt_DrawingSurface.cpp @@ -24,6 +24,8 @@ */ #define _JNI_IMPLEMENTATION_ + +#include "awt.h" #include "awt_DrawingSurface.h" #include "awt_Component.h" diff --git a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp index 08d839fc44f..84339e40eee 100644 --- a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "awt_FileDialog.h" #include "awt_Dialog.h" #include "awt_Toolkit.h" -#include "awt_dlls.h" #include "ComCtl32Util.h" #include #include @@ -65,7 +64,7 @@ AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription) { int length = env->GetStringLength(filterDescription); DASSERT(length + 1 < MAX_FILTER_STRING); - LPCTSTR tmp = (LPTSTR)JNU_GetStringPlatformChars(env, filterDescription, NULL); + LPCTSTR tmp = JNU_GetStringPlatformChars(env, filterDescription, NULL); _tcscpy(s_fileFilterString, tmp); JNU_ReleaseStringPlatformChars(env, filterDescription, tmp); @@ -156,7 +155,7 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl; // Get the filename and directory TCHAR szPath[MAX_PATH]; - if (!get_path_from_idlist(pidl,szPath)) { + if (!::SHGetPathFromIDList(pidl, szPath)) { return TRUE; } jstring strPath = JNU_NewStringPlatform(env, szPath); @@ -190,7 +189,7 @@ AwtFileDialog::Show(void *p) WCHAR unicodeChar = L' '; LPTSTR fileBuffer = NULL; LPTSTR currentDirectory = NULL; - AWTOPENFILENAME ofn; + OPENFILENAME ofn; jint mode = 0; BOOL result = FALSE; DWORD dlgerr; @@ -222,7 +221,7 @@ AwtFileDialog::Show(void *p) HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; if (title == NULL || env->GetStringLength(title)==0) { - title = env->NewString(&unicodeChar, 1); + title = JNU_NewStringPlatform(env, &unicodeChar); } JavaStringBuffer titleBuffer(env, title); @@ -243,14 +242,7 @@ AwtFileDialog::Show(void *p) memset(&ofn, 0, sizeof(ofn)); - // According to the MSDN docs, lStructSize must be set to - // OPENFILENAME_SIZE_VERSION_400 on NT4.0. - if (IS_NT && !(IS_WIN2000)) { - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - } - else { ofn.lStructSize = sizeof(ofn); - } ofn.lpstrFilter = s_fileFilterString; ofn.nFilterIndex = 1; /* @@ -289,9 +281,6 @@ AwtFileDialog::Show(void *p) mode = env->GetIntField(target, AwtFileDialog::modeID); - // Fix for 4364256 : call load_shell_procs() - load_shell_procs(); - AwtDialog::CheckInstallModalHook(); // show the Win32 file dialog @@ -304,7 +293,7 @@ AwtFileDialog::Show(void *p) // If the dialog is not shown because of invalid file name // replace the file name by empty string. if (!result) { - dlgerr = AwtCommDialog::CommDlgExtendedError(); + dlgerr = ::CommDlgExtendedError(); if (dlgerr == FNERR_INVALIDFILENAME) { _tcscpy(fileBuffer, TEXT("")); if (mode == java_awt_FileDialog_LOAD) { @@ -326,7 +315,7 @@ AwtFileDialog::Show(void *p) // Report result to peer. if (result) { jstring tmpJString = (_tcslen(ofn.lpstrFile) == 0 ? - env->NewStringUTF("") : + JNU_NewStringPlatform(env, L"") : JNU_NewStringPlatform(env, ofn.lpstrFile)); env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, tmpJString); env->DeleteLocalRef(tmpJString); @@ -362,20 +351,18 @@ AwtFileDialog::Show(void *p) } BOOL -AwtFileDialog::GetOpenFileName(LPAWTOPENFILENAME data) { - AwtCommDialog::load_comdlg_procs(); +AwtFileDialog::GetOpenFileName(LPOPENFILENAME data) { return static_cast(reinterpret_cast( AwtToolkit::GetInstance().InvokeFunction((void*(*)(void*)) - AwtCommDialog::GetOpenFileNameWrapper, data))); + ::GetOpenFileName, data))); } BOOL -AwtFileDialog::GetSaveFileName(LPAWTOPENFILENAME data) { - AwtCommDialog::load_comdlg_procs(); +AwtFileDialog::GetSaveFileName(LPOPENFILENAME data) { return static_cast(reinterpret_cast( AwtToolkit::GetInstance().InvokeFunction((void *(*)(void *)) - AwtCommDialog::GetSaveFileNameWrapper, data))); + ::GetSaveFileName, data))); } diff --git a/jdk/src/windows/native/sun/windows/awt_FileDialog.h b/jdk/src/windows/native/sun/windows/awt_FileDialog.h index 9a324f68f34..82638d30752 100644 --- a/jdk/src/windows/native/sun/windows/awt_FileDialog.h +++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.h @@ -1,5 +1,5 @@ /* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,43 +36,6 @@ #include "java_awt_FileDialog.h" #include "sun_awt_windows_WFileDialogPeer.h" -// The VC6 headers don't include this, but it's necessary for -// backward-compatibility with NT4.0, so we fake it. -#ifndef OPENFILENAME_SIZE_VERSION_400 - // Determined via sizeof(OPENFILENAME) - #define OPENFILENAME_SIZE_VERSION_400 76 -#endif - -// 4859390 -// For the Places Bar to show up, we need the "full" OPENFILENAME struct -typedef struct tagAWTOFN { - DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCTSTR lpstrFilter; - LPTSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPTSTR lpstrFile; - DWORD nMaxFile; - LPTSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCTSTR lpstrInitialDir; - LPCTSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCTSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCTSTR lpTemplateName; -//#if (_WIN32_WINNT >= 0x0500) - void * pvReserved; - DWORD dwReserved; - DWORD FlagsEx; -//#endif // (_WIN32_WINNT >= 0x0500) -} AWTOPENFILENAME, *LPAWTOPENFILENAME; - /************************************************************************ * AwtFileDialog class */ @@ -96,8 +59,8 @@ public: static void Initialize(JNIEnv *env, jstring filterDescription); static void Show(void *peer); - static BOOL GetOpenFileName(LPAWTOPENFILENAME); - static BOOL GetSaveFileName(LPAWTOPENFILENAME); + static BOOL GetOpenFileName(LPOPENFILENAME); + static BOOL GetSaveFileName(LPOPENFILENAME); virtual BOOL InheritsNativeMouseWheelBehavior(); diff --git a/jdk/src/windows/native/sun/windows/awt_Font.cpp b/jdk/src/windows/native/sun/windows/awt_Font.cpp index 8dc9d5a67b5..6815b1afab1 100644 --- a/jdk/src/windows/native/sun/windows/awt_Font.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Font.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include #include "jlong.h" #include "awt_Font.h" @@ -195,7 +196,7 @@ AwtFont* AwtFont::GetFont(JNIEnv *env, jobject font, } // Get suitable CHARSET from charset string provided by font configuration. -static int GetNativeCharset(WCHAR* name) +static int GetNativeCharset(LPCWSTR name) { if (wcsstr(name, L"ANSI_CHARSET")) return ANSI_CHARSET; @@ -259,7 +260,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) cfnum = 0; } - WCHAR* wName; + LPCWSTR wName; awtFont = new AwtFont(cfnum, env, font); @@ -269,9 +270,7 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) if (cfnum > 0) { // Ask peer class for the text component font name jstring jTextComponentFontName = GetTextComponentFontName(env, font); - WCHAR* textComponentFontName = TO_WSTRING(jTextComponentFontName); - - env->DeleteLocalRef(jTextComponentFontName); + LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL); awtFont->m_textInput = -1; for (int i = 0; i < cfnum; i++) { @@ -282,13 +281,13 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) jstring nativeName = (jstring)env->GetObjectField(fontDescriptor, AwtFont::nativeNameID); - wName = TO_WSTRING(nativeName); + wName = JNU_GetStringPlatformChars(env, nativeName, NULL); DASSERT(wName); //On NT platforms, if the font is not Symbol or Dingbats //use "W" version of Win32 APIs directly, info the FontDescription //no need to convert characters from Unicode to locale encodings. - if (IS_NT && GetNativeCharset(wName) != SYMBOL_CHARSET) { + if (GetNativeCharset(wName) != SYMBOL_CHARSET) { env->SetBooleanField(fontDescriptor, AwtFont::useUnicodeID, TRUE); } @@ -299,10 +298,12 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) (wcscmp(wName, textComponentFontName) == 0)) { awtFont->m_textInput = i; } - HFONT hfonttmp = CreateHFont(wName, fontStyle, fontSize, + HFONT hfonttmp = CreateHFont(const_cast(wName), fontStyle, fontSize, angle, awScale); awtFont->m_hFont[i] = hfonttmp; + JNU_ReleaseStringPlatformChars(env, nativeName, wName); + env->DeleteLocalRef(fontDescriptor); env->DeleteLocalRef(nativeName); } @@ -311,11 +312,14 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) // to first component awtFont->m_textInput = 0; } + + JNU_ReleaseStringPlatformChars(env, jTextComponentFontName, textComponentFontName); + env->DeleteLocalRef(jTextComponentFontName); } else { // Instantiation for English version. jstring fontName = (jstring)env->GetObjectField(font, AwtFont::nameID); - wName = TO_WSTRING(fontName); + wName = JNU_GetStringPlatformChars(env, fontName, NULL); WCHAR* wEName; if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) { @@ -338,6 +342,9 @@ AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale) awtFont->m_textInput = 0; awtFont->m_hFont[0] = CreateHFont(wEName, fontStyle, fontSize, angle, awScale); + + JNU_ReleaseStringPlatformChars(env, fontName, wName); + env->DeleteLocalRef(fontName); } /* The several callers of this method also set the pData field. @@ -381,7 +388,7 @@ static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any po } -static HFONT CreateHFont_sub(WCHAR* name, int style, int height, +static HFONT CreateHFont_sub(LPCWSTR name, int style, int height, int angle=0, float awScale=1.0f) { LOGFONTW logFont; @@ -420,18 +427,7 @@ static HFONT CreateHFont_sub(WCHAR* name, int style, int height, strip_tail(tmpname,L"Italic"); strip_tail(tmpname,L"Bold"); wcscpy(&(logFont.lfFaceName[0]), tmpname); - HFONT hFont; - if (IS_WIN95) { -#ifdef WIN32 - DASSERT(IS_WIN95); -#endif - HDC hdc = ::GetDC(NULL); - ::EnumFontFamiliesEx(hdc, &logFont, (FONTENUMPROC)FindFamilyName, - (LPARAM)tmpname, 0L); - ::ReleaseDC(NULL, hdc); - wcscpy(&logFont.lfFaceName[0], tmpname); - } - hFont = ::CreateFontIndirectW(&logFont); + HFONT hFont = ::CreateFontIndirect(&logFont); DASSERT(hFont != NULL); // get a expanded or condensed version if its specified. if (awScale != 1.0f) { @@ -446,7 +442,7 @@ static HFONT CreateHFont_sub(WCHAR* name, int style, int height, } avgWidth = tm.tmAveCharWidth; logFont.lfWidth = (LONG)((fabs)(avgWidth*awScale)); - hFont = CreateFontIndirectW(&logFont); + hFont = ::CreateFontIndirect(&logFont); DASSERT(hFont != NULL); VERIFY(::ReleaseDC(0, hDC)); } @@ -460,15 +456,8 @@ HFONT AwtFont::CreateHFont(WCHAR* name, int style, int height, WCHAR longName[80]; // 80 > (max face name(=30) + strlen("CHINESEBIG5_CHARSET")) // longName doesn't have to be printable. So, it is OK not to convert. - if (IS_NT) { - //wsprintfW only works on NT. See bugid 4123362 - wsprintfW(longName, L"%ls-%d-%d", name, style, height); - } else { -#ifdef WIN32 - DASSERT(IS_WIN95); -#endif - swprintf(longName, L"%ls-%d-%d", name, style, height); - } + + wsprintf(longName, L"%ls-%d-%d", name, style, height); HFONT hFont = NULL; @@ -682,28 +671,16 @@ SIZE AwtFont::DrawStringSize_sub(jstring str, HDC hDC, if (arrayLength == 0) { int length = env->GetStringLength(str); - WCHAR* string = TO_WSTRING(str); + LPCWSTR strW = JNU_GetStringPlatformChars(env, str, NULL); VERIFY(::SelectObject(hDC, awtFont->GetHFont())); if (AwtComponent::GetRTLReadingOrder()){ - if (IS_WIN95) { - // Start of conversion Code to fix arabic shaping problems - // with unicode support in win 95 - LPSTR buffer = (LPSTR) alloca((wcslen(string) + 1) * 2); - int count = ::WideCharToMultiByte(codePage, 0, string, length, - buffer, - static_cast((wcslen(string) + 1) * 2), - NULL, NULL); - VERIFY(!draw || ::ExtTextOutA(hDC, x, y, ETO_RTLREADING, NULL, - buffer, count, NULL)); - // End Of Conversion Code - } else { - VERIFY(!draw || ::ExtTextOutW(hDC, x, y, ETO_RTLREADING, NULL, - string, length, NULL)); - } + VERIFY(!draw || ::ExtTextOut(hDC, x, y, ETO_RTLREADING, NULL, + strW, length, NULL)); } else { - VERIFY(!draw || ::TextOutW(hDC, x, y, string, length)); + VERIFY(!draw || ::TextOut(hDC, x, y, strW, length)); } - VERIFY(::GetTextExtentPoint32W(hDC, string, length, &size)); + VERIFY(::GetTextExtentPoint32(hDC, strW, length, &size)); + JNU_ReleaseStringPlatformChars(env, str, strW); } else { for (int i = 0; i < arrayLength; i = i + 2) { jobject fontDescriptor = env->GetObjectArrayElement(array, i); @@ -732,7 +709,7 @@ SIZE AwtFont::DrawStringSize_sub(jstring str, HDC hDC, * extend buflen and bad things will happen. */ unsigned char* buffer = NULL; - jboolean unicodeUsed = env->GetBooleanField(fontDescriptor,AwtFont::useUnicodeID); + jboolean unicodeUsed = env->GetBooleanField(fontDescriptor, AwtFont::useUnicodeID); try { buffer = (unsigned char *) env->GetPrimitiveArrayCritical(convertedBytes, 0); @@ -1231,7 +1208,7 @@ class CSegTableComponent public: CSegTableComponent(); virtual ~CSegTableComponent(); - virtual void Create(LPWSTR name); + virtual void Create(LPCWSTR name); virtual BOOL In(USHORT iChar) { DASSERT(FALSE); return FALSE; }; LPWSTR GetFontName(){ DASSERT(m_lpszFontName != NULL); return m_lpszFontName; @@ -1254,7 +1231,7 @@ CSegTableComponent::~CSegTableComponent() } } -void CSegTableComponent::Create(LPWSTR name) +void CSegTableComponent::Create(LPCWSTR name) { if (m_lpszFontName != NULL) { free(m_lpszFontName); @@ -1453,7 +1430,7 @@ public: CStdSegTable(); virtual ~CStdSegTable(); BOOL IsEUDC() { return FALSE; }; - virtual void Create(LPWSTR name); + virtual void Create(LPCWSTR name); protected: void GetData(DWORD dwOffset, LPVOID lpData, DWORD cbData); @@ -1481,7 +1458,7 @@ inline void CStdSegTable::GetData(DWORD dwOffset, DASSERT(nBytes != GDI_ERROR); } -void CStdSegTable::Create(LPWSTR name) +void CStdSegTable::Create(LPCWSTR name) { CSegTableComponent::Create(name); @@ -1509,7 +1486,7 @@ public: CEUDCSegTable(); virtual ~CEUDCSegTable(); BOOL IsEUDC() { return TRUE; }; - virtual void Create(LPWSTR name); + virtual void Create(LPCWSTR name); protected: void GetData(DWORD dwOffset, LPVOID lpData, DWORD cbData); @@ -1543,7 +1520,7 @@ inline void CEUDCSegTable::GetData(DWORD dwOffset, DASSERT(dwRead == cbData); } -void CEUDCSegTable::Create(LPWSTR name) +void CEUDCSegTable::Create(LPCWSTR name) { typedef struct tagHEAD{ FIXED sfnt_version; @@ -1564,19 +1541,8 @@ typedef struct tagENTRY{ // create EUDC font file and make EUDCSegTable // after wrapper function for CreateFileW, we use only CreateFileW - if (IS_NT) { - m_hTmpFile = ::CreateFileW(name, GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } else { -#ifdef WIN32 - DASSERT(IS_WIN95); -#endif - char szFileName[_MAX_PATH]; - ::WideCharToMultiByte(CP_ACP, 0, name, -1, - szFileName, sizeof(szFileName), NULL, NULL); - m_hTmpFile = ::CreateFileA(szFileName, GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } + m_hTmpFile = ::CreateFile(name, GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hTmpFile == INVALID_HANDLE_VALUE){ m_hTmpFile = NULL; return; @@ -1654,10 +1620,10 @@ void CSegTableManagerComponent::MakeBiggerTable() class CSegTableManager : public CSegTableManagerComponent { public: - CSegTable* GetTable(LPWSTR lpszFontName, BOOL fEUDC); + CSegTable* GetTable(LPCWSTR lpszFontName, BOOL fEUDC); }; -CSegTable* CSegTableManager::GetTable(LPWSTR lpszFontName, BOOL fEUDC) +CSegTable* CSegTableManager::GetTable(LPCWSTR lpszFontName, BOOL fEUDC) { for (int i = 0; i < m_nTable; i++) { if ((((CSegTable*)m_tables[i])->IsEUDC() == fEUDC) && @@ -1685,7 +1651,7 @@ class CCombinedSegTable : public CSegTableComponent { public: CCombinedSegTable(); - void Create(LPWSTR name); + void Create(LPCWSTR name); BOOL In(USHORT iChar); private: @@ -1807,7 +1773,7 @@ void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName) wcscpy(m_szDefaultEUDCFile, lpszFileName); } -void CCombinedSegTable::Create(LPWSTR name) +void CCombinedSegTable::Create(LPCWSTR name) { CSegTableComponent::Create(name); @@ -1840,10 +1806,10 @@ BOOL CCombinedSegTable::In(USHORT iChar) class CCombinedSegTableManager : public CSegTableManagerComponent { public: - CCombinedSegTable* GetTable(LPWSTR lpszFontName); + CCombinedSegTable* GetTable(LPCWSTR lpszFontName); }; -CCombinedSegTable* CCombinedSegTableManager::GetTable(LPWSTR lpszFontName) +CCombinedSegTable* CCombinedSegTableManager::GetTable(LPCWSTR lpszFontName) { for (int i = 0; i < m_nTable; i++) { if (wcscmp(m_tables[i]->GetFontName(),lpszFontName) == 0) @@ -1901,8 +1867,9 @@ Java_sun_awt_windows_WDefaultFontCharset_canConvert(JNIEnv *env, jobject self, jstring fontName = (jstring)env->GetObjectField(self, AwtFont::fontNameID); DASSERT(fontName != NULL); - LPWSTR fontNameWStr = TO_WSTRING(fontName); - CCombinedSegTable* pTable = tableManager.GetTable(fontNameWStr); + LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL); + CCombinedSegTable* pTable = tableManager.GetTable(fontNameW); + JNU_ReleaseStringPlatformChars(env, fontName, fontNameW); return (pTable->In((USHORT) ch) ? JNI_TRUE : JNI_FALSE); CATCH_BAD_ALLOC_RET(FALSE); diff --git a/jdk/src/windows/native/sun/windows/awt_Font.h b/jdk/src/windows/native/sun/windows/awt_Font.h index c1edd9d0eab..ac537a122b0 100644 --- a/jdk/src/windows/native/sun/windows/awt_Font.h +++ b/jdk/src/windows/native/sun/windows/awt_Font.h @@ -28,7 +28,6 @@ #include "awt.h" #include "awt_Object.h" -#include "awt_Unicode.h" #include "java_awt_Font.h" #include "sun_awt_windows_WFontMetrics.h" diff --git a/jdk/src/windows/native/sun/windows/awt_Frame.cpp b/jdk/src/windows/native/sun/windows/awt_Frame.cpp index 37e8546ed49..60738e69357 100644 --- a/jdk/src/windows/native/sun/windows/awt_Frame.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Frame.cpp @@ -1472,7 +1472,7 @@ void AwtFrame::_SetIMMOption(void *param) int badAlloc = 0; LPCTSTR coption; - LPTSTR empty = TEXT("InputMethod"); + LPCTSTR empty = TEXT("InputMethod"); AwtFrame *f = NULL; PDATA pData; diff --git a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp index ff944b0e8e7..bd78cdaf3ef 100644 --- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp +++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -580,18 +580,10 @@ HKL getDefaultKeyboardLayout() { DWORD cbHKL = 16; LPTSTR end; - if (IS_NT) { - ret = ::RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Preload"), NULL, KEY_READ, &hKey); - } else { - ret = ::RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("keyboard layout\\preload\\1"), NULL, KEY_READ, &hKey); - } + ret = ::RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Keyboard Layout\\Preload"), NULL, KEY_READ, &hKey); if (ret == ERROR_SUCCESS) { - if (IS_NT) { - ret = ::RegQueryValueEx(hKey, TEXT("1"), 0, 0, szHKL, &cbHKL); - } else { - ret = ::RegQueryValueEx(hKey, NULL, 0, 0, szHKL, &cbHKL); - } + ret = ::RegQueryValueEx(hKey, TEXT("1"), 0, 0, szHKL, &cbHKL); if (ret == ERROR_SUCCESS) { hkl = reinterpret_cast(static_cast( diff --git a/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp b/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp index 82f54a4ead8..3c26fbb95d0 100644 --- a/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp +++ b/jdk/src/windows/native/sun/windows/awt_InputTextInfor.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,10 +22,9 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ -#include -#include -#include + #include "awt.h" +#include #include "awt_Component.h" #include "awt_InputTextInfor.h" @@ -91,12 +90,12 @@ AwtInputTextInfor::GetContextData(HIMC hIMC, const LPARAM flags) { LONG cbData[5] = {0}; LPVOID lpData[5] = {NULL}; for (int i = startIndex, j = 0; i <= endIndex; i++, j++) { - cbData[j] = ImmGetCompositionStringW(hIMC, GCS_INDEX[i], NULL, 0); + cbData[j] = ::ImmGetCompositionString(hIMC, GCS_INDEX[i], NULL, 0); if (cbData[j] == 0) { lpData[j] = NULL; } else { LPBYTE lpTemp = new BYTE[cbData[j]]; - cbData[j] = ImmGetCompositionStringW(hIMC, GCS_INDEX[i], lpTemp, cbData[j]); + cbData[j] = ::ImmGetCompositionString(hIMC, GCS_INDEX[i], lpTemp, cbData[j]); if (IMM_ERROR_GENERAL != cbData[j]) { lpData[j] = (LPVOID)lpTemp; } else { @@ -126,7 +125,7 @@ AwtInputTextInfor::GetContextData(HIMC hIMC, const LPARAM flags) { // Get the cursor position if (flags & GCS_COMPSTR) { - m_cursorPosW = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, + m_cursorPosW = ::ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0); } @@ -185,9 +184,11 @@ AwtInputTextInfor::~AwtInputTextInfor() { jstring AwtInputTextInfor::MakeJavaString(JNIEnv* env, LPWSTR lpStrW, int cStrW) { - if (env == NULL || lpStrW == NULL || cStrW == 0) return NULL; - - return env->NewString(lpStrW, cStrW); + if (env == NULL || lpStrW == NULL || cStrW == 0) { + return NULL; + } else { + return env->NewString(reinterpret_cast(lpStrW), cStrW); + } } // @@ -232,7 +233,7 @@ int AwtInputTextInfor::GetClauseInfor(int*& lpBndClauseW, jstring*& lpReadingCla LCID lcJPN = MAKELCID(MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT),SORT_DEFAULT); // Reading string is given in half width katakana in Japanese Windows // Convert it to full width katakana. - int cFWStrW = LCMapStringW( lcJPN, LCMAP_FULLWIDTH, lpHWStrW, cHWStrW, NULL, 0 ); + int cFWStrW = ::LCMapString(lcJPN, LCMAP_FULLWIDTH, lpHWStrW, cHWStrW, NULL, 0); LPWSTR lpFWStrW; try { lpFWStrW = new WCHAR[cFWStrW]; @@ -244,7 +245,7 @@ int AwtInputTextInfor::GetClauseInfor(int*& lpBndClauseW, jstring*& lpReadingCla throw; } - LCMapStringW( lcJPN, LCMAP_FULLWIDTH, lpHWStrW, cHWStrW, lpFWStrW, cFWStrW ); + ::LCMapString(lcJPN, LCMAP_FULLWIDTH, lpHWStrW, cHWStrW, lpFWStrW, cFWStrW); readingClauseW[cls] = MakeJavaString(env, lpFWStrW, cFWStrW); delete [] lpFWStrW; } else { @@ -252,7 +253,7 @@ int AwtInputTextInfor::GetClauseInfor(int*& lpBndClauseW, jstring*& lpReadingCla } } else { - readingClauseW[cls] = MakeJavaString(env, (LPWSTR)NULL, 0); + readingClauseW[cls] = NULL; } } diff --git a/jdk/src/windows/native/sun/windows/awt_List.cpp b/jdk/src/windows/native/sun/windows/awt_List.cpp index 9000aaa685a..20844de7875 100644 --- a/jdk/src/windows/native/sun/windows/awt_List.cpp +++ b/jdk/src/windows/native/sun/windows/awt_List.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ #include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "awt_Dimension.h" -#include "awt_Unicode.h" #include "awt_Toolkit.h" #include "awt_Window.h" @@ -112,9 +111,8 @@ AwtList* AwtList::Create(jobject peer, jobject parent) DWORD wrapExStyle = 0; DWORD style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL | - LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_OWNERDRAWFIXED | - (IS_WIN4X ? 0 : WS_BORDER); - DWORD exStyle = IS_WIN4X ? WS_EX_CLIENTEDGE : 0; + LBS_NOINTEGRALHEIGHT | LBS_NOTIFY | LBS_OWNERDRAWFIXED; + DWORD exStyle = WS_EX_CLIENTEDGE; /* * NOTE: WS_VISIBLE is always set for the listbox. Listbox @@ -571,10 +569,10 @@ MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic) // operate WM_PRINT to be compatible with the "smooth scrolling" feature. MsgRouting AwtList::WmPrint(HDC hDC, LPARAM flags) { - if (!isWrapperPrint && IS_WIN4X - && (flags & PRF_CLIENT) - && (GetStyleEx() & WS_EX_CLIENTEDGE)) { - + if (!isWrapperPrint && + (flags & PRF_CLIENT) && + (GetStyleEx() & WS_EX_CLIENTEDGE)) + { int nOriginalDC = ::SaveDC(hDC); DASSERT(nOriginalDC != 0); // Save a copy of the DC for WmPrintClient diff --git a/jdk/src/windows/native/sun/windows/awt_MMStub.cpp b/jdk/src/windows/native/sun/windows/awt_MMStub.cpp deleted file mode 100644 index 675f48e784b..00000000000 --- a/jdk/src/windows/native/sun/windows/awt_MMStub.cpp +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#include "awt_MMStub.h" - -//--------------------------------------------------------------------------- -// Basic API -//--------------------------------------------------------------------------- - -int (WINAPI* g_pfnGetSystemMetrics) (int); -MHND (WINAPI* g_pfnMonitorFromWindow) (HWND,BOOL); -MHND (WINAPI* g_pfnMonitorFromRect) (LPCRECT,BOOL); -MHND (WINAPI* g_pfnMonitorFromPoint) (POINT,BOOL); -BOOL (WINAPI* g_pfnGetMonitorInfo) (MHND,PMONITOR_INFO); -BOOL (WINAPI* g_pfnEnumDisplayMonitors) (HDC,LPCRECT,MON_ENUM_CALLBACK_PROC,LPARAM); -BOOL (WINAPI* g_pfnEnumDisplayDevices) (LPVOID,int,P_DISPLAY_DEVICE,DWORD); - -BOOL __initMultipleMonitorStubs(void); -BOOL __initMultipleMonitorStubs(void) -{ - static BOOL fInitDone; - HMODULE hUser32; - HMODULE hUnicows = UnicowsLoader::GetModuleHandle(); - BOOL retCode = FALSE; - - if (fInitDone) - { - retCode = g_pfnGetMonitorInfo != NULL; - goto _RET_; - } - - if ((hUser32 = GetModuleHandle(TEXT("USER32"))) && - (*(FARPROC*)&g_pfnGetSystemMetrics = GetProcAddress(hUser32,"GetSystemMetrics")) && - (*(FARPROC*)&g_pfnMonitorFromWindow = GetProcAddress(hUser32,"MonitorFromWindow")) && - (*(FARPROC*)&g_pfnMonitorFromRect = GetProcAddress(hUser32,"MonitorFromRect")) && - (*(FARPROC*)&g_pfnMonitorFromPoint = GetProcAddress(hUser32,"MonitorFromPoint")) && - (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) && - (*(FARPROC*)&g_pfnGetMonitorInfo = GetProcAddress(IS_WIN95 ? hUnicows : hUser32,"GetMonitorInfoW")) && - (*(FARPROC*)&g_pfnEnumDisplayDevices = GetProcAddress(IS_WIN95 ? hUnicows : hUser32,"EnumDisplayDevicesW")) && - (GetSystemMetrics(SM_CXVSCREEN) >= GetSystemMetrics(SM_CXSCREEN)) && - (GetSystemMetrics(SM_CYVSCREEN) >= GetSystemMetrics(SM_CYSCREEN)) ) - { - fInitDone = TRUE; - retCode = TRUE; - goto _RET_; - } - g_pfnGetSystemMetrics = NULL; - g_pfnMonitorFromWindow = NULL; - g_pfnMonitorFromRect = NULL; - g_pfnMonitorFromPoint = NULL; - g_pfnGetMonitorInfo = NULL; - g_pfnEnumDisplayMonitors = NULL; - g_pfnEnumDisplayDevices = NULL; - - fInitDone = TRUE; - retCode = FALSE; - -_RET_: - return retCode; -} - -int WINAPI _getSystemMetrics(int nCode) -{ - int retCode; - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnGetSystemMetrics(nCode); - goto _RET_; - } - - switch( nCode ) - { - case SM_CMONITORS: - case SM_SAMEDSPLFORMAT: - return 1; - - case SM_XVSCREEN: - case SM_YVSCREEN: - return 0; - - case SM_CXVSCREEN: - nCode = SM_CXSCREEN; - break; - - case SM_CYVSCREEN: - nCode = SM_CYSCREEN; - break; - } - - retCode = GetSystemMetrics(nCode); -_RET_: - return retCode; -} - - -MHND WINAPI _monitorFromRect(LPCRECT prScreen, UINT nFlags) -{ - MHND retCode = NULL; - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnMonitorFromRect(prScreen, nFlags); - goto _RET_; - } - - if( (prScreen->right < 0) || (prScreen->bottom < 0) ) - { - goto _RET_; - } - { - POINT pP = {0,0}; - - pP.x = prScreen->left; - pP.y = prScreen->top; - - retCode = _monitorFromPoint(pP,nFlags); - } - -_RET_: - return retCode; -} - -MHND WINAPI _monitorFromWindow(HWND hwProbe, UINT nFlags) -{ - RECT rR; - MHND retCode = NULL; - - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnMonitorFromWindow(hwProbe, nFlags); - goto _RET_; - } - - if( nFlags & (MONITOR_DEFAULT_TO_PRIMARY | MONITOR_DEFAULT_TO_NEAR) ) - { - retCode = PRIMARY_MONITOR; - goto _RET_; - } - - if( GetWindowRect(hwProbe, &rR) ) - { - retCode = _monitorFromRect(&rR, nFlags); - goto _RET_; - } - -_RET_: - return retCode; -} - -MHND WINAPI _monitorFromPoint(POINT ptProbe, UINT nFlags) -{ - MHND retCode = NULL; - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnMonitorFromPoint(ptProbe,nFlags); - goto _RET_; - } - - if( nFlags & (MONITOR_DEFAULT_TO_PRIMARY | MONITOR_DEFAULT_TO_NEAR) ) - { - goto _ASSIGN_; - } - - if( (ptProbe.x <= 0) || (ptProbe.x > GetSystemMetrics(SM_CXSCREEN)) ) - { - goto _RET_; - } - - if( (ptProbe.y <= 0) || (ptProbe.y < GetSystemMetrics(SM_CYSCREEN)) ) - { - goto _RET_; - } -_ASSIGN_: - retCode = PRIMARY_MONITOR; - -_RET_: - return retCode; -} - -BOOL WINAPI _getMonitorInfo(MHND mhMon, PMONITOR_INFO pmMonInfo) -{ - RECT rArea; - BOOL retCode = FALSE; - - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnGetMonitorInfo(mhMon, pmMonInfo); - goto _RET_; - } - - if( mhMon != PRIMARY_MONITOR ) - { - goto _RET_; - } - - if( NULL == pmMonInfo ) - { - goto _RET_; - } - - if( FALSE == SystemParametersInfo(SPI_GETWORKAREA,0,&rArea,0) ) - { - goto _RET_; - } - - if( pmMonInfo->dwSize >= sizeof(MONITOR_INFO) ) - { - pmMonInfo->rMonitor.left = 0; - pmMonInfo->rMonitor.top = 0; - pmMonInfo->rMonitor.right = GetSystemMetrics(SM_CXSCREEN); - pmMonInfo->rMonitor.bottom = GetSystemMetrics(SM_CYSCREEN); - pmMonInfo->rWork = rArea; - pmMonInfo->dwFlags = MONITOR_INFO_FLAG_PRIMARY; - - if( pmMonInfo->dwSize >= sizeof(MONITOR_INFO_EXTENDED)) - { - lstrcpy(((PMONITOR_INFO_EXTENDED)pmMonInfo)->strDevice, - TEXT("DISPLAY") ); - } - - retCode = TRUE; - } - -_RET_: - return retCode; -} - -BOOL WINAPI _enumDisplayMonitors( - HDC hDC,LPCRECT lrcSect, - MON_ENUM_CALLBACK_PROC lpfnEnumProc, - LPARAM lData - ) -{ - BOOL retCode = FALSE; - RECT rToPass = {0,0,0,0}; - RECT rBorder = {0,0,0,0}; - - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnEnumDisplayMonitors ( - hDC, lrcSect, - lpfnEnumProc,lData - ); - goto _RET_; - } - - if( !lpfnEnumProc ) - { - goto _RET_; - } - - rBorder.left = 0; - rBorder.top = 0; - rBorder.right = GetSystemMetrics(SM_CXSCREEN); - rBorder.bottom = GetSystemMetrics(SM_CYSCREEN); - - if( hDC ) - { - RECT rSect = {0,0,0,0}; - HWND hWnd = NULL; - - if( NULL == (hWnd = WindowFromDC(hDC)) ) - { - goto _RET_; - } - - switch( GetClipBox(hDC,&rSect) ) - { - case NULLREGION: - goto _ASSIGN_; - case ERROR: - goto _RET_; - default: - MapWindowPoints(NULL, hWnd, (LPPOINT)&rBorder, 2); - if( TRUE == IntersectRect(&rToPass,&rSect,&rBorder) ) - { - break; - } - } - - rBorder = rToPass; - } - - if( (NULL == lrcSect) || (TRUE == IntersectRect(&rToPass,lrcSect,&rBorder)) ) - { - lpfnEnumProc(PRIMARY_MONITOR,hDC,&rToPass,lData); - } -_ASSIGN_: - retCode = TRUE; -_RET_: - return retCode; -} - -BOOL WINAPI _enumDisplayDevices ( - LPVOID lpReserved, int iDeviceNum, - _DISPLAY_DEVICE * pDisplayDevice, DWORD dwFlags - ) -{ - BOOL retCode = FALSE; - if( __initMultipleMonitorStubs() ) - { - retCode = g_pfnEnumDisplayDevices(lpReserved,iDeviceNum,pDisplayDevice,dwFlags); - } - - return retCode; -} - - -//--------------------------------------------------------------------------- -// Extended API. -//--------------------------------------------------------------------------- -// Globais -int g_nMonitorCounter; -int g_nMonitorLimit; -MHND* g_hmpMonitors; -// Callbacks -BOOL WINAPI clb_fCountMonitors(MHND,HDC,LPRECT,LPARAM); -BOOL WINAPI clb_fCountMonitors(MHND hMon,HDC hDC,LPRECT rRect,LPARAM lP) -{ - g_nMonitorCounter ++; - return TRUE; -} -BOOL WINAPI clb_fCollectMonitors(MHND,HDC,LPRECT,LPARAM); -BOOL WINAPI clb_fCollectMonitors(MHND hMon,HDC hDC,LPRECT rRect,LPARAM lP) -{ - - if( (g_nMonitorCounter < g_nMonitorLimit) && (NULL != g_hmpMonitors) ) - { - g_hmpMonitors[g_nMonitorCounter] = hMon; - g_nMonitorCounter ++; - } - - return TRUE; -} -// Tools -void __normaRectPos(RECT*,RECT,RECT); -HWND __createWindow0(MHND,LPCTSTR,LPCTSTR,DWORD,int,int,int,int,HWND,HMENU,HANDLE,LPVOID); -HWND __createWindow1(MHND,LPCTSTR,LPCTSTR,DWORD,int,int,int,int,HWND,HMENU,HANDLE,LPVOID); -void __normaRectPos(RECT* rDest,RECT rSrc,RECT rNorma) -{ - int nDX = rSrc.right - rSrc.left; - int nDY = rSrc.bottom - rSrc.top; - - rDest->left = rSrc.left + rNorma.left; - rDest->top = rSrc.top + rNorma.top; - - rDest->right = rDest->left + nDX; - rDest->bottom = rDest->top + nDY; -} -HWND __createWindow0( MHND hmMonitor,LPCTSTR lpClassName,LPCTSTR lpWindowName, - DWORD dwStyle,int x,int y,int nWidth, - int nHeight,HWND hWndParent,HMENU hMenu, - HANDLE hInstance,LPVOID lpParam ) -{ - HWND retCode = NULL; - - if( (NULL != hmMonitor) && (NULL != lpClassName) && - (NULL != lpWindowName) && (NULL != hInstance) ) - { - RECT rRW = {0,0,0,0}; - RECT rRM = {0,0,0,0}; - RECT rSect = {0,0,0,0}; - - SetRect(&rRW,x,y,x+nWidth,y+nHeight); - - if( TRUE == _monitorBounds(hmMonitor,&rRM) ) - { - __normaRectPos(&rRW,rRW,rRM); - - IntersectRect(&rSect,&rRM,&rRW); - - if( TRUE == EqualRect(&rSect,&rRW) ) - { - x = rSect.left; - y = rSect.top; - nWidth = rSect.right - rSect.left; - nHeight = rSect.bottom - rSect.top; - retCode = CreateWindow( - lpClassName,lpWindowName, - dwStyle,x,y,nWidth, - nHeight,hWndParent,hMenu, - (HINSTANCE)hInstance,lpParam - ); - } else { - // A coisa indefinida. Nao tenho sabdoria o que - // fazer aqui mesmo - // E necessario perguntar Jeannette - } - } - } - - return retCode; -} -HWND __createWindow1( MHND hmMonitor,LPCTSTR lpClassName,LPCTSTR lpWindowName, - DWORD dwStyle,int x,int y,int nWidth, - int nHeight,HWND hWndParent,HMENU hMenu, - HANDLE hInstance,LPVOID lpParam ) -{ - HWND retCode = NULL; - - if( (NULL != hmMonitor) && (NULL != lpClassName) && - (NULL != lpWindowName) && (NULL != hInstance) ) - { - RECT rRM = {0,0,0,0}; - - if( TRUE == _monitorBounds(hmMonitor,&rRM) ) - { - HWND wW = NULL; - BOOL wasVisible = (0 != (dwStyle & WS_VISIBLE)); - - if( TRUE == wasVisible ) - { - dwStyle &= ~WS_VISIBLE; - } - - if( NULL != (wW = CreateWindow( - lpClassName,lpWindowName, - dwStyle,x,y,nWidth, - nHeight,hWndParent,hMenu, - (HINSTANCE)hInstance,lpParam - )) ) - { - RECT rRW = {0,0,0,0}; - RECT rSect = {0,0,0,0}; - - GetWindowRect(wW,&rRW); - - __normaRectPos(&rRW,rRW,rRM); - - IntersectRect(&rSect,&rRM,&rRW); - - if( TRUE == EqualRect(&rSect,&rRW) ) - { - x = rSect.left; - y = rSect.top; - nWidth = rSect.right - rSect.left; - nHeight = rSect.bottom - rSect.top; - - MoveWindow(wW,x,y,nWidth,nHeight,FALSE); - - if( TRUE == wasVisible ) - { - UpdateWindow(wW); - ShowWindow(wW,SW_SHOW); - } - - retCode = wW; - } else { - // A coisa indefinida. Nao sei o que - // fazer aqui. E necessario perguntar Jeannette - DestroyWindow(wW); - } - } - } - } - - return retCode; -} - -// Implementations -int WINAPI _countMonitors(void) -{ - g_nMonitorCounter = 0; - - _enumDisplayMonitors(NULL,NULL,clb_fCountMonitors,0L); - - return g_nMonitorCounter; - -} -int WINAPI _collectMonitors(MHND* hmpMonitors,int nNum) -{ - int retCode = 0; - - if( NULL != hmpMonitors ) - { - g_nMonitorCounter = 0; - g_nMonitorLimit = nNum; - g_hmpMonitors = hmpMonitors; - - _enumDisplayMonitors(NULL,NULL,clb_fCollectMonitors,0L); - - retCode = g_nMonitorCounter; - - g_nMonitorCounter = 0; - g_nMonitorLimit = 0; - g_hmpMonitors = NULL; - - } - return retCode; -} -BOOL WINAPI _monitorBounds(MHND hmMonitor,RECT* rpBounds) -{ - BOOL retCode = FALSE; - - if( (NULL != hmMonitor) && (NULL != rpBounds) ) - { - MONITOR_INFO miInfo; - - memset((void*)(&miInfo),0,sizeof(MONITOR_INFO)); - miInfo.dwSize = sizeof(MONITOR_INFO); - - if( TRUE == (retCode = _getMonitorInfo(hmMonitor,&(miInfo))) ) - { - (*rpBounds) = miInfo.rMonitor; - } - } - return retCode; -} - -HDC WINAPI _makeDCFromMonitor(MHND hmMonitor) { - HDC retCode = NULL; - - if( NULL != hmMonitor ) { - - MONITOR_INFO_EXTENDED mieInfo; - - memset((void*)(&mieInfo),0,sizeof(MONITOR_INFO_EXTENDED)); - mieInfo.dwSize = sizeof(MONITOR_INFO_EXTENDED); - - if( TRUE == _getMonitorInfo(hmMonitor,(PMONITOR_INFO)(&mieInfo)) ) { - HDC hDC = CreateDC(mieInfo.strDevice,NULL,NULL,NULL); - - if( NULL != hDC ) { - retCode = hDC; - } - } - } - return retCode; -} - -HWND WINAPI _createWindowOM( MHND hmMonitor,LPCTSTR lpClassName,LPCTSTR lpWindowName, - DWORD dwStyle,int x,int y,int nWidth, - int nHeight,HWND hWndParent,HMENU hMenu, - HANDLE hInstance,LPVOID lpParam ) -{ - if( (CW_USEDEFAULT == x) || (CW_USEDEFAULT == y) || - (CW_USEDEFAULT == nWidth) || (CW_USEDEFAULT == nHeight) ) - { - return __createWindow1 ( - hmMonitor,lpClassName,lpWindowName, - dwStyle,x,y,nWidth, - nHeight,hWndParent,hMenu, - hInstance,lpParam - ); - } - return __createWindow0 ( - hmMonitor,lpClassName,lpWindowName, - dwStyle,x,y,nWidth, - nHeight,hWndParent,hMenu, - hInstance,lpParam - ); -} diff --git a/jdk/src/windows/native/sun/windows/awt_MMStub.h b/jdk/src/windows/native/sun/windows/awt_MMStub.h deleted file mode 100644 index ec73dd74f37..00000000000 --- a/jdk/src/windows/native/sun/windows/awt_MMStub.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ -#ifndef _INC_MMSTUB -#define _INC_MMSTUB - -#ifndef _WINDOWS_ -#include "windows.h" -#endif - -#ifndef _AWT_H_ -#include "awt.h" -#endif - -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) - -/* Cdecl for C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Constants */ -#define SM_XVSCREEN 76 -#define SM_YVSCREEN 77 -#define SM_CXVSCREEN 78 -#define SM_CYVSCREEN 79 -#define SM_CMONITORS 80 -#define SM_SAMEDSPLFORMAT 81 - -#define MONITOR_DEFAULT_TO_NULL 0x00000000 -#define MONITOR_DEFAULT_TO_PRIMARY 0x00000001 -#define MONITOR_DEFAULT_TO_NEAR 0x00000002 - - - -#define MONITOR_INFO_FLAG_PRIMARY 0x00000001 - -#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001 -#define DISPLAY_DEVICE_MULTY_DRIVER 0x00000002 -#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004 -#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008 - - -#define DISPLAY_DEVICE_VGA 0x00000010 - -#define ENUM_CURRENT_SETTINGS ((DWORD)-1) -#define ENUM_REGISTRY_SETTINGS ((DWORD)-2) - -#define PRIMARY_MONITOR ((MHND)0x42) - - -#define DEV_NAME_LEN 32 -#define DEV_STR_LEN 128 - - -// Datatypes -typedef HANDLE MHND; -typedef BOOL (CALLBACK* MON_ENUM_CALLBACK_PROC)(MHND,HDC,LPRECT,LPARAM); - -typedef struct tagMONITOR_INFO -{ - DWORD dwSize; - RECT rMonitor; - RECT rWork; - DWORD dwFlags; -} MONITOR_INFO, *PMONITOR_INFO; - -typedef struct tagMONITOR_INFO_EXTENDED -{ - DWORD dwSize; - RECT rMonitor; - RECT rWork; - DWORD dwFlags; - TCHAR strDevice[DEV_NAME_LEN]; -} MONITOR_INFO_EXTENDED, *PMONITOR_INFO_EXTENDED; - -typedef struct tagDISPLAY_DEVICE -{ - DWORD dwSize; - WCHAR strDevName[DEV_NAME_LEN]; - WCHAR strDevString[DEV_STR_LEN]; - DWORD dwFlags; - WCHAR deviceID[128]; - WCHAR deviceKey[128]; -} _DISPLAY_DEVICE, *P_DISPLAY_DEVICE; - -/* Basic API's */ -BOOL WINAPI _enumDisplayMonitors(HDC,LPCRECT,MON_ENUM_CALLBACK_PROC,LPARAM); -BOOL WINAPI _enumDisplayDevices (LPVOID,int,P_DISPLAY_DEVICE,DWORD); -BOOL WINAPI _getMonitorInfo (MHND,PMONITOR_INFO); -MHND WINAPI _monitorFromPoint (POINT,UINT); -MHND WINAPI _monitorFromWindow (HWND,UINT); -MHND WINAPI _monitorFromRect (LPCRECT,UINT); -int WINAPI _getSystemMetrics (int); - -/* Additional API's */ -int WINAPI _countMonitors (void); -int WINAPI _collectMonitors (MHND*,int); -BOOL WINAPI _monitorBounds (MHND,RECT*); -HDC WINAPI _makeDCFromMonitor (MHND); -HWND WINAPI _createWindowOM (MHND,LPCTSTR,LPCTSTR,DWORD,int,int,int, - int,HWND,HMENU,HANDLE,LPVOID); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) */ - -#endif /* _INC_MMSTUB */ diff --git a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp index 626b3a31368..51fc47718cb 100644 --- a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp +++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include "awt_MenuItem.h" #include "awt_Menu.h" #include "awt_MenuBar.h" @@ -70,7 +71,6 @@ jmethodID AwtMenuItem::getDefaultFontMID; LANGID AwtMenuItem::m_idLang = LOWORD(GetKeyboardLayout(0)); UINT AwtMenuItem::m_CodePage = AwtMenuItem::LangToCodePage(AwtMenuItem::m_idLang); -BOOL AwtMenuItem::m_isWin95 = IS_WIN95; BOOL AwtMenuItem::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC || PRIMARYLANGID(GetInputLanguage()) == LANG_HEBREW; BOOL AwtMenuItem::sm_rtlReadingOrder = @@ -150,7 +150,7 @@ BOOL AwtMenuItem::CheckMenuCreation(JNIEnv *env, jobject self, HMENU hMenu) jobject createError = NULL; if (dw == ERROR_OUTOFMEMORY) { - jstring errorMsg = env->NewStringUTF("too many menu handles"); + jstring errorMsg = JNU_NewStringPlatform(env, L"too many menu handles"); createError = JNU_NewObjectByName(env, "java/lang/OutOfMemoryError", "(Ljava/lang/String;)V", errorMsg); @@ -435,16 +435,7 @@ void AwtMenuItem::DrawItem(DRAWITEMSTRUCT& drawInfo) if (drawInfo.itemID != m_Id) return; - /* Fixed bug 4349969. Since the problem occurs on Windows 98 and not on - Windows NT, the fix is to check for Windows 95/98 and to check if the - handle to the menu of the item to be drawn is the same as the handle to the - menu of the menu object. If they're not the same, just return and don't do - the drawing. - */ - if ( IS_WIN95 && drawInfo.hwndItem != (HWND)this->m_menuContainer->GetHMenu()) { - return; - } else - DrawSelf(drawInfo); + DrawSelf(drawInfo); } void AwtMenuItem::MeasureSelf(HDC hDC, MEASUREITEMSTRUCT& measureInfo) @@ -802,8 +793,9 @@ BOOL AwtMenuItem::IsSeparator() { jobject jitem = GetTarget(env); jstring label = (jstring)(env)->GetObjectField(jitem, AwtMenuItem::labelID); - LPWSTR labelW = TO_WSTRING(label); + LPCWSTR labelW = JNU_GetStringPlatformChars(env, label, NULL); BOOL isSeparator = (labelW && (wcscmp(labelW, L"-") == 0)); + JNU_ReleaseStringPlatformChars(env, label, labelW); env->DeleteLocalRef(label); env->DeleteLocalRef(jitem); diff --git a/jdk/src/windows/native/sun/windows/awt_Object.cpp b/jdk/src/windows/native/sun/windows/awt_Object.cpp index aab7e98b502..b6b999be2a7 100644 --- a/jdk/src/windows/native/sun/windows/awt_Object.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Object.cpp @@ -25,9 +25,6 @@ #include "awt_Object.h" #include "ObjectList.h" -#ifdef DEBUG -#include "awt_Unicode.h" -#endif #ifdef DEBUG static BOOL reportEvents = FALSE; @@ -116,8 +113,9 @@ AwtObject::DoCallback(const char* methodName, const char* methodSig, ...) "getName", "()Ljava/lang/String;").l; DASSERT(!safe_ExceptionOccurred(env)); - printf("Posting %s%s method to %S\n", methodName, methodSig, - TO_WSTRING(targetStr)); + LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL); + printf("Posting %s%s method to %S\n", methodName, methodSig, targetStrW); + JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW); } #endif /* caching would do much good here */ @@ -148,8 +146,11 @@ void AwtObject::SendEvent(jobject event) (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),"getName", "()Ljava/lang/String;").l; DASSERT(!safe_ExceptionOccurred(env)); - printf("Posting %S to %S\n", TO_WSTRING(eventStr), - TO_WSTRING(targetStr)); + LPCWSTR eventStrW = JNU_GetStringPlatformChars(env, eventStr, NULL); + LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL); + printf("Posting %S to %S\n", eventStrW, targetStrW); + JNU_ReleaseStringPlatformChars(env, eventStr, eventStrW); + JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW); } #endif /* Post event to the system EventQueue. */ diff --git a/jdk/src/windows/native/sun/windows/awt_Palette.cpp b/jdk/src/windows/native/sun/windows/awt_Palette.cpp index ea0488e816f..a567c246d86 100644 --- a/jdk/src/windows/native/sun/windows/awt_Palette.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Palette.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ * have any questions. */ -#include +#include "awt.h" #include "awt_Palette.h" #include "awt_Component.h" #include "img_util_md.h" diff --git a/jdk/src/windows/native/sun/windows/awt_PopupMenu.cpp b/jdk/src/windows/native/sun/windows/awt_PopupMenu.cpp index 8862b86bda7..794277eda24 100644 --- a/jdk/src/windows/native/sun/windows/awt_PopupMenu.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PopupMenu.cpp @@ -234,11 +234,13 @@ void AwtPopupMenu::Enable(BOOL isEnabled) jobject jitem = item->GetTarget(env); BOOL bItemEnabled = isEnabled && (jboolean)env->GetBooleanField(jitem, AwtMenuItem::enabledID); - LPWSTR labelW = TO_WSTRING((jstring)env->GetObjectField(jitem, - AwtMenuItem::labelID)); - if (labelW != NULL && wcscmp(labelW,L"-") != 0) { + jstring labelStr = static_cast(env->GetObjectField(jitem, AwtMenuItem::labelID)); + LPCWSTR labelStrW = JNU_GetStringPlatformChars(env, labelStr, NULL); + if (labelStrW && wcscmp(labelStrW, L"-") != 0) { item->Enable(bItemEnabled); } + JNU_ReleaseStringPlatformChars(env, labelStr, labelStrW); + env->DeleteLocalRef(labelStr); env->DeleteLocalRef(jitem); } env->DeleteLocalRef(target); diff --git a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp index 486d9f66950..cc562ec0056 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,16 +108,13 @@ BOOL AwtPrintControl::FindPrinter(jstring printerName, LPBYTE pPrinterEnum, { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - BOOL nt = IS_NT; DWORD cReturned = 0; if (pPrinterEnum == NULL) { // Compute size of buffer DWORD cbNeeded = 0; - if (nt) { - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &cbNeeded, &cReturned); - } ::EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, pcbBuf, &cReturned); if (cbNeeded > (*pcbBuf)) { @@ -139,65 +136,63 @@ BOOL AwtPrintControl::FindPrinter(jstring printerName, LPBYTE pPrinterEnum, // doesn't support port searches. So, if the user has specified the // printer name as "LPT1:" (even though this is actually a port // name), we won't find the printer here. - if (nt) { - if (!::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - NULL, 4, pPrinterEnum, cbBuf, &dummyWord, &cReturned)) { - return FALSE; - } + if (!::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + NULL, 4, pPrinterEnum, cbBuf, &dummyWord, &cReturned)) { + return FALSE; + } - for (DWORD i = 0; i < cReturned; i++) { - PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) - (pPrinterEnum + i * sizeof(PRINTER_INFO_4)); - if (info4->pPrinterName != NULL && - _tcsicmp(lpcPrinterName, info4->pPrinterName) == 0) { + for (DWORD i = 0; i < cReturned; i++) { + PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) + (pPrinterEnum + i * sizeof(PRINTER_INFO_4)); + if (info4->pPrinterName != NULL && + _tcsicmp(lpcPrinterName, info4->pPrinterName) == 0) { - // Fix for BugTraq Id 4281380. - // Get the port name since some drivers may require - // this name to be passed to ::DeviceCapabilities(). - HANDLE hPrinter = NULL; - if (::OpenPrinter(info4->pPrinterName, &hPrinter, NULL)) { - // Fix for BugTraq Id 4286812. - // Some drivers don't support PRINTER_INFO_5. - // In this case we try PRINTER_INFO_2, and if that - // isn't supported as well return NULL port name. - try { - if (AwtPrintControl::IsSupportedLevel(hPrinter, 5)) { - VERIFY(::GetPrinter(hPrinter, 5, pPrinterEnum, cbBuf, - &dummyWord)); - PRINTER_INFO_5 *info5 = (PRINTER_INFO_5 *)pPrinterEnum; - *foundPrinter = info5->pPrinterName; - // pPortName may specify multiple ports. We only want one. - *foundPort = (info5->pPortName != NULL) - ? _tcstok(info5->pPortName, TEXT(",")) : NULL; - } else if (AwtPrintControl::IsSupportedLevel(hPrinter, 2)) { - VERIFY(::GetPrinter(hPrinter, 2, pPrinterEnum, cbBuf, - &dummyWord)); - PRINTER_INFO_2 *info2 = (PRINTER_INFO_2 *)pPrinterEnum; - *foundPrinter = info2->pPrinterName; - // pPortName may specify multiple ports. We only want one. - *foundPort = (info2->pPortName != NULL) - ? _tcstok(info2->pPortName, TEXT(",")) : NULL; - } else { - *foundPrinter = info4->pPrinterName; - // We failed to determine port name for the found printer. - *foundPort = NULL; - } - } catch (std::bad_alloc&) { - VERIFY(::ClosePrinter(hPrinter)); - throw; + // Fix for BugTraq Id 4281380. + // Get the port name since some drivers may require + // this name to be passed to ::DeviceCapabilities(). + HANDLE hPrinter = NULL; + if (::OpenPrinter(info4->pPrinterName, &hPrinter, NULL)) { + // Fix for BugTraq Id 4286812. + // Some drivers don't support PRINTER_INFO_5. + // In this case we try PRINTER_INFO_2, and if that + // isn't supported as well return NULL port name. + try { + if (AwtPrintControl::IsSupportedLevel(hPrinter, 5)) { + VERIFY(::GetPrinter(hPrinter, 5, pPrinterEnum, cbBuf, + &dummyWord)); + PRINTER_INFO_5 *info5 = (PRINTER_INFO_5 *)pPrinterEnum; + *foundPrinter = info5->pPrinterName; + // pPortName may specify multiple ports. We only want one. + *foundPort = (info5->pPortName != NULL) + ? _tcstok(info5->pPortName, TEXT(",")) : NULL; + } else if (AwtPrintControl::IsSupportedLevel(hPrinter, 2)) { + VERIFY(::GetPrinter(hPrinter, 2, pPrinterEnum, cbBuf, + &dummyWord)); + PRINTER_INFO_2 *info2 = (PRINTER_INFO_2 *)pPrinterEnum; + *foundPrinter = info2->pPrinterName; + // pPortName may specify multiple ports. We only want one. + *foundPort = (info2->pPortName != NULL) + ? _tcstok(info2->pPortName, TEXT(",")) : NULL; + } else { + *foundPrinter = info4->pPrinterName; + // We failed to determine port name for the found printer. + *foundPort = NULL; } - + } catch (std::bad_alloc&) { VERIFY(::ClosePrinter(hPrinter)); - - return TRUE; + throw; } - return FALSE; + VERIFY(::ClosePrinter(hPrinter)); + + return TRUE; } + + return FALSE; } } - // We still haven't found the printer, or we're using 95/98. + // We still haven't found the printer, /* or we're using 95/98. */ // PRINTER_INFO_5 supports both printer name and port name, so // we'll test both. On NT, PRINTER_ENUM_LOCAL means just local // printers. This is what we want, because we already tested all @@ -213,28 +208,17 @@ BOOL AwtPrintControl::FindPrinter(jstring printerName, LPBYTE pPrinterEnum, for (DWORD i = 0; i < cReturned; i++) { PRINTER_INFO_5 *info5 = (PRINTER_INFO_5 *) (pPrinterEnum + i * sizeof(PRINTER_INFO_5)); - if (nt) { - // pPortName can specify multiple ports. Test them one at - // a time. - if (info5->pPortName != NULL) { - LPTSTR port = _tcstok(info5->pPortName, TEXT(",")); - while (port != NULL) { - if (_tcsicmp(lpcPrinterName, port) == 0) { - *foundPrinter = info5->pPrinterName; - *foundPort = port; - return TRUE; - } - port = _tcstok(NULL, TEXT(",")); + // pPortName can specify multiple ports. Test them one at + // a time. + if (info5->pPortName != NULL) { + LPTSTR port = _tcstok(info5->pPortName, TEXT(",")); + while (port != NULL) { + if (_tcsicmp(lpcPrinterName, port) == 0) { + *foundPrinter = info5->pPrinterName; + *foundPort = port; + return TRUE; } - } - } else { - if ((info5->pPrinterName != NULL && - _tcsicmp(lpcPrinterName, info5->pPrinterName) == 0) || - (info5->pPortName != NULL && - _tcsicmp(lpcPrinterName, info5->pPortName) == 0)) { - *foundPrinter = info5->pPrinterName; - *foundPort = info5->pPortName; - return TRUE; + port = _tcstok(NULL, TEXT(",")); } } } @@ -400,13 +384,11 @@ BOOL AwtPrintControl::CreateDevModeAndDevNames(PRINTDLG *ppd, } // Create DEVNAMES. - if (IS_NT) { - if (pPortName != NULL) { - info2->pPortName = pPortName; - } else if (info2->pPortName != NULL) { - // pPortName may specify multiple ports. We only want one. - info2->pPortName = _tcstok(info2->pPortName, TEXT(",")); - } + if (pPortName != NULL) { + info2->pPortName = pPortName; + } else if (info2->pPortName != NULL) { + // pPortName may specify multiple ports. We only want one. + info2->pPortName = _tcstok(info2->pPortName, TEXT(",")); } size_t lenDriverName = ((info2->pDriverName != NULL) diff --git a/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp b/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp index d9e738411ae..762ae2673eb 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintDialog.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,10 @@ * have any questions. */ +#include "awt.h" #include "awt_PrintDialog.h" #include "awt_Dialog.h" #include "awt_PrintControl.h" -#include "awt_dlls.h" #include "awt_Window.h" #include "ComCtl32Util.h" #include @@ -39,11 +39,9 @@ jmethodID AwtPrintDialog::setHWndMID; BOOL AwtPrintDialog::PrintDlg(LPPRINTDLG data) { - AwtCommDialog::load_comdlg_procs(); return static_cast(reinterpret_cast( AwtToolkit::GetInstance().InvokeFunction( - reinterpret_cast(AwtCommDialog::PrintDlgWrapper), - data))); + reinterpret_cast(::PrintDlg), data))); } LRESULT CALLBACK PrintDialogWndProc(HWND hWnd, UINT message, diff --git a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp index 0ecd0388ac0..9136b786412 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include #include #include @@ -30,10 +31,9 @@ #include #include -#include "awt.h" -#include "awt_dlls.h" #include "awt_Toolkit.h" #include "awt_Component.h" +#include "awt_Dialog.h" #include "awt_Font.h" #include "awt_PrintDialog.h" #include "awt_PrintControl.h" @@ -422,7 +422,7 @@ Java_sun_awt_windows_WPageDialogPeer__1show(JNIEnv *env, jobject peer) */ if (AwtPrintControl::getPrintHDMode(env, self) == NULL || AwtPrintControl::getPrintHDName(env,self) == NULL) { - (void)AwtCommDialog::PageSetupDlg(&setup); + (void)::PageSetupDlg(&setup); /* check if hDevMode and hDevNames are set. * If both are null, then there is no default printer. */ @@ -460,7 +460,7 @@ Java_sun_awt_windows_WPageDialogPeer__1show(JNIEnv *env, jobject peer) AwtDialog::CheckInstallModalHook(); - BOOL ret = AwtCommDialog::PageSetupDlg(&setup); + BOOL ret = ::PageSetupDlg(&setup); if (ret) { jobject paper = getPaper(env, page); @@ -733,7 +733,7 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self, pd.lStructSize = sizeof(PRINTDLG); pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC; - if (AwtCommDialog::PrintDlg(&pd)) { + if (::PrintDlg(&pd)) { printDC = pd.hDC; hDevMode = pd.hDevMode; hDevNames = pd.hDevNames; @@ -1838,10 +1838,6 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WPrinterJob_selectStylePen (JNIEnv *env, jobject self, jlong printDC, jlong cap, jlong join, jfloat width, jint red, jint green, jint blue) { - /* End cap and line join styles are not supported in Win 9x. */ - if (IS_WIN95) - return JNI_FALSE; - TRY; LOGBRUSH logBrush; @@ -1879,23 +1875,13 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WPrinterJob_setFont { jboolean didSetFont = JNI_FALSE; - if (IS_NT) { - didSetFont = jFontToWFontW(env, (HDC)printDC, + didSetFont = jFontToWFontW(env, (HDC)printDC, fontName, fontSize, isBold, isItalic, rotation, awScale); - } else { - didSetFont = jFontToWFontA(env, (HDC)printDC, - fontName, - fontSize, - isBold, - isItalic, - rotation, - awScale); - } return didSetFont; } @@ -1919,7 +1905,7 @@ static jboolean jFontToWFontA(JNIEnv *env, HDC printDC, jstring fontName, memset(&matchedLogFont, 0, sizeof(matchedLogFont)); - WCHAR* name = TO_WSTRING(fontName); + LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL); /* Some fontnames of Non-ASCII fonts like 'MS Minchou' are themselves @@ -1928,14 +1914,14 @@ static jboolean jFontToWFontA(JNIEnv *env, HDC printDC, jstring fontName, */ int maxlen = static_cast(sizeof(lf.lfFaceName)) - 1; // maxlen is int due to cbMultiByte parameter is int - int destLen = WideCharToMultiByte(CP_ACP, // convert to ASCII code page - 0, // flags - name, // Unicode string - -1, // Unicode length is calculated automatically + int destLen = WideCharToMultiByte(CP_ACP, // convert to ASCII code page + 0, // flags + fontNameW, // Unicode string + -1, // Unicode length is calculated automatically lf.lfFaceName, // Put ASCII string here - maxlen, // max len - NULL, // default handling of unmappables - NULL);// do not care if def char is used + maxlen, // max len + NULL, // default handling of unmappables + NULL); // do not care if def char is used /* If WideCharToMultiByte succeeded then the number * of bytes it copied into the face name buffer will @@ -2018,9 +2004,10 @@ static jboolean jFontToWFontA(JNIEnv *env, HDC printDC, jstring fontName, } else { foundFont = false; } - } + JNU_ReleaseStringPlatformChars(env, fontName, fontNameW); + return foundFont ? JNI_TRUE : JNI_FALSE; } @@ -2043,27 +2030,29 @@ static jboolean jFontToWFontW(JNIEnv *env, HDC printDC, jstring fontName, memset(&matchedLogFont, 0, sizeof(matchedLogFont)); + LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL); + /* Describe the GDI fonts we want enumerated. We * simply supply the java font name and let GDI * do the matching. If the java font name is * longer than the GDI maximum font lenght then * we can't convert the font. */ - WCHAR* name = TO_WSTRING(fontName); - size_t nameLen = wcslen(name); - + size_t nameLen = wcslen(fontNameW); if (nameLen < (sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0]))) { - wcscpy(lf.lfFaceName, name); + wcscpy(lf.lfFaceName, fontNameW); lf.lfCharSet = DEFAULT_CHARSET; lf.lfPitchAndFamily = 0; - foundFont = !EnumFontFamiliesExW((HDC)printDC, &lf, + foundFont = !::EnumFontFamiliesEx((HDC)printDC, &lf, (FONTENUMPROCW) fontEnumProcW, (LPARAM) &matchedLogFont, 0); } + JNU_ReleaseStringPlatformChars(env, fontName, fontNameW); + if (!foundFont) { return JNI_FALSE; } @@ -2100,7 +2089,7 @@ static jboolean jFontToWFontW(JNIEnv *env, HDC printDC, jstring fontName, //Debug: dumpLogFont(&matchedLogFont); - HFONT font = CreateFontIndirectW(&matchedLogFont); + HFONT font = ::CreateFontIndirect(&matchedLogFont); if (font == NULL) { return JNI_FALSE; } @@ -2123,7 +2112,7 @@ static jboolean jFontToWFontW(JNIEnv *env, HDC printDC, jstring fontName, GetTextMetrics(printDC, &tm); avgWidth = tm.tmAveCharWidth; matchedLogFont.lfWidth = (LONG)((fabs)(avgWidth*awScale)); - font = CreateFontIndirectW(&matchedLogFont); + font = ::CreateFontIndirect(&matchedLogFont); if (font == NULL) { return JNI_FALSE; } @@ -2230,14 +2219,11 @@ JNIEXPORT jint JNICALL Java_sun_awt_windows_WPrinterJob_getGDIAdvance (JNIEnv *env, jobject self, jlong printDC, jstring text) { SIZE size; - LPWSTR wText = TO_WSTRING(text); + LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL); size_t strLen = wcslen(wText); BOOL ok = GetTextExtentPoint32((HDC)printDC, wText, (int)strLen, &size); - if (ok) { - return size.cx; - } else { - return 0; - } + JNU_ReleaseStringPlatformChars(env, text, wText); + return ok ? size.cx : 0; } @@ -2288,7 +2274,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_textOut long posX = ROUND_TO_LONG(x); long posY = ROUND_TO_LONG(y); int flags = (glyphCodes !=0) ? ETO_GLYPH_INDEX : 0; - LPWSTR wText = TO_WSTRING(text); + LPCWSTR wText = JNU_GetStringPlatformChars(env, text, NULL); int *advances = NULL, *xadvances = NULL, *xyadvances = NULL; BOOL useYAdvances = FALSE; @@ -2359,7 +2345,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_textOut *inxyAdvances = 0; } - if (useYAdvances && IS_WIN2000) { + if (useYAdvances) { advances = xyadvances; flags |= J2D_ETO_PDY; } else { @@ -2371,7 +2357,7 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_textOut env->ReleaseFloatArrayElements(positions, glyphPos, JNI_ABORT); } - BOOL drawn = ::ExtTextOutW( (HDC)printDC, + BOOL drawn = ::ExtTextOut((HDC)printDC, posX, posY, // starting position for the text flags, // glyphCodes?, y advances? NULL, // optional clipping-opaquing rectangle @@ -2385,6 +2371,8 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_textOut if (xyadvances != NULL) { free(xyadvances); } + + JNU_ReleaseStringPlatformChars(env, text, wText); } /** @@ -2968,7 +2956,7 @@ static HDC getDefaultPrinterDC(JNIEnv *env, jobject printerJob) { pd.lStructSize = sizeof(PRINTDLG); pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC; - if (AwtCommDialog::PrintDlg(&pd)) { + if (::PrintDlg(&pd)) { printDC = pd.hDC; /* Find out how many copies the driver can do, and use driver's diff --git a/jdk/src/windows/native/sun/windows/awt_Robot.cpp b/jdk/src/windows/native/sun/windows/awt_Robot.cpp index 15a9a243fd1..e774f5160db 100644 --- a/jdk/src/windows/native/sun/windows/awt_Robot.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Robot.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * have any questions. */ +#include "awt.h" #include "awt_Toolkit.h" #include "awt_Component.h" #include "awt_Robot.h" @@ -30,8 +31,6 @@ #include "java_awt_event_InputEvent.h" #include -static const int MOUSE_MAX = 65535; - AwtRobot::AwtRobot( jobject peer ) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -44,11 +43,11 @@ AwtRobot::~AwtRobot() } #ifndef SPI_GETMOUSESPEED -#define SPI_GETMOUSESPEED 112 +#define SPI_GETMOUSESPEED 112 #endif #ifndef SPI_SETMOUSESPEED -#define SPI_SETMOUSESPEED 113 +#define SPI_SETMOUSESPEED 113 #endif void AwtRobot::MouseMove( jint x, jint y) @@ -102,19 +101,38 @@ void AwtRobot::MousePress( jint buttonMask ) // left handed mouse setup BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON); - if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) + { dwFlags |= MOUSEEVENTF_MIDDLEDOWN; } - mouse_event(dwFlags, 0, 0, 0, 0 ); + INPUT mouseInput = {0}; + mouseInput.type = INPUT_MOUSE; + mouseInput.mi.time = 0; + mouseInput.mi.dwFlags = dwFlags; + if ( buttonMask & AwtComponent::masks[3] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN; + mouseInput.mi.mouseData = XBUTTON1; + } + + if ( buttonMask & AwtComponent::masks[4] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN; + mouseInput.mi.mouseData = XBUTTON2; + } + ::SendInput(1, &mouseInput, sizeof(mouseInput)); } void AwtRobot::MouseRelease( jint buttonMask ) @@ -125,61 +143,43 @@ void AwtRobot::MouseRelease( jint buttonMask ) // left handed mouse setup BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON); - if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) + { dwFlags |= MOUSEEVENTF_MIDDLEUP; } - mouse_event(dwFlags, 0, 0, 0, 0 ); + INPUT mouseInput = {0}; + mouseInput.type = INPUT_MOUSE; + mouseInput.mi.time = 0; + mouseInput.mi.dwFlags = dwFlags; + + if ( buttonMask & AwtComponent::masks[3] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP; + mouseInput.mi.mouseData = XBUTTON1; + } + + if ( buttonMask & AwtComponent::masks[4] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP; + mouseInput.mi.mouseData = XBUTTON2; + } + ::SendInput(1, &mouseInput, sizeof(mouseInput)); } void AwtRobot::MouseWheel (jint wheelAmt) { - if (IS_WIN95 && !IS_WIN98) { - // Other win32 platforms do nothing for mouse_event(0), so - // do nothing on 95, too. - if (wheelAmt == 0) { - return; - } - - // Win95 doesn't understand MOUSEEVENTF_WHEEL, so use PostEvent - POINT curPos; - HWND mouseOver = NULL; - HWND topLevel = NULL; - UINT wheelMsg = NULL; - - if (::GetCursorPos((LPPOINT)&curPos) == 0) { - return; - } - // get hwnd of top-level container - mouseOver = ::WindowFromPoint(curPos); - DASSERT(mouseOver); - topLevel = AwtComponent::GetTopLevelParentForWindow(mouseOver); - DASSERT(topLevel); - - if (::ScreenToClient(topLevel, (LPPOINT)&curPos) == 0) { - return; - } - wheelMsg = AwtComponent::Wheel95GetMsg(); - - if (wheelMsg == NULL) { - return; - } - - ::PostMessage(topLevel, - wheelMsg, - wheelAmt * -1 * WHEEL_DELTA, - MAKELPARAM((WORD)curPos.x, (WORD)curPos.y)); - } - else { - mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheelAmt * -1 * WHEEL_DELTA, 0); - } + mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheelAmt * -1 * WHEEL_DELTA, 0); } inline jint AwtRobot::WinToJavaPixel(USHORT r, USHORT g, USHORT b) @@ -437,3 +437,9 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_keyRelease( CATCH_BAD_ALLOC; } + +JNIEXPORT jint JNICALL Java_sun_awt_windows_WRobotPeer_getNumberOfButtons( + JNIEnv *, jobject self) +{ + return GetSystemMetrics(SM_CMOUSEBUTTONS); +} diff --git a/jdk/src/windows/native/sun/windows/awt_Robot.h b/jdk/src/windows/native/sun/windows/awt_Robot.h index ec25746e7b3..ba532c74821 100644 --- a/jdk/src/windows/native/sun/windows/awt_Robot.h +++ b/jdk/src/windows/native/sun/windows/awt_Robot.h @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,13 +42,13 @@ class AwtRobot : public AwtObject void MouseRelease( jint buttonMask ); void MouseWheel(jint wheelAmt); + jint getNumberOfButtons(); jint GetRGBPixel( jint x, jint y); void GetRGBPixels(jint x, jint y, jint width, jint height, jintArray pixelArray); void KeyPress( jint key ); void KeyRelease( jint key ); - static AwtRobot * GetRobot( jobject self ); private: diff --git a/jdk/src/windows/native/sun/windows/awt_ScrollPane.cpp b/jdk/src/windows/native/sun/windows/awt_ScrollPane.cpp index 3975a3fd8d5..4d41e0b0cbe 100644 --- a/jdk/src/windows/native/sun/windows/awt_ScrollPane.cpp +++ b/jdk/src/windows/native/sun/windows/awt_ScrollPane.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,13 +108,6 @@ AwtScrollPane* AwtScrollPane::Create(jobject self, jobject parent) { DWORD style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - if (!IS_WIN4X) { - /* - * It's been decided by the UI folks that 3.X ScrollPanes - * should have borders... - */ - style |= WS_BORDER; - } jint scrollbarDisplayPolicy = env->GetIntField(target, scrollbarDisplayPolicyID); @@ -122,7 +115,7 @@ AwtScrollPane* AwtScrollPane::Create(jobject self, jobject parent) == java_awt_ScrollPane_SCROLLBARS_ALWAYS) { style |= WS_HSCROLL | WS_VSCROLL; } - DWORD exStyle = IS_WIN4X ? WS_EX_CLIENTEDGE : 0; + DWORD exStyle = WS_EX_CLIENTEDGE; if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; @@ -225,15 +218,8 @@ void AwtScrollPane::RecalcSizes(int parentWidth, int parentHeight, } /* Determine border width without scrollbars. */ - int horzBorder; - int vertBorder; - if (IS_WIN4X) { - horzBorder = ::GetSystemMetrics(SM_CXEDGE); - vertBorder = ::GetSystemMetrics(SM_CYEDGE); - } else { - horzBorder = ::GetSystemMetrics(SM_CXBORDER); - vertBorder = ::GetSystemMetrics(SM_CYBORDER); - } + int horzBorder = ::GetSystemMetrics(SM_CXEDGE);; + int vertBorder = ::GetSystemMetrics(SM_CYEDGE);; parentWidth -= (horzBorder * 2); parentHeight -= (vertBorder * 2); diff --git a/jdk/src/windows/native/sun/windows/awt_TextArea.cpp b/jdk/src/windows/native/sun/windows/awt_TextArea.cpp index 92a36b7a1a9..e0d4c6158c2 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextArea.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TextArea.cpp @@ -26,10 +26,8 @@ #include "awt_Toolkit.h" #include "awt_TextArea.h" #include "awt_TextComponent.h" -#include "awt_dlls.h" #include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" -#include "awt_Unicode.h" #include "awt_Window.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. @@ -50,7 +48,6 @@ struct ReplaceTextStruct { jfieldID AwtTextArea::scrollbarVisibilityID; WNDPROC AwtTextArea::sm_pDefWindowProc = NULL; -BOOL AwtTextArea::sm_RichEdit20 = (IS_WIN98 || IS_NT); /************************************************************************ * AwtTextArea methods @@ -78,8 +75,12 @@ void AwtTextArea::Dispose() } LPCTSTR AwtTextArea::GetClassName() { - load_rich_edit_library(); - return sm_RichEdit20 ? RICHEDIT_CLASS : TEXT("RICHEDIT"); + static BOOL richedLibraryLoaded = FALSE; + if (!richedLibraryLoaded) { + ::LoadLibrary(TEXT("RICHED20.DLL")); + richedLibraryLoaded = TRUE; + } + return RICHEDIT_CLASS; } /* Create a new AwtTextArea object and window. */ @@ -134,9 +135,8 @@ AwtTextArea* AwtTextArea::Create(jobject peer, jobject parent) * scrollbars instead of hiding them when not needed. */ DWORD style = WS_CHILD | WS_CLIPSIBLINGS | ES_LEFT | ES_MULTILINE | - ES_WANTRETURN | scroll_style | - (IS_WIN4X ? 0 : WS_BORDER) | ES_DISABLENOSCROLL; - DWORD exStyle = IS_WIN4X ? WS_EX_CLIENTEDGE : 0; + ES_WANTRETURN | scroll_style | ES_DISABLENOSCROLL; + DWORD exStyle = WS_EX_CLIENTEDGE; if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; if (GetRTLReadingOrder()) @@ -169,9 +169,7 @@ AwtTextArea* AwtTextArea::Create(jobject peer, jobject parent) // end-of-document marker or carriage return, // to format paragraphs. // kdm@sparc.spb.su - if (sm_RichEdit20) { - c->SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0); - } + c->SendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0); c->m_backgroundColorSet = TRUE; /* suppress inheriting parent's color. */ @@ -242,7 +240,7 @@ size_t AwtTextArea::CountNewLines(JNIEnv *env, jstring jStr, size_t maxlen) */ size_t length = env->GetStringLength(jStr) + 1; WCHAR *string = new WCHAR[length]; - env->GetStringRegion(jStr, 0, static_cast(length - 1), string); + env->GetStringRegion(jStr, 0, static_cast(length - 1), reinterpret_cast(string)); string[length-1] = '\0'; for (size_t i = 0; i < maxlen && i < length - 1; i++) { if (string[i] == L'\n') { @@ -461,12 +459,7 @@ AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { /* Check if all the text is selected. */ if (cr.cpMin == 0) { - int len = 0; - if (m_isWin95) { - len = ::GetWindowTextLengthA(GetHWnd()); - } else { - len = ::GetWindowTextLengthW(GetHWnd()); - } + int len = ::GetWindowTextLength(GetHWnd()); if (cr.cpMin == 0 && cr.cpMax >= len) { /* * All the text is selected in RichEdit - select all the @@ -738,14 +731,8 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) // kdm@sparc.spb.su UINT platfScrollLines = 3; // Retrieve a number of scroll lines. - if (!sm_RichEdit20) { - // 95 doesn't understand the SPI_GETWHEELSCROLLLINES - get the user - // preference by other means - platfScrollLines = Wheel95GetScrLines(); - } else { - ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, - &platfScrollLines, 0); - } + ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, + &platfScrollLines, 0); if (platfScrollLines > 0) { HWND hWnd = GetHWnd(); @@ -838,23 +825,6 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) return returnVal; } -int AwtTextArea::GetText(LPTSTR buffer, int size) -{ - // Due to a known limitation of the MSLU, GetWindowText cannot be - // issued for the Unicode RichEdit control on Win9x. Use EM_GETTEXTEX instead. - if (sm_RichEdit20 && !IS_NT) { - GETTEXTEX gte; - gte.cb = size * sizeof(TCHAR); - gte.flags = GT_USECRLF; - gte.codepage = 1200; // implies Unicode - gte.lpDefaultChar = NULL; - gte.lpUsedDefChar = NULL; - return (int)SendMessage(EM_GETTEXTEX, (WPARAM)>e, (LPARAM)buffer); - } else { - return ::GetWindowText(GetHWnd(), buffer, size); - } -} - /* * WM_CTLCOLOR is not sent by rich edit controls. * Use EM_SETCHARFORMAT and EM_SETBKGNDCOLOR to set @@ -984,16 +954,16 @@ void AwtTextArea::_ReplaceText(void *param) jsize length = env->GetStringLength(text) + 1; // Bugid 4141477 - Can't use TO_WSTRING here because it uses alloca // WCHAR* buffer = TO_WSTRING(text); - WCHAR *buffer = new WCHAR[length]; - env->GetStringRegion(text, 0, length-1, buffer); + TCHAR *buffer = new TCHAR[length]; + env->GetStringRegion(text, 0, length-1, reinterpret_cast(buffer)); buffer[length-1] = '\0'; c->CheckLineSeparator(buffer); c->RemoveCR(buffer); // Fix for 5003402: added restoring/hiding selection to enable automatic scrolling c->SendMessage(EM_HIDESELECTION, FALSE, TRUE); - c->SendMessageW(EM_SETSEL, start, end); - c->SendMessageW(EM_REPLACESEL, FALSE, (LPARAM)buffer); + c->SendMessage(EM_SETSEL, start, end); + c->SendMessage(EM_REPLACESEL, FALSE, (LPARAM)buffer); c->SendMessage(EM_HIDESELECTION, TRUE, TRUE); delete[] buffer; @@ -1187,12 +1157,11 @@ AwtTextArea::OleCallback::QueryAcceptData(LPDATAOBJECT pdataobj, HGLOBAL hMetaPict) { if (reco == RECO_PASTE) { // If CF_TEXT format is available edit controls will select it, - // otherwise if it is WinNT or Win2000 and CF_UNICODETEXT is - // available it will be selected, otherwise if CF_OEMTEXT is - // available it will be selected. + // otherwise if it is CF_UNICODETEXT is available it will be + // selected, otherwise if CF_OEMTEXT is available it will be selected. if (::IsClipboardFormatAvailable(CF_TEXT)) { *pcfFormat = CF_TEXT; - } else if (!m_isWin95 && ::IsClipboardFormatAvailable(CF_UNICODETEXT)) { + } else if (::IsClipboardFormatAvailable(CF_UNICODETEXT)) { *pcfFormat = CF_UNICODETEXT; } else if (::IsClipboardFormatAvailable(CF_OEMTEXT)) { *pcfFormat = CF_OEMTEXT; diff --git a/jdk/src/windows/native/sun/windows/awt_TextArea.h b/jdk/src/windows/native/sun/windows/awt_TextArea.h index 7e054f61079..12ba0baa658 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextArea.h +++ b/jdk/src/windows/native/sun/windows/awt_TextArea.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,6 @@ public: MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal); MsgRouting HandleEvent(MSG *msg, BOOL synthetic); - INLINE virtual int GetText(LPTSTR buffer, int size); - INLINE void SetIgnoreEnChange(BOOL b) { m_bIgnoreEnChange = b; } virtual void SetColor(COLORREF c); @@ -96,10 +94,6 @@ protected: void EditGetSel(CHARRANGE &cr); LONG EditGetCharFromPos(POINT& pt); private: - - // TRUE if the rich edit version is 2.0 - static BOOL sm_RichEdit20; - // RichEdit 1.0 control generates EN_CHANGE notifications not only // on text changes, but also on any character formatting change. // This flag is true when the latter case is detected. diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp index 1be6d9f1450..9920b925254 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -326,7 +326,7 @@ jstring AwtTextComponent::_GetText(void *param) WCHAR* buf = new WCHAR[len + 1]; c->GetText(buf, len + 1); c->RemoveCR(buf); - result = env->NewString(buf, static_cast(wcslen(buf))); + result = JNU_NewStringPlatform(env, buf); delete [] buf; } } @@ -362,7 +362,7 @@ void AwtTextComponent::_SetText(void *param) { int length = env->GetStringLength(text); WCHAR* buffer = new WCHAR[length + 1]; - env->GetStringRegion(text, 0, length, buffer); + env->GetStringRegion(text, 0, length, reinterpret_cast(buffer)); buffer[length] = 0; c->CheckLineSeparator(buffer); c->RemoveCR(buffer); diff --git a/jdk/src/windows/native/sun/windows/awt_TextComponent.h b/jdk/src/windows/native/sun/windows/awt_TextComponent.h index 2eff0505715..32a430baf38 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextComponent.h +++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,15 +70,6 @@ public: static jstring _GetText(void *param); BOOL ActMouseMessage(MSG* pMsg); - /* - * For TextComponents that contains WCHAR strings or messages with - * WCHAR parameters. - */ - INLINE LRESULT SendMessageW(UINT msg, WPARAM wParam = 0, LPARAM lParam = 0) - { - DASSERT(GetHWnd()); - return ::SendMessageW(GetHWnd(), msg, wParam, lParam); - } void SetFont(AwtFont* font); diff --git a/jdk/src/windows/native/sun/windows/awt_TextField.cpp b/jdk/src/windows/native/sun/windows/awt_TextField.cpp index 5b95495d067..975fd20bc0b 100644 --- a/jdk/src/windows/native/sun/windows/awt_TextField.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TextField.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #include "awt_Toolkit.h" #include "awt_TextField.h" #include "awt_TextComponent.h" -#include "awt_dlls.h" #include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" @@ -69,9 +68,8 @@ AwtTextField* AwtTextField::Create(jobject peer, jobject parent) { DWORD style = WS_CHILD | WS_CLIPSIBLINGS | - ES_LEFT | ES_AUTOHSCROLL | - (IS_WIN4X ? 0 : WS_BORDER); - DWORD exStyle = IS_WIN4X ? WS_EX_CLIENTEDGE : 0; + ES_LEFT | ES_AUTOHSCROLL; + DWORD exStyle = WS_EX_CLIENTEDGE; if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; if (GetRTLReadingOrder()) diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp index 3a9dfb24c7d..c4292826a8e 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -23,15 +23,16 @@ * have any questions. */ +#include "awt.h" #include #include -#if defined(_DEBUG) && defined(_MSC_VER) && _MSC_VER >= 1000 -#include -#endif +//#if defined(_DEBUG) && defined(_MSC_VER) && _MSC_VER >= 1000 +//#include +//#endif #define _JNI_IMPLEMENTATION_ -#include "stdhdrs.h" + #include "awt_DrawingSurface.h" #include "awt_AWTEvent.h" #include "awt_Component.h" @@ -51,7 +52,6 @@ #include "awt_FileDialog.h" #include "CmdIDList.h" #include "awt_new.h" -#include "awt_Unicode.h" #include "debug_trace.h" #include "debug_mem.h" @@ -225,8 +225,7 @@ BOOL AwtToolkit::activateKeyboardLayout(HKL hkl) { HKL prev = ::ActivateKeyboardLayout(hkl, 0); // If the above call fails, try loading the layout in case of NT - if ((prev == 0) && IS_NT) { - + if (!prev) { // create input locale string, e.g., "00000409", from hkl. TCHAR inputLocale[9]; TCHAR buf[9]; @@ -297,7 +296,7 @@ JavaStringBuffer::JavaStringBuffer(JNIEnv *env, jstring jstr) { if (jstr != NULL) { int length = env->GetStringLength(jstr); buffer = new TCHAR[length + 1]; - LPCTSTR tmp = (LPCTSTR)JNU_GetStringPlatformChars(env, jstr, NULL); + LPCTSTR tmp = JNU_GetStringPlatformChars(env, jstr, NULL); _tcscpy(buffer, tmp); JNU_ReleaseStringPlatformChars(env, jstr, tmp); } else { @@ -323,6 +322,7 @@ AwtToolkit::AwtToolkit() { m_vmSignalled = FALSE; m_isDynamicLayoutSet = FALSE; + m_areExtraMouseButtonsEnabled = TRUE; m_verifyComponents = FALSE; m_breakOnError = FALSE; @@ -490,8 +490,6 @@ BOOL AwtToolkit::Dispose() { ::CloseHandle(m_waitEvent); - ComCtl32Util::GetInstance().FreeLibraries(); - tk.m_isDisposed = TRUE; return TRUE; @@ -886,8 +884,6 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message, return (DWORD)ImmGetOpenStatus((HIMC)wParam); } case WM_DISPLAYCHANGE: { - AwtCursor::DirtyAllCustomCursors(); - // Reinitialize screens initScreens(env); @@ -1161,9 +1157,7 @@ BOOL AwtToolkit::PreProcessMsg(MSG& msg) if (p && p->PreProcessMsg(msg) == mrConsume) return TRUE; - if ((msg.message >= WM_MOUSEFIRST && msg.message <= WM_AWT_MOUSELAST) || - (IS_WIN95 && !IS_WIN98 && - msg.message == AwtComponent::Wheel95GetMsg()) || + if ((msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) || (msg.message >= WM_NCMOUSEMOVE && msg.message <= WM_NCMBUTTONDBLCLK)) { if (PreProcessMouseMsg(p, msg)) { return TRUE; @@ -1190,9 +1184,7 @@ BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg) return FALSE; } - if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_AWT_MOUSELAST || - (IS_WIN95 && !IS_WIN98 && msg.message == AwtComponent::Wheel95GetMsg())) - { + if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) { mouseWParam = msg.wParam; mouseLParam = msg.lParam; } else { @@ -1287,21 +1279,6 @@ BOOL AwtToolkit::PreProcessMouseMsg(AwtComponent* p, MSG& msg) //window msg.hwnd = hWndForWheel; } - else if (IS_WIN95 && !IS_WIN98 && - msg.message == AwtComponent::Wheel95GetMsg() && - mouseWheelComp != NULL) { - - // On Win95, mouse wheels are _always_ delivered to the top level - // Frame. Default behavior only takes place if the message's hwnd - // remains that of the Frame. We only want to change the hwnd if - // we're changing it to a Component that DOESN'T handle the - // mousewheel natively. - - if (!mouseWheelComp->InheritsNativeMouseWheelBehavior()) { - DTRACE_PRINTLN("AwtT::PPMM: changing hwnd on 95"); - msg.hwnd = hWndForWheel; - } - } /* * Make sure we get at least one last chance to check for transitions @@ -1792,7 +1769,7 @@ Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env, { jobject insets = NULL; RECT rRW; - MONITOR_INFO *miInfo; + LPMONITORINFO miInfo; TRY; @@ -1814,10 +1791,10 @@ Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env, if (miInfo) { insets = env->NewObject(env->FindClass("java/awt/Insets"), AwtToolkit::insetsMID, - miInfo->rWork.top - miInfo->rMonitor.top, - miInfo->rWork.left - miInfo->rMonitor.left, - miInfo->rMonitor.bottom - miInfo->rWork.bottom, - miInfo->rMonitor.right - miInfo->rWork.right); + miInfo->rcWork.top - miInfo->rcMonitor.top, + miInfo->rcWork.left - miInfo->rcMonitor.left, + miInfo->rcMonitor.bottom - miInfo->rcWork.bottom, + miInfo->rcMonitor.right - miInfo->rcWork.right); } } @@ -2057,29 +2034,15 @@ Java_sun_awt_windows_WToolkit_getWindowsVersion(JNIEnv *env, jclass cls) swprintf(szVer, L"0x%x = %ld", version, version); int l = lstrlen(szVer); - if (IS_WIN95) { - if (IS_WIN98) { - if (IS_WINME) { - swprintf(szVer + l, L" (Windows ME)"); + if (IS_WIN2000) { + if (IS_WINXP) { + if (IS_WINVISTA) { + swprintf(szVer + l, L" (Windows Vista)"); } else { - swprintf(szVer + l, L" (Windows 98)"); + swprintf(szVer + l, L" (Windows XP)"); } } else { - swprintf(szVer + l, L" (Windows 95)"); - } - } else if (IS_NT) { - if (IS_WIN2000) { - if (IS_WINXP) { - if (IS_WINVISTA) { - swprintf(szVer + l, L" (Windows Vista)"); - } else { - swprintf(szVer + l, L" (Windows XP)"); - } - } else { - swprintf(szVer + l, L" (Windows 2000)"); - } - } else { - swprintf(szVer + l, L" (Windows NT)"); + swprintf(szVer + l, L" (Windows 2000)"); } } else { swprintf(szVer + l, L" (Unknown)"); @@ -2130,3 +2093,26 @@ Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls) splashClose(); } } + +/* + * accessible from awt_Component + */ +BOOL AwtToolkit::areExtraMouseButtonsEnabled() { + return m_areExtraMouseButtonsEnabled; +} + +/* + * Class: sun_awt_windows_WToolkit + * Method: setExtraMouseButtonsEnabledNative + * Signature: (Z)V + */ +extern "C" JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkit_setExtraMouseButtonsEnabledNative +(JNIEnv *env, jclass self, jboolean enable){ + TRY; + AwtToolkit::GetInstance().setExtraMouseButtonsEnabled(enable); + CATCH_BAD_ALLOC; +} + +void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) { + m_areExtraMouseButtonsEnabled = enable; +} diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.h b/jdk/src/windows/native/sun/windows/awt_Toolkit.h index fcee2d4ad5c..d76546fa4eb 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h @@ -50,7 +50,6 @@ #include "awt.h" #include "awtmsg.h" -#include "awt_Multimon.h" #include "Trace.h" #include "sun_awt_windows_WToolkit.h" @@ -89,11 +88,8 @@ class JNILocalFrame { */ class CriticalSection { public: - INLINE CriticalSection() { ::InitializeCriticalSection(&rep); - ::InitializeCriticalSection(&tryrep); - tryEntered = 0; } - INLINE ~CriticalSection() { ::DeleteCriticalSection(&rep); - ::DeleteCriticalSection(&tryrep); } + INLINE CriticalSection() { ::InitializeCriticalSection(&rep); } + INLINE ~CriticalSection() { ::DeleteCriticalSection(&rep); } class Lock { public: @@ -111,50 +107,18 @@ class CriticalSection { private: CRITICAL_SECTION rep; - CRITICAL_SECTION tryrep; - long tryEntered; - CriticalSection(const CriticalSection&); const CriticalSection& operator =(const CriticalSection&); public: - virtual void Enter (void) - { - ::EnterCriticalSection(&tryrep); - tryEntered++; - if (tryEntered == 1) { - ::EnterCriticalSection(&rep); - ::LeaveCriticalSection(&tryrep); - } else { - ::LeaveCriticalSection(&tryrep); - ::EnterCriticalSection(&rep); - } + virtual void Enter() { + ::EnterCriticalSection(&rep); } - // we cannot use ::TryEnterCriticalSection as it is not supported on Win9x/Me - virtual BOOL TryEnter (void) - { - BOOL result = FALSE; - ::EnterCriticalSection(&tryrep); - if (tryEntered == 0) { - ::EnterCriticalSection(&rep); - tryEntered++; - result = TRUE; - } - ::LeaveCriticalSection(&tryrep); - return result; + virtual BOOL TryEnter() { + return ::TryEnterCriticalSection(&rep); } - virtual void Leave (void) - { - ::EnterCriticalSection(&tryrep); - if (tryEntered > 0) { - tryEntered--; - } else { - // this may happen only if we call to Leave() before - // Enter() so this is definitely a bug - DASSERT(FALSE); - } + virtual void Leave() { ::LeaveCriticalSection(&rep); - ::LeaveCriticalSection(&tryrep); } }; @@ -211,6 +175,8 @@ public: BOOL IsDynamicLayoutSet(); BOOL IsDynamicLayoutSupported(); BOOL IsDynamicLayoutActive(); + BOOL areExtraMouseButtonsEnabled(); + void setExtraMouseButtonsEnabled(BOOL enable); INLINE BOOL localPump() { return m_localPump; } INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag @@ -387,6 +353,7 @@ private: BOOL m_verbose; BOOL m_isActive; // set to FALSE at beginning of Dispose BOOL m_isDisposed; // set to TRUE at end of Dispose + BOOL m_areExtraMouseButtonsEnabled; BOOL m_vmSignalled; // set to TRUE if QUERYENDSESSION has successfully // raised SIGTERM diff --git a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp index 0d3047b59e5..9165314bbc5 100644 --- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp +++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp @@ -23,9 +23,10 @@ * have any questions. */ -#include +#include "awt.h" #include #include +#include #include "awt_Toolkit.h" #include "awt_TrayIcon.h" @@ -173,27 +174,20 @@ AwtTrayIcon* AwtTrayIcon::Create(jobject self, jobject parent) env->DeleteLocalRef(target); return awtTrayIcon; } -typedef struct _SDLLVERSIONINFO -{ - DWORD cbSize; - DWORD dwMajorVersion; // Major version - DWORD dwMinorVersion; // Minor version - DWORD dwBuildNumber; // Build number - DWORD dwPlatformID; // DLLVER_PLATFORM_* -} SDLLVERSIONINFO; -typedef HRESULT (CALLBACK* SDLLGETVERSIONPROC)(SDLLVERSIONINFO *); void AwtTrayIcon::InitNID(UINT uID) { // fix for 6271589: we MUST set the size of the structure to match // the shell version, otherwise some errors may occur (like missing // balloon messages on win2k) - SDLLVERSIONINFO dllVersionInfo; - dllVersionInfo.cbSize = sizeof(SDLLVERSIONINFO); - int shellVersion = 4; // WIN_98 + DLLVERSIONINFO dllVersionInfo; + dllVersionInfo.cbSize = sizeof(DLLVERSIONINFO); + int shellVersion = 5; // WIN_2000 + // MSDN: DllGetVersion should not be implicitly called, but rather + // loaded using GetProcAddress HMODULE hShell = LoadLibrary(TEXT("Shell32.dll")); if (hShell != NULL) { - SDLLGETVERSIONPROC proc = (SDLLGETVERSIONPROC)GetProcAddress(hShell, "DllGetVersion"); + DLLGETVERSIONPROC proc = (DLLGETVERSIONPROC)GetProcAddress(hShell, "DllGetVersion"); if (proc != NULL) { if (proc(&dllVersionInfo) == NOERROR) { shellVersion = dllVersionInfo.dwMajorVersion; @@ -202,14 +196,16 @@ void AwtTrayIcon::InitNID(UINT uID) } FreeLibrary(hShell); switch (shellVersion) { - case 5: // WIN_2000, WIN_ME + case 5: // WIN_2000 m_nid.cbSize = (BYTE *)(&m_nid.guidItem) - (BYTE *)(&m_nid.cbSize); break; case 6: // WIN_XP + // Uncomment these two lines when moving to VS2008 +// m_nid.cbSize = (BYTE *)(&m_nid.hBalloonIcon) - (BYTE *)(&m_nid.cbSize); +// break; + default: // WIN_VISTA? m_nid.cbSize = sizeof(m_nid); break; - default: // WIN_98, WIN_NT - m_nid.cbSize = (BYTE *)(&m_nid.szTip) - (BYTE *)(&m_nid.cbSize) + sizeof(m_nid.szTip) / 2; } m_nid.hWnd = AwtTrayIcon::sm_msgWindow; m_nid.uID = uID; @@ -217,7 +213,7 @@ void AwtTrayIcon::InitNID(UINT uID) m_nid.uCallbackMessage = WM_AWT_TRAY_NOTIFY; m_nid.hIcon = AwtToolkit::GetInstance().GetAwtIcon(); m_nid.szTip[0] = '\0'; - m_nid.uVersion = IS_WIN2000 ? AWT_NOTIFYICON_VERSION : 0; + m_nid.uVersion = NOTIFYICON_VERSION; } BOOL AwtTrayIcon::SendTrayMessage(DWORD dwMessage) @@ -304,13 +300,13 @@ MsgRouting AwtTrayIcon::WmAwtTrayNotify(WPARAM wParam, LPARAM lParam) case WM_CONTEXTMENU: mr = WmContextMenu(0, pos.x, pos.y); break; - case AWT_NIN_KEYSELECT: + case NIN_KEYSELECT: mr = WmKeySelect(0, pos.x, pos.y); break; - case AWT_NIN_SELECT: + case NIN_SELECT: mr = WmSelect(0, pos.x, pos.y); break; - case AWT_NIN_BALLOONUSERCLICK: + case NIN_BALLOONUSERCLICK: mr = WmBalloonUserClick(0, pos.x, pos.y); break; } @@ -371,7 +367,7 @@ MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button) (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? TRUE : FALSE), AwtComponent::GetButton(button), &msg); - if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 1) { // No up-button in the drag-state + if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED, TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(), clickCount, JNI_FALSE, AwtComponent::GetButton(button)); @@ -397,7 +393,7 @@ MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y) lastX = x; lastY = y; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - if ((flags & AwtComponent::ALL_MK_BUTTONS) != 0) { + if ((flags & ALL_MK_BUTTONS) != 0) { m_mouseButtonClickAllowed = 0; } else { SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y, @@ -473,7 +469,7 @@ MsgRouting AwtTrayIcon::WmTaskbarCreated() { BOOL result = item->m_trayIcon->SendTrayMessage(NIM_ADD); // 6270114: Instructs the taskbar to behave according to the Shell version 5.0 if (result) { - item->m_trayIcon->SendTrayMessage(AWT_NIM_SETVERSION); + item->m_trayIcon->SendTrayMessage(NIM_SETVERSION); } } return mrDoDefault; @@ -733,9 +729,9 @@ void AwtTrayIcon::_SetToolTip(void *param) goto ret; } - tooltipStr = env->GetStringChars(jtooltip, (jboolean *)NULL); + tooltipStr = JNU_GetStringPlatformChars(env, jtooltip, (jboolean *)NULL); trayIcon->SetToolTip(tooltipStr); - env->ReleaseStringChars(jtooltip, tooltipStr); + JNU_ReleaseStringPlatformChars(env, jtooltip, tooltipStr); ret: env->DeleteGlobalRef(self); env->DeleteGlobalRef(jtooltip); @@ -782,7 +778,7 @@ void AwtTrayIcon::_UpdateIcon(void *param) BOOL result = trayIcon->SendTrayMessage(jupdate == JNI_TRUE ? NIM_MODIFY : NIM_ADD); // 6270114: Instructs the taskbar to behave according to the Shell version 5.0 if (result && jupdate == JNI_FALSE) { - trayIcon->SendTrayMessage(AWT_NIM_SETVERSION); + trayIcon->SendTrayMessage(NIM_SETVERSION); } ret: env->DeleteGlobalRef(self); @@ -791,22 +787,19 @@ ret: void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType) { - if (!IS_WIN2000) - return; - - m_nid.uFlags |= AWT_NIF_INFO; + m_nid.uFlags |= NIF_INFO; m_nid.uTimeout = 10000; if (lstrcmp(msgType, TEXT("ERROR")) == 0) { - m_nid.dwInfoFlags = AWT_NIIF_ERROR; + m_nid.dwInfoFlags = NIIF_ERROR; } else if (lstrcmp(msgType, TEXT("WARNING")) == 0) { - m_nid.dwInfoFlags = AWT_NIIF_WARNING; + m_nid.dwInfoFlags = NIIF_WARNING; } else if (lstrcmp(msgType, TEXT("INFO")) == 0) { - m_nid.dwInfoFlags = AWT_NIIF_INFO; + m_nid.dwInfoFlags = NIIF_INFO; } else if (lstrcmp(msgType, TEXT("NONE")) == 0) { - m_nid.dwInfoFlags = AWT_NIIF_NONE; + m_nid.dwInfoFlags = NIIF_NONE; } else { - m_nid.dwInfoFlags = AWT_NIIF_NONE; + m_nid.dwInfoFlags = NIIF_NONE; } if (caption[0] == '\0') { @@ -835,7 +828,7 @@ void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType) } SendTrayMessage(NIM_MODIFY); - m_nid.uFlags &= ~AWT_NIF_INFO; + m_nid.uFlags &= ~NIF_INFO; } void AwtTrayIcon::_DisplayMessage(void *param) @@ -855,15 +848,15 @@ void AwtTrayIcon::_DisplayMessage(void *param) JNI_CHECK_PEER_GOTO(self, ret); trayIcon = (AwtTrayIcon *)pData; - captionStr = env->GetStringChars(jcaption, (jboolean *)NULL); - textStr = env->GetStringChars(jtext, (jboolean *)NULL); - msgTypeStr = env->GetStringChars(jmsgType, (jboolean *)NULL); + captionStr = JNU_GetStringPlatformChars(env, jcaption, (jboolean *)NULL); + textStr = JNU_GetStringPlatformChars(env, jtext, (jboolean *)NULL); + msgTypeStr = JNU_GetStringPlatformChars(env, jmsgType, (jboolean *)NULL); trayIcon->DisplayMessage(captionStr, textStr, msgTypeStr); - env->ReleaseStringChars(jcaption, captionStr); - env->ReleaseStringChars(jtext, textStr); - env->ReleaseStringChars(jmsgType, msgTypeStr); + JNU_ReleaseStringPlatformChars(env, jcaption, captionStr); + JNU_ReleaseStringPlatformChars(env, jtext, textStr); + JNU_ReleaseStringPlatformChars(env, jmsgType, msgTypeStr); ret: env->DeleteGlobalRef(self); env->DeleteGlobalRef(jcaption); @@ -1057,16 +1050,14 @@ Java_sun_awt_windows_WTrayIconPeer__1displayMessage(JNIEnv *env, jobject self, { TRY; - if (IS_WIN2000) { - DisplayMessageStruct *dms = new DisplayMessageStruct; - dms->trayIcon = env->NewGlobalRef(self); - dms->caption = (jstring)env->NewGlobalRef(caption); - dms->text = (jstring)env->NewGlobalRef(text); - dms->msgType = (jstring)env->NewGlobalRef(msgType); + DisplayMessageStruct *dms = new DisplayMessageStruct; + dms->trayIcon = env->NewGlobalRef(self); + dms->caption = (jstring)env->NewGlobalRef(caption); + dms->text = (jstring)env->NewGlobalRef(text); + dms->msgType = (jstring)env->NewGlobalRef(msgType); - AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_DisplayMessage, dms); - // global ref is deleted in _DisplayMessage - } + AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_DisplayMessage, dms); + // global ref is deleted in _DisplayMessage CATCH_BAD_ALLOC(NULL); } diff --git a/jdk/src/windows/native/sun/windows/awt_TrayIcon.h b/jdk/src/windows/native/sun/windows/awt_TrayIcon.h index 6a3c25dd730..8ee418aa794 100644 --- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.h +++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.h @@ -36,57 +36,11 @@ #define TRAY_ICON_X_HOTSPOT 0 #define TRAY_ICON_Y_HOTSPOT 0 -#define TRAY_ICON_TOOLTIP_MAX_SIZE (IS_WIN2000 ? 128 : 64) +#define TRAY_ICON_TOOLTIP_MAX_SIZE 128 #define TRAY_ICON_BALLOON_TITLE_MAX_SIZE 64 #define TRAY_ICON_BALLOON_INFO_MAX_SIZE 256 -// ********************************************************************** -// The following definitions are duplicates for those from the shellapi.h -// ********************************************************************** - -#define AWT_NOTIFYICON_VERSION 3 - -#define AWT_NIM_SETVERSION 0x00000004 - -#define AWT_NIN_SELECT (WM_USER + 0) -#define AWT_NINF_KEY 0x1 -#define AWT_NIN_KEYSELECT (AWT_NIN_SELECT | AWT_NINF_KEY) -#define AWT_NIN_BALLOONSHOW (WM_USER + 2) -#define AWT_NIN_BALLOONHIDE (WM_USER + 3) -#define AWT_NIN_BALLOONTIMEOUT (WM_USER + 4) -#define AWT_NIN_BALLOONUSERCLICK (WM_USER + 5) - -#define AWT_NIIF_NONE 0x00000000 -#define AWT_NIIF_INFO 0x00000001 -#define AWT_NIIF_WARNING 0x00000002 -#define AWT_NIIF_ERROR 0x00000003 - -#define AWT_NIF_INFO 0x00000010 - -typedef struct _AWT_NOTIFYICONDATA { - DWORD cbSize; - HWND hWnd; - UINT uID; - UINT uFlags; - UINT uCallbackMessage; - HICON hIcon; - TCHAR szTip[128]; - - DWORD dwState; // _WIN32_IE >= 0x0500 - DWORD dwStateMask; - TCHAR szInfo[256]; - union { - UINT uTimeout; - UINT uVersion; - } DUMMYUNIONNAME; - TCHAR szInfoTitle[64]; - DWORD dwInfoFlags; - - GUID guidItem; // _WIN32_IE >= 0x600 -} AWT_NOTIFYICONDATA, *PAWT_NOTIFYICONDATA; - - /************************************************************************ * AwtTrayIcon class */ @@ -174,7 +128,7 @@ public: static int sm_instCount; private: - AWT_NOTIFYICONDATA m_nid; + NOTIFYICONDATA m_nid; /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON * which are allowed to diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp index 6f2f62c3154..2a23bfa9b3e 100644 --- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsConfig.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,12 @@ * have any questions. */ -#include #include "awt.h" #include #include "awt_Win32GraphicsConfig.h" #include "awt_Canvas.h" #include "awt_Win32GraphicsDevice.h" +#include "Devices.h" //Info for building a ColorModel #include "java_awt_image_DataBuffer.h" @@ -93,8 +93,8 @@ JNIEXPORT jobject JNICALL clazz = env->FindClass("java/awt/Rectangle"); mid = env->GetMethodID(clazz, "", "(IIII)V"); if (mid != 0) { - RECT rRW = {0,0,0,0}; - if( TRUE == ::MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW) ) { + RECT rRW = {0, 0, 0, 0}; + if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) { bounds = env->NewObject(clazz, mid, rRW.left, rRW.top, rRW.right - rRW.left, diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp index 047f7148c19..aba41a5a4cb 100644 --- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp @@ -37,19 +37,17 @@ * array index. */ -#include -#include #include #include #include "awt_Canvas.h" #include "awt_Win32GraphicsDevice.h" +#include "awt_Window.h" #include "java_awt_Transparency.h" #include "java_awt_color_ColorSpace.h" #include "sun_awt_Win32GraphicsDevice.h" #include "java_awt_image_DataBuffer.h" #include "dither.h" #include "img_util_md.h" -#include "awt_dlls.h" #include "Devices.h" uns_ordered_dither_array img_oda_alpha; @@ -72,7 +70,7 @@ int AwtWin32GraphicsDevice::primaryIndex = 0; * device, and information on whether the primary device is palettized. */ AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen, - MHND mhnd, Devices *arr) + HMONITOR mhnd, Devices *arr) { this->screen = screen; this->devicesArray = arr; @@ -83,8 +81,8 @@ AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen, cData = NULL; gpBitmapInfo = NULL; monitor = mhnd; - pMonitorInfo = (PMONITOR_INFO)new MONITOR_INFO_EXTENDED; - pMonitorInfo->dwSize = sizeof(MONITOR_INFO_EXTENDED); + pMonitorInfo = new MONITORINFOEX; + pMonitorInfo->cbSize = sizeof(MONITORINFOEX); ::GetMonitorInfo(monitor, pMonitorInfo); // Set primary device info: other devices will need to know @@ -93,7 +91,7 @@ AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen, HDC hDC = this->GetDC(); colorData->bitsperpixel = ::GetDeviceCaps(hDC, BITSPIXEL); this->ReleaseDC(hDC); - if (MONITOR_INFO_FLAG_PRIMARY & pMonitorInfo->dwFlags) { + if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { primaryIndex = screen; if (colorData->bitsperpixel > 8) { primaryPalettized = FALSE; @@ -124,6 +122,24 @@ AwtWin32GraphicsDevice::~AwtWin32GraphicsDevice() } } +HDC AwtWin32GraphicsDevice::MakeDCFromMonitor(HMONITOR hmMonitor) { + HDC retCode = NULL; + if (NULL != hmMonitor) { + MONITORINFOEX mieInfo; + + memset((void*)(&mieInfo), 0, sizeof(MONITORINFOEX)); + mieInfo.cbSize = sizeof(MONITORINFOEX); + + if (TRUE == ::GetMonitorInfo(hmMonitor, (LPMONITORINFOEX)(&mieInfo))) { + HDC hDC = CreateDC(mieInfo.szDevice, NULL, NULL, NULL); + if (NULL != hDC) { + retCode = hDC; + } + } + } + return retCode; +} + HDC AwtWin32GraphicsDevice::GetDC() { return MakeDCFromMonitor(monitor); @@ -164,7 +180,7 @@ void AwtWin32GraphicsDevice::Initialize() VERIFY(::GetDIBits(hBMDC, hBM, 0, 1, NULL, gpBitmapInfo, DIB_RGB_COLORS)); if (colorData->bitsperpixel > 8) { - if (MONITOR_INFO_FLAG_PRIMARY & pMonitorInfo->dwFlags) { + if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { primaryPalettized = FALSE; } if (colorData->bitsperpixel != 24) { // 15, 16, or 32 bpp @@ -250,7 +266,7 @@ void AwtWin32GraphicsDevice::Initialize() ((int *)gpBitmapInfo->bmiColors)[2] = 0xff0000; } } else { - if (MONITOR_INFO_FLAG_PRIMARY & pMonitorInfo->dwFlags) { + if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { primaryPalettized = TRUE; } gpBitmapInfo->bmiHeader.biBitCount = 8; @@ -565,8 +581,8 @@ void AwtWin32GraphicsDevice::RealizePalette(HDC hDC) */ int AwtWin32GraphicsDevice::DeviceIndexForWindow(HWND hWnd) { - MHND mon = MonitorFromWindow(hWnd, MONITOR_DEFAULT_TO_NEAR); - int screen = AwtWin32GraphicsDevice::GetScreenFromMHND(mon); + HMONITOR mon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(mon); return screen; } @@ -645,14 +661,14 @@ jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic, return devices->GetDevice(deviceIndex)->GetColorModel(env, dynamic); } -MONITOR_INFO *AwtWin32GraphicsDevice::GetMonitorInfo(int deviceIndex) +LPMONITORINFO AwtWin32GraphicsDevice::GetMonitorInfo(int deviceIndex) { Devices::InstanceAccess devices; return devices->GetDevice(deviceIndex)->GetMonitorInfo(); } /** - * This function updates the data in the MONITOR_INFO structure pointed to by + * This function updates the data in the MONITORINFOEX structure pointed to by * pMonitorInfo for all monitors on the system. Added for 4654713. */ void AwtWin32GraphicsDevice::ResetAllMonitorInfo() @@ -660,14 +676,14 @@ void AwtWin32GraphicsDevice::ResetAllMonitorInfo() Devices::InstanceAccess devices; int devicesNum = devices->GetNumDevices(); for (int deviceIndex = 0; deviceIndex < devicesNum; deviceIndex++) { - MHND monitor = devices->GetDevice(deviceIndex)->GetMonitor(); + HMONITOR monitor = devices->GetDevice(deviceIndex)->GetMonitor(); ::GetMonitorInfo(monitor, devices->GetDevice(deviceIndex)->pMonitorInfo); } } void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice( - MHND hMonitor) + HMONITOR hMonitor) { Devices::InstanceAccess devices; if (hMonitor == NULL) { @@ -682,7 +698,7 @@ void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice( } } -MHND AwtWin32GraphicsDevice::GetMonitor(int deviceIndex) +HMONITOR AwtWin32GraphicsDevice::GetMonitor(int deviceIndex) { Devices::InstanceAccess devices; return devices->GetDevice(deviceIndex)->GetMonitor(); @@ -741,30 +757,31 @@ HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) { return MakeDCFromMonitor(dev->GetMonitor()); } -/** Compare elements of MONITOR_INFO structures for the given MHNDs. +/** Compare elements of MONITORINFOEX structures for the given HMONITORs. * If equal, return TRUE */ -BOOL AwtWin32GraphicsDevice::AreSameMonitors(MHND mon1, MHND mon2) { +BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) { J2dTraceLn2(J2D_TRACE_INFO, "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x", mon1, mon2); DASSERT(mon1 != NULL); DASSERT(mon2 != NULL); - MONITOR_INFO mi1; - MONITOR_INFO mi2; + MONITORINFOEX mi1; + MONITORINFOEX mi2; - memset((void*)(&mi1),0,sizeof(MONITOR_INFO)); - mi1.dwSize = sizeof(MONITOR_INFO); - memset((void*)(&mi2),0,sizeof(MONITOR_INFO)); - mi2.dwSize = sizeof(MONITOR_INFO); + memset((void*)(&mi1), 0, sizeof(MONITORINFOEX)); + mi1.cbSize = sizeof(MONITORINFOEX); + memset((void*)(&mi2), 0, sizeof(MONITORINFOEX)); + mi2.cbSize = sizeof(MONITORINFOEX); - if (::GetMonitorInfo(mon1,&mi1) != 0 && - ::GetMonitorInfo(mon2,&mi2) != 0 ) { - - if (::EqualRect(&mi1.rMonitor,&mi2.rMonitor) && - ::EqualRect(&mi1.rWork,&mi2.rWork) && - mi1.dwFlags == mi1.dwFlags) { + if (::GetMonitorInfo(mon1, &mi1) != 0 && + ::GetMonitorInfo(mon2, &mi2) != 0 ) + { + if (::EqualRect(&mi1.rcMonitor, &mi2.rcMonitor) && + ::EqualRect(&mi1.rcWork, &mi2.rcWork) && + (mi1.dwFlags == mi1.dwFlags)) + { J2dTraceLn(J2D_TRACE_VERBOSE, " the monitors are the same"); return TRUE; @@ -774,15 +791,15 @@ BOOL AwtWin32GraphicsDevice::AreSameMonitors(MHND mon1, MHND mon2) { return FALSE; } -int AwtWin32GraphicsDevice::GetScreenFromMHND(MHND mon) { +int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { J2dTraceLn1(J2D_TRACE_INFO, - "AwtWin32GraphicsDevice::GetScreenFromMHND mhnd=%x", mon); + "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon); DASSERT(mon != NULL); Devices::InstanceAccess devices; for (int i = 0; i < devices->GetNumDevices(); i++) { - MHND mhnd = devices->GetDevice(i)->GetMonitor(); + HMONITOR mhnd = devices->GetDevice(i)->GetMonitor(); if (AreSameMonitors(mon, mhnd)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " Found device: %d", i); return i; @@ -790,8 +807,8 @@ int AwtWin32GraphicsDevice::GetScreenFromMHND(MHND mon) { } J2dTraceLn1(J2D_TRACE_WARNING, - "AwtWin32GraphicsDevice::GetScreenFromMHND(): "\ - "couldn't find screen for MHND %x, returning default", mon); + "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\ + "couldn't find screen for HMONITOR %x, returning default", mon); return AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); } @@ -1076,19 +1093,19 @@ jobject CreateDisplayMode(JNIEnv* env, jint width, jint height, * of the structure pointed to by lpDisplayDevice is undefined. */ static BOOL -GetAttachedDisplayDevice(int screen, _DISPLAY_DEVICE *lpDisplayDevice) +GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice) { DWORD dwDeviceNum = 0; - lpDisplayDevice->dwSize = sizeof(_DISPLAY_DEVICE); + lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE); while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) && dwDeviceNum < 20) // avoid infinite loop with buggy drivers { - if (lpDisplayDevice->dwFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { + if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { Devices::InstanceAccess devices; - MONITOR_INFO_EXTENDED *pMonInfo = - (PMONITOR_INFO_EXTENDED) devices->GetDevice(screen)->GetMonitorInfo(); + MONITORINFOEX *pMonInfo = + (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo(); // make sure the device names match - if (wcscmp(pMonInfo->strDevice, lpDisplayDevice->strDevName) == 0) { + if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) { return TRUE; } } @@ -1114,9 +1131,9 @@ Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode dm.dmSize = sizeof(dm); dm.dmDriverExtra = 0; - _DISPLAY_DEVICE displayDevice; + DISPLAY_DEVICE displayDevice; if (GetAttachedDisplayDevice(screen, &displayDevice)) { - pName = displayDevice.strDevName; + pName = displayDevice.DeviceName; } if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm)) { @@ -1156,7 +1173,7 @@ Java_sun_awt_Win32GraphicsDevice_configDisplayMode // ChangeDisplaySettingsEx is not available on NT, // so it'd be nice not to break it if we can help it. if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) { - if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != + if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { JNU_ThrowInternalError(env, @@ -1165,15 +1182,9 @@ Java_sun_awt_Win32GraphicsDevice_configDisplayMode return; } - // make sure the function pointer for fn_change_display_settings_ex - // is initialized - load_user_procs(); - - _DISPLAY_DEVICE displayDevice; - if (fn_change_display_settings_ex == NULL || - !GetAttachedDisplayDevice(screen, &displayDevice) || - ((*fn_change_display_settings_ex) - (displayDevice.strDevName, &dm, NULL, CDS_FULLSCREEN, NULL) != + DISPLAY_DEVICE displayDevice; + if (!GetAttachedDisplayDevice(screen, &displayDevice) || + (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)) { JNU_ThrowInternalError(env, @@ -1231,11 +1242,11 @@ JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes DEVMODE dm; LPTSTR pName = NULL; - _DISPLAY_DEVICE displayDevice; + DISPLAY_DEVICE displayDevice; if (GetAttachedDisplayDevice(screen, &displayDevice)) { - pName = displayDevice.strDevName; + pName = displayDevice.DeviceName; } dm.dmSize = sizeof(dm); diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h index 9d3978ba324..42a7ff18029 100644 --- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h +++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h @@ -32,7 +32,6 @@ extern "C" { } // extern "C" #include "colordata.h" #include "awt_Palette.h" -#include "awt_MMStub.h" #include "Devices.h" class AwtPalette; @@ -40,7 +39,7 @@ class Devices; class AwtWin32GraphicsDevice { public: - AwtWin32GraphicsDevice(int screen, MHND mhnd, Devices *arr); + AwtWin32GraphicsDevice(int screen, HMONITOR mhnd, Devices *arr); ~AwtWin32GraphicsDevice(); void UpdateDeviceColorState(); void SetGrayness(int grayValue); @@ -60,8 +59,8 @@ public: HPALETTE GetPalette(); ColorData *GetColorData() { return cData; } int GetBitDepth() { return colorData->bitsperpixel; } - MHND GetMonitor() { return monitor; } - MONITOR_INFO *GetMonitorInfo() { return pMonitorInfo; } + HMONITOR GetMonitor() { return monitor; } + LPMONITORINFO GetMonitorInfo() { return pMonitorInfo; } jobject GetJavaDevice() { return javaDevice; } int GetDeviceIndex() { return screen; } void Release(); @@ -78,14 +77,14 @@ public: static void UpdateDynamicColorModel(int deviceIndex); static BOOL UpdateSystemPalette(int deviceIndex); static HPALETTE GetPalette(int deviceIndex); - static MHND GetMonitor(int deviceIndex); - static MONITOR_INFO *GetMonitorInfo(int deviceIndex); + static HMONITOR GetMonitor(int deviceIndex); + static LPMONITORINFO GetMonitorInfo(int deviceIndex); static void ResetAllMonitorInfo(); static BOOL IsPrimaryPalettized() { return primaryPalettized; } static int GetDefaultDeviceIndex() { return primaryIndex; } - static void DisableOffscreenAccelerationForDevice(MHND hMonitor); + static void DisableOffscreenAccelerationForDevice(HMONITOR hMonitor); static HDC GetDCFromScreen(int screen); - static int GetScreenFromMHND(MHND mon); + static int GetScreenFromHMONITOR(HMONITOR mon); static int primaryIndex; static BOOL primaryPalettized; @@ -97,17 +96,19 @@ public: static jmethodID paletteChangedMID; private: - static BOOL AreSameMonitors(MHND mon1, MHND mon2); + static BOOL AreSameMonitors(HMONITOR mon1, HMONITOR mon2); ImgColorData *colorData; AwtPalette *palette; ColorData *cData; // Could be static, but may sometime // have per-device info in this structure BITMAPINFO *gpBitmapInfo; int screen; - MHND monitor; - MONITOR_INFO *pMonitorInfo; + HMONITOR monitor; + LPMONITORINFO pMonitorInfo; jobject javaDevice; Devices *devicesArray; + + static HDC MakeDCFromMonitor(HMONITOR); }; #endif AWT_WIN32GRAPHICSDEVICE_H diff --git a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp index 398e17d27d8..1617d54e657 100644 --- a/jdk/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp @@ -23,8 +23,6 @@ * have any questions. */ -#include -#include #include #include #include "awt_Canvas.h" @@ -188,44 +186,6 @@ Java_sun_awt_Win32GraphicsEnvironment_getDefaultScreen(JNIEnv *env, return AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); } -#define FR_PRIVATE 0x10 /* from wingdi.h */ -typedef int (WINAPI *AddFontResourceExType)(LPCTSTR,DWORD,VOID*); -typedef int (WINAPI *RemoveFontResourceExType)(LPCTSTR,DWORD,VOID*); - -static AddFontResourceExType procAddFontResourceEx = NULL; -static RemoveFontResourceExType procRemoveFontResourceEx = NULL; - -static int winVer = -1; - -static int getWinVer() { - if (winVer == -1) { - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - winVer = osvi.dwMajorVersion; - if (winVer >= 5) { - // REMIND verify on 64 bit windows - HMODULE hGDI = LoadLibrary(TEXT("gdi32.dll")); - if (hGDI != NULL) { - procAddFontResourceEx = - (AddFontResourceExType)GetProcAddress(hGDI,"AddFontResourceExW"); - if (procAddFontResourceEx == NULL) { - winVer = 0; - } - procRemoveFontResourceEx = - (RemoveFontResourceExType)GetProcAddress(hGDI, - "RemoveFontResourceExW"); - if (procRemoveFontResourceEx == NULL) { - winVer = 0; - } - FreeLibrary(hGDI); - } - } - } - - return winVer; -} - /* * Class: sun_awt_Win32GraphicsEnvironment * Method: registerFontWithPlatform @@ -236,9 +196,10 @@ Java_sun_awt_Win32GraphicsEnvironment_registerFontWithPlatform(JNIEnv *env, jclass cl, jstring fontName) { - if (getWinVer() >= 5 && procAddFontResourceEx != NULL) { - LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, NULL); - (*procAddFontResourceEx)(file, FR_PRIVATE, NULL); + LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE); + if (file) { + ::AddFontResourceEx(file, FR_PRIVATE, NULL); + JNU_ReleaseStringPlatformChars(env, fontName, file); } } @@ -255,9 +216,10 @@ Java_sun_awt_Win32GraphicsEnvironment_deRegisterFontWithPlatform(JNIEnv *env, jclass cl, jstring fontName) { - if (getWinVer() >= 5 && procRemoveFontResourceEx != NULL) { - LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, NULL); - (*procRemoveFontResourceEx)(file, FR_PRIVATE, NULL); + LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE); + if (file) { + ::RemoveFontResourceEx(file, FR_PRIVATE, NULL); + JNU_ReleaseStringPlatformChars(env, fontName, file); } } diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp index 13b41863235..0c9bce1210d 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp @@ -23,7 +23,7 @@ * have any questions. */ -#include +#include "awt.h" #include "awt_Component.h" #include "awt_Container.h" @@ -32,7 +32,6 @@ #include "awt_Panel.h" #include "awt_Toolkit.h" #include "awt_Window.h" -#include "awt_dlls.h" #include "awt_Win32GraphicsDevice.h" #include "awt_BitmapUtil.h" #include "awt_IconCursor.h" @@ -42,6 +41,8 @@ #include #include "sun_awt_windows_WCanvasPeer.h" +#include + #if !defined(__int3264) typedef __int32 LONG_PTR; #endif // __int3264 @@ -501,8 +502,7 @@ void AwtWindow::Show() // which might involve tagging java.awt.Window instances with a semantic // property so platforms can animate/decorate/etc accordingly. // - if ((IS_WIN98 || IS_WIN2000) && - JNU_IsInstanceOfByName(env, target, "com/sun/java/swing/plaf/windows/WindowsPopupWindow") > 0) + if (JNU_IsInstanceOfByName(env, target, "com/sun/java/swing/plaf/windows/WindowsPopupWindow") > 0) { // need this global ref to make the class unloadable (see 6500204) static jclass windowsPopupWindowCls; @@ -535,13 +535,8 @@ void AwtWindow::Show() windowType = env->GetIntField(target, windowTypeFID); if (windowType == windowTYPES[TOOLTIP]) { - if (IS_WIN2000) { - SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &animateflag, 0); - SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fadeflag, 0); - } else { - // use same setting as menus - SystemParametersInfo(SPI_GETMENUANIMATION, 0, &animateflag, 0); - } + SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &animateflag, 0); + SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &fadeflag, 0); if (animateflag) { // AW_BLEND currently produces runtime parameter error // animateStyle = fadeflag? AW_BLEND : AW_SLIDE | AW_VER_POSITIVE; @@ -551,13 +546,10 @@ void AwtWindow::Show() windowType == windowTYPES[POPUPMENU]) { SystemParametersInfo(SPI_GETMENUANIMATION, 0, &animateflag, 0); if (animateflag) { - - if (IS_WIN2000) { - SystemParametersInfo(SPI_GETMENUFADE, 0, &fadeflag, 0); - if (fadeflag) { - // AW_BLEND currently produces runtime parameter error - //animateStyle = AW_BLEND; - } + SystemParametersInfo(SPI_GETMENUFADE, 0, &fadeflag, 0); + if (fadeflag) { + // AW_BLEND currently produces runtime parameter error + //animateStyle = AW_BLEND; } if (animateStyle == 0 && !fadeflag) { animateStyle = AW_SLIDE; @@ -578,38 +570,18 @@ void AwtWindow::Show() } if (animateStyle != 0) { - load_user_procs(); - - if (fn_animate_window != NULL) { - BOOL result = (*fn_animate_window)(hWnd, (DWORD)200, animateStyle); - if (result == 0) { - LPTSTR msgBuffer = NULL; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&msgBuffer, // it's an output parameter when allocate buffer is used - 0, - NULL); - - if (msgBuffer == NULL) { - msgBuffer = TEXT(""); - } - _ftprintf(stderr,TEXT("AwtWindow::Show: AnimateWindow: ")); - _ftprintf(stderr,msgBuffer); - LocalFree(msgBuffer); - } else { - // WM_PAINT is not automatically sent when invoking AnimateWindow, - // so force an expose event - RECT rect; - ::GetWindowRect(hWnd,&rect); - ::ScreenToClient(hWnd, (LPPOINT)&rect); - ::InvalidateRect(hWnd,&rect,TRUE); - ::UpdateWindow(hWnd); - done = TRUE; - } + BOOL result = ::AnimateWindow(hWnd, (DWORD)200, animateStyle); + if (!result) { + // TODO: log message + } else { + // WM_PAINT is not automatically sent when invoking AnimateWindow, + // so force an expose event + RECT rect; + ::GetWindowRect(hWnd,&rect); + ::ScreenToClient(hWnd, (LPPOINT)&rect); + ::InvalidateRect(hWnd, &rect, TRUE); + ::UpdateWindow(hWnd); + done = TRUE; } } } @@ -1205,16 +1177,17 @@ MsgRouting AwtWindow::WmNcPaint(HRGN hrgn) } /* draw warning text */ - LPWSTR text = TO_WSTRING(warningString); + LPCWSTR text = JNU_GetStringPlatformChars(env, warningString, NULL); VERIFY(::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE)) != CLR_INVALID); VERIFY(::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT)) != CLR_INVALID); VERIFY(::SelectObject(hDC, ::GetStockObject(DEFAULT_GUI_FONT)) != NULL); VERIFY(::SetTextAlign(hDC, TA_LEFT | TA_BOTTOM) != GDI_ERROR); - VERIFY(::ExtTextOutW(hDC, r.left+2, r.bottom-1, + VERIFY(::ExtTextOut(hDC, r.left+2, r.bottom-1, ETO_CLIPPED | ETO_OPAQUE, &r, text, static_cast(wcslen(text)), NULL)); VERIFY(::RestoreDC(hDC, iSaveDC)); ::ReleaseDC(GetHWnd(), hDC); + JNU_ReleaseStringPlatformChars(env, warningString, text); } env->DeleteLocalRef(target); @@ -1360,13 +1333,13 @@ void AwtWindow::RedrawNonClient() } int AwtWindow::GetScreenImOn() { - MHND hmon; + HMONITOR hmon; int scrnNum; - hmon = ::MonitorFromWindow(GetHWnd(), MONITOR_DEFAULT_TO_PRIMARY); + hmon = ::MonitorFromWindow(GetHWnd(), MONITOR_DEFAULTTOPRIMARY); DASSERT(hmon != NULL); - scrnNum = AwtWin32GraphicsDevice::GetScreenFromMHND(hmon); + scrnNum = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hmon); DASSERT(scrnNum > -1); return scrnNum; @@ -1619,10 +1592,10 @@ void AwtWindow::_SetTitle(void *param) if (::IsWindow(w->GetHWnd())) { int length = env->GetStringLength(title); - WCHAR *buffer = new WCHAR[length + 1]; - env->GetStringRegion(title, 0, length, buffer); + TCHAR *buffer = new TCHAR[length + 1]; + env->GetStringRegion(title, 0, length, reinterpret_cast(buffer)); buffer[length] = L'\0'; - VERIFY(::SetWindowTextW(w->GetHWnd(), buffer)); + VERIFY(::SetWindowText(w->GetHWnd(), buffer)); delete[] buffer; } ret: @@ -1967,13 +1940,11 @@ void AwtWindow::_SetFocusableWindow(void *param) window->m_isFocusableWindow = isFocusableWindow; - if (IS_WIN2000) { - if (!window->m_isFocusableWindow) { - LONG isPopup = window->GetStyle() & WS_POPUP; - window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE); - } else { - window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE); - } + if (!window->m_isFocusableWindow) { + LONG isPopup = window->GetStyle() & WS_POPUP; + window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE); + } else { + window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE); } ret: diff --git a/jdk/src/windows/native/sun/windows/awt_dlls.cpp b/jdk/src/windows/native/sun/windows/awt_dlls.cpp deleted file mode 100644 index 26af4196dd9..00000000000 --- a/jdk/src/windows/native/sun/windows/awt_dlls.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#include "awt.h" -#include "awt_dlls.h" - -/* - * To reduce memory footprint we don't statically link to COMDLG32.DLL - * and SHELL32. Instead we programatically load them only when they are - * needed. - */ - -PrintDlgType AwtCommDialog::do_print_dlg; -PageSetupDlgType AwtCommDialog::do_page_setup_dlg; -GetOpenFileNameType AwtCommDialog::get_open_file_name; -GetSaveFileNameType AwtCommDialog::get_save_file_name; -GetExtendedErrorType AwtCommDialog::get_dlg_extended_error; - -/***********************************************************************/ - -DWORD -AwtCommDialog::CommDlgExtendedError(VOID) { - AwtCommDialog::load_comdlg_procs(); - return static_cast(reinterpret_cast( - AwtToolkit::GetInstance(). - InvokeFunction(reinterpret_cast - (AwtCommDialog::GetExtendedErrorWrapper)))); -} - -BOOL -AwtCommDialog::PrintDlg(LPPRINTDLG data) { - AwtCommDialog::load_comdlg_procs(); - return static_cast(reinterpret_cast( - AwtToolkit::GetInstance(). - InvokeFunction(reinterpret_cast - (AwtCommDialog::PrintDlgWrapper), data))); -} - -BOOL -AwtCommDialog::PageSetupDlg(LPPAGESETUPDLG data) { - AwtCommDialog::load_comdlg_procs(); - return static_cast(reinterpret_cast( - AwtToolkit::GetInstance(). - InvokeFunction(reinterpret_cast - (AwtCommDialog::PageSetupDlgWrapper), data))); -} - -/* - * Load the COMDLG32.dll and get pointers to various procedures. - */ - -void -AwtCommDialog::load_comdlg_procs() -{ - static int initialized = 0; - HMODULE lib = NULL; - if (initialized) { - return; - } - lib = LoadLibrary(TEXT("COMDLG32.DLL")); - HMODULE libUnicows = UnicowsLoader::GetModuleHandle(); - do_print_dlg = (PrintDlgType)GetProcAddress(IS_WIN95 ? libUnicows : lib, "PrintDlgW"); - do_page_setup_dlg = (PageSetupDlgType)GetProcAddress(IS_WIN95 ? libUnicows : lib, "PageSetupDlgW"); - get_open_file_name = (GetOpenFileNameType)GetProcAddress(IS_WIN95 ? libUnicows : lib, "GetOpenFileNameW"); - get_save_file_name = (GetSaveFileNameType)GetProcAddress(IS_WIN95 ? libUnicows : lib, "GetSaveFileNameW"); - get_dlg_extended_error = (GetExtendedErrorType)GetProcAddress(lib, "CommDlgExtendedError"); - initialized = 1; -} - -/***********************************************************************/ - -DragQueryFileType do_drag_query_file; -GetPathFromIDListType get_path_from_idlist; - -/* - * Load the SHELL32.dll and get pointers to various procedures. - */ - -void -load_shell_procs() -{ - static int initialized = 0; - HMODULE lib = NULL; - if (initialized) { - return; - } - - if (IS_WIN95) { - lib = UnicowsLoader::GetModuleHandle(); - } else { - lib = LoadLibrary(TEXT("SHELL32.DLL")); - } - - do_drag_query_file = (DragQueryFileType)GetProcAddress(lib, "DragQueryFileW"); - get_path_from_idlist = (GetPathFromIDListType)GetProcAddress(lib, - "SHGetPathFromIDListW"); - initialized = 1; -} - -/***********************************************************************/ - -AnimateWindowType fn_animate_window; -ChangeDisplaySettingsExType fn_change_display_settings_ex; - -/* - * Load the USER32.dll and get pointers to various procedures. - */ - -void -load_user_procs() -{ - static int initialized = 0; - HMODULE lib = NULL; - if (initialized) { - return; - } - lib = LoadLibrary(TEXT("USER32.DLL")); - HMODULE libUnicows = UnicowsLoader::GetModuleHandle(); - fn_animate_window = (AnimateWindowType)GetProcAddress(lib, "AnimateWindow"); - fn_change_display_settings_ex = (ChangeDisplaySettingsExType) - GetProcAddress(IS_WIN95 ? libUnicows : lib, "ChangeDisplaySettingsExW"); - initialized = 1; -} - -/***********************************************************************/ - -GetFileVersionInfoSizeType get_file_version_info_size; -GetFileVersionInfoType get_file_version_info; -VerQueryValueType do_ver_query_value; - -/* - * Load the VERSION.dll and get pointers to various procedures. - */ - -void -load_version_procs() -{ - static int initialized = 0; - HMODULE lib = NULL; - if (initialized) { - return; - } - - if (IS_WIN95) { - lib = UnicowsLoader::GetModuleHandle(); - } else { - lib = LoadLibrary(TEXT("VERSION.DLL")); - } - - get_file_version_info_size = - (GetFileVersionInfoSizeType)GetProcAddress(lib, "GetFileVersionInfoSizeW"); - get_file_version_info = - (GetFileVersionInfoType)GetProcAddress(lib, "GetFileVersionInfoW"); - do_ver_query_value = - (VerQueryValueType)GetProcAddress(lib, "VerQueryValueW"); - initialized = 1; -} - -/***********************************************************************/ - -#define MAX_KNOWN_VERSION 4 - -/* - * We are going to use an undocumented procedure RSRC32.DLL. - * The safest will be to use it only for a finite set of known versions. - */ - -DWORD known_versions[MAX_KNOWN_VERSION][2] = { - { 0x00040000, 0x000003B6 }, // WIN95\RETAIL - // WIN95\RETAIL\UPGRADE - // WIN95\OSR2 - // WIN95\OSR25 - // WIN95\international\RETAIL - // WIN95\international\OSR2 - - { 0x0004000A, 0x00000672 }, // WIN98\international\win98beta3 - - { 0x0004000A, 0x000007CE }, // WIN98\RETAIL - // WIN98\international\RETAIL - // WIN98\SE - - { 0x0004005A, 0x00000BB8 } // WIN98ME -}; - -GetFreeSystemResourcesType get_free_system_resources = NULL; - -/* - * Load the RSRC32.dll, check that it is a known version - * and get the pointer to the undocumented procedure. - */ - -void -load_rsrc32_procs() -{ - static int initialized = 0; - if (initialized) { - return; - } - if (IS_NT) { - // 4310028: Only load library on non-NT systems. The load - // will always fail anyways. However, if a Win 9x OS is - // also installed on the system, and the user's path - // includes C:\WINDOWS\SYSTEM, or the equivalent, a really - // ugly and annoying warning dialog will appear. - initialized = 1; - return; - } - HMODULE lib = LoadLibrary(TEXT("RSRC32.DLL")); - if (lib != NULL) { - TCHAR szFullPath[_MAX_PATH]; - DWORD dwVerHnd = 0; - DWORD dwVersionInfoSize; - LPBYTE lpVersionInfo; - LPVOID lpBuffer; - UINT uLength = 0; - - /* - * We use undocumented procedure exported by RSRC32.DLL, so the - * safest will be to check the library's version and only attempt - * to get the procedure address if it's a known version. - */ - if (::GetModuleFileName(lib, szFullPath, sizeof(szFullPath))) { - load_version_procs(); - dwVersionInfoSize = (*get_file_version_info_size)(szFullPath, &dwVerHnd); - if (dwVersionInfoSize) { - lpVersionInfo = new BYTE[dwVersionInfoSize]; - (*get_file_version_info)(szFullPath, dwVerHnd, - dwVersionInfoSize, lpVersionInfo); - if ((*do_ver_query_value)(lpVersionInfo, TEXT("\\"), &lpBuffer, &uLength)) { - VS_FIXEDFILEINFO *lpvsFixedFileInfo = (VS_FIXEDFILEINFO *)lpBuffer; - DWORD dwFileVersionMS = lpvsFixedFileInfo->dwFileVersionMS; - DWORD dwFileVersionLS = lpvsFixedFileInfo->dwFileVersionLS; - for (int i = 0; i < MAX_KNOWN_VERSION; i++) { - if ((known_versions[i][0] == dwFileVersionMS) && - (known_versions[i][1] == dwFileVersionLS)) { - get_free_system_resources = - (GetFreeSystemResourcesType) - ::GetProcAddress(lib, "_MyGetFreeSystemResources32@4"); - break; - } - } - } - delete[] lpVersionInfo; - } - } - } - initialized = 1; -} - -void -load_rich_edit_library() { - static int initialized = 0; - BOOL isRichEdit32Needed = IS_WIN95 && !IS_WIN98; - - if (initialized) { - return; - } - - HMODULE lib = NULL; - if (isRichEdit32Needed) { - lib = ::LoadLibrary(TEXT("RICHED32.DLL")); - } else { - lib = ::LoadLibrary(TEXT("RICHED20.DLL")); - } - if (lib == NULL) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - JNU_ThrowInternalError(env, "Can't load a rich edit DLL"); - } else if (isRichEdit32Needed) { - // Richedit language checking logic is needed for RICHED32.DLL only. - LPTSTR szFullPath = new TCHAR[_MAX_PATH]; - DWORD dwVerHnd = 0; - DWORD dwVersionInfoSize; - LPVOID lpVersionInfo; - UINT uLength = 0; - struct LANGANDCODEPAGE { - WORD wLanguage; - WORD wCodePage; - } *lpTranslate; - - try { - if (!IS_WIN2000 && ::GetModuleFileName(lib, szFullPath, _MAX_PATH)) { - load_version_procs(); - dwVersionInfoSize = (*get_file_version_info_size)(szFullPath, &dwVerHnd); - if (dwVersionInfoSize) { - lpVersionInfo = new BYTE[dwVersionInfoSize]; - try { - if ((*get_file_version_info)(szFullPath, - dwVerHnd, - dwVersionInfoSize, - lpVersionInfo) - && (*do_ver_query_value)(lpVersionInfo, - TEXT("\\VarFileInfo\\Translation"), - (LPVOID*)&lpTranslate, - &uLength)) { - - if (::GetSystemMetrics(SM_DBCSENABLED) - && LANGIDFROMLCID(::GetThreadLocale()) != lpTranslate[0].wLanguage) { - - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - if (env->PushLocalFrame(6) >= 0) { - jstring keystr = env->NewStringUTF("AWT.InconsistentDLLsWarning"); - jstring defstr = env->NewStringUTF( -"Text based operations may not work correctly due to \ -an inconsistent set of dynamic linking libraries (DLLs) installed on your \ -system. For more information on this problem and a suggested workaround \ -please see the Java(TM) 2 SDK, Standard Edition Release Notes \ -on java.sun.com."); - - jstring retstr = - (jstring) JNU_CallStaticMethodByName( - env, - NULL, - "java/awt/Toolkit", - "getProperty", - "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", - keystr, - defstr).l; - - jboolean exception; - jstring pkgstr = env->NewStringUTF("java.awt"); - jobject logger = - (jobject) JNU_CallStaticMethodByName( - env, - &exception, - "java/util/logging/Logger", - "getLogger", - "(Ljava/lang/String;)Ljava/util/logging/Logger;", - pkgstr).l; - - jstring msgstr = (retstr) ? retstr : defstr; - if (!exception) { - JNU_CallMethodByName( - env, - NULL, - logger, - "warning", - "(Ljava/lang/String;)V", - msgstr); - } else { - LPCTSTR outstr = JNU_GetStringPlatformChars(env, msgstr, NULL); - _ftprintf(stdout, TEXT("\nWARNING: %s\n"), outstr); - fflush(stdout); - JNU_ReleaseStringPlatformChars(env, msgstr, outstr); - } - - env->PopLocalFrame(NULL); - } - } - } - } catch (...) { - delete[] lpVersionInfo; - throw; - } - delete[] lpVersionInfo; - } - } - } catch (...) { - delete[] szFullPath; - throw; - } - delete[] szFullPath; - } - initialized = 1; -} - -/***********************************************************************/ - -bool AwtWinMM::initialized = false; -AwtWinMM::PlaySoundWFunc* AwtWinMM::playSoundFunc = NULL; - -BOOL AwtWinMM::PlaySoundWrapper(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound) { - load_winmm_procs(); - if (playSoundFunc == NULL) { - return FALSE; - } - return (*playSoundFunc)(pszSound, hmod, fdwSound); -} - -void AwtWinMM::load_winmm_procs() { - if (initialized) { - return; - } - HMODULE dll = NULL; - - if (IS_WIN95) { - dll = UnicowsLoader::GetModuleHandle(); - } else { - dll = ::LoadLibrary(TEXT("winmm.dll")); - } - - if (dll == NULL) { - return; - } - playSoundFunc = - (PlaySoundWFunc*) GetProcAddress(dll, "PlaySoundW"); - if (playSoundFunc == NULL) { - return; - } - initialized = true; -} diff --git a/jdk/src/windows/native/sun/windows/awt_dlls.h b/jdk/src/windows/native/sun/windows/awt_dlls.h deleted file mode 100644 index b7e08980226..00000000000 --- a/jdk/src/windows/native/sun/windows/awt_dlls.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#ifndef AWT_DLLS_H -#define AWT_DLLS_H - -#include -#include -#include -#include "awt_FileDialog.h" -#include "awt_PrintDialog.h" - -/* - * To reduce memory footprint we don't statically link to COMDLG32.DLL - * and SHELL32. Instead we programatically load them only when they are - * needed. - */ - -//--------------------------------------------------------------------------- - -typedef BOOL (APIENTRY *PrintDlgType)(LPPRINTDLGW); -typedef BOOL (APIENTRY *PageSetupDlgType)(LPPAGESETUPDLGW); -typedef BOOL (APIENTRY *GetOpenFileNameType)(LPOPENFILENAMEW); -typedef BOOL (APIENTRY *GetSaveFileNameType)(LPOPENFILENAMEW); -typedef DWORD (APIENTRY *GetExtendedErrorType)(VOID); - -class AwtCommDialog { -public: - static DWORD CommDlgExtendedError(VOID); - - static BOOL PrintDlg(LPPRINTDLG data); - - static BOOL PageSetupDlg(LPPAGESETUPDLG data); - -private: - static void load_comdlg_procs(); - - // Use wrapper functions with default calling convention. If the - // default isn't __stdcall, accessing the Win32 functions directly - // will cause stack corruption if we cast away __stdcall. - static BOOL PrintDlgWrapper(LPPRINTDLG data) { - return (*do_print_dlg)(data); - } - static BOOL PageSetupDlgWrapper(LPPAGESETUPDLG data) { - return (*do_page_setup_dlg)(data); - } - static BOOL GetOpenFileNameWrapper(LPOPENFILENAME data) { - return (*get_open_file_name)(data); - } - static BOOL GetSaveFileNameWrapper(LPOPENFILENAME data) { - return (*get_save_file_name)(data); - } - static DWORD GetExtendedErrorWrapper(VOID) { - return (*get_dlg_extended_error)(); - } - - friend BOOL AwtFileDialog::GetOpenFileName(LPAWTOPENFILENAME); - friend BOOL AwtFileDialog::GetSaveFileName(LPAWTOPENFILENAME); - friend BOOL AwtPrintDialog::PrintDlg(LPPRINTDLG); - - static PrintDlgType do_print_dlg; - static PageSetupDlgType do_page_setup_dlg; - static GetOpenFileNameType get_open_file_name; - static GetSaveFileNameType get_save_file_name; - static GetExtendedErrorType get_dlg_extended_error; -}; - -//--------------------------------------------------------------------------- - -// Dynamically load in SHELL32.DLL and define the procedure pointers listed below. -extern void load_shell_procs(); - -// Procedure pointers obtained from SHELL32.DLL -// You must call load_shell_procs() before using any of these. -typedef UINT (APIENTRY *DragQueryFileType)(HDROP,UINT,LPTSTR,UINT); -typedef BOOL (APIENTRY *GetPathFromIDListType)(LPCITEMIDLIST,LPTSTR); -extern DragQueryFileType do_drag_query_file; -extern GetPathFromIDListType get_path_from_idlist; - -//--------------------------------------------------------------------------- - -// Dynamically load in USER32.DLL and define the procedure pointers listed below. -extern void load_user_procs(); - -// Procedure pointers obtained from USER32.DLL -// You must call load_user_procs() before using any of these. -typedef BOOL (WINAPI *AnimateWindowType)(HWND,DWORD,DWORD); -typedef LONG (WINAPI *ChangeDisplaySettingsExType)(LPCTSTR,LPDEVMODE,HWND,DWORD,LPVOID lParam); -extern AnimateWindowType fn_animate_window; -extern ChangeDisplaySettingsExType fn_change_display_settings_ex; - -//--------------------------------------------------------------------------- - -// Dynamically load in VERSION.DLL and define the procedure pointers listed below. -extern void load_version_procs(); - -// Procedure pointers obtained from VERSION.DLL -// You must call load_version_procs() before using any of these. -typedef DWORD (APIENTRY *GetFileVersionInfoSizeType)(LPTSTR,LPDWORD); -typedef BOOL (APIENTRY *GetFileVersionInfoType)(LPTSTR,DWORD,DWORD,LPVOID); -typedef BOOL (APIENTRY *VerQueryValueType)(const LPVOID,LPTSTR,LPVOID*,PUINT); -extern GetFileVersionInfoSizeType get_file_version_info_size; -extern GetFileVersionInfoType get_file_version_info; -extern VerQueryValueType do_ver_query_value; - -//--------------------------------------------------------------------------- - -// Dynamically load in RSRC32.DLL and define the procedure pointers listed below. -extern void load_rsrc32_procs(); - -// Procedure pointers obtained from RSRC32.DLL -// You must call load_rsrc32_procs() before using this procedure. - -/* - * NOTE: even after load_rsrc32_procs() you must check that - * the function pointer is valid before use. - * It will be NULL in three cases: - * 1.RSRC32.DLL not found. This means that Resource Meter - * isn't installed. - * 2.RSRC32.DLL can't be loaded. This happens on WinNT. - * 3.Unknown version of RSRC32.DLL. This is undocumented - * procedure, so the safest will be to use it only for - * a finite set of known versions. - */ -typedef UINT (APIENTRY *GetFreeSystemResourcesType)(UINT); - -extern GetFreeSystemResourcesType get_free_system_resources; - -extern void load_rich_edit_library(); - -//--------------------------------------------------------------------------- - -/* - * Loading WINMM.DLL (the Windows MultiMedia library) is extremely - * expensive. The AWT only uses it to play certain Windows sounds - * (which are off by default) so we dynamically load it upon demand - * instead of statically linking to it. - */ - -class AwtWinMM { -public: - static BOOL PlaySoundWrapper(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound); - -private: - static void load_winmm_procs(); - static bool initialized; - typedef BOOL WINAPI PlaySoundWFunc(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound); - static PlaySoundWFunc* playSoundFunc; -}; - -#endif /* AWT_DLLS_H */ diff --git a/jdk/src/windows/native/sun/windows/awtmsg.h b/jdk/src/windows/native/sun/windows/awtmsg.h index fe03b0c460c..35e436b53e7 100644 --- a/jdk/src/windows/native/sun/windows/awtmsg.h +++ b/jdk/src/windows/native/sun/windows/awtmsg.h @@ -182,18 +182,6 @@ extern const UINT SYSCOMMAND_IMM; #endif //AW_BLEND - - -// WM_MOUSEWHEEL should be WM_MOUSELAST, but -// is not being defined. See winuser.h -#ifdef WM_MOUSELAST -#if WM_MOUSELAST <= 0x020A -#define WM_AWT_MOUSELAST 0x020A -#else -#error Unexpected value of WM_MOUSELAST -#endif //WM_MOUSELAST <= 0x0209 -#endif //WM_MOUSELAST - // AwtComponent messages enum { // 6427323: unfortunately WM_APP+nnn conflicts with edit control messages diff --git a/jdk/src/windows/native/sun/windows/jawt.cpp b/jdk/src/windows/native/sun/windows/jawt.cpp index 91de38a9fd5..ae2d09dd4d9 100644 --- a/jdk/src/windows/native/sun/windows/jawt.cpp +++ b/jdk/src/windows/native/sun/windows/jawt.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define _JNI_IMPLEMENTATION_ #include +#include "awt.h" #include "awt_DrawingSurface.h" /* diff --git a/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java b/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java new file mode 100644 index 00000000000..3111b6e9c65 --- /dev/null +++ b/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java @@ -0,0 +1,136 @@ +/* + @test + @bug 6304473 6727884 + @summary Tests that an exception on EDT is handled with ThreadGroup.uncaughtException() + @author artem.ananiev: area=awt.eventdispatching + @library ../../regtesthelpers + @build Util + @run main HandleExceptionOnEDT +*/ + +import java.awt.*; +import java.awt.event.*; + +import test.java.awt.regtesthelpers.Util; + +public class HandleExceptionOnEDT +{ + private final static String EXCEPTION_MESSAGE = "A1234567890"; + + private static volatile boolean exceptionHandled = false; + private static volatile boolean mousePressed = false; + + public static void main(String[] args) + { + final Thread.UncaughtExceptionHandler eh = new Thread.UncaughtExceptionHandler() + { + @Override + public void uncaughtException(Thread t, Throwable e) + { + if (e.getMessage().equals(EXCEPTION_MESSAGE)) + { + exceptionHandled = true; + } + } + }; + + Frame f = new Frame("F"); + f.setBounds(100, 100, 400, 300); + // set exception handler for EDT + f.addWindowListener(new WindowAdapter() + { + @Override + public void windowOpened(WindowEvent we) + { + Thread edt = Thread.currentThread(); + edt.setUncaughtExceptionHandler(eh); + } + }); + f.setVisible(true); + + Robot r = Util.createRobot(); + Util.waitForIdle(r); + + // check exception without modal dialog + MouseListener exceptionListener = new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent me) + { + throw new RuntimeException(EXCEPTION_MESSAGE); + } + }; + f.addMouseListener(exceptionListener); + + exceptionHandled = false; + Point fp = f.getLocationOnScreen(); + r.mouseMove(fp.x + f.getWidth() / 2, fp.y + f.getHeight() / 2); + Util.waitForIdle(r); + r.mousePress(InputEvent.BUTTON1_MASK); + Util.waitForIdle(r); + r.mouseRelease(InputEvent.BUTTON2_MASK); + f.removeMouseListener(exceptionListener); + + if (!exceptionHandled) + { + throw new RuntimeException("Test FAILED: exception is not handled for frame"); + } + + // check exception with modal dialog + final Dialog d = new Dialog(f, "D", true); + d.setBounds(fp.x + 100, fp.y + 100, 400, 300); + d.addMouseListener(exceptionListener); + EventQueue.invokeLater(new Runnable() + { + @Override + public void run() + { + d.setVisible(true); + } + }); + Util.waitForIdle(r); + + exceptionHandled = false; + Point dp = d.getLocationOnScreen(); + r.mouseMove(dp.x + d.getWidth() / 2, dp.y + d.getHeight() / 2); + Util.waitForIdle(r); + r.mousePress(InputEvent.BUTTON1_MASK); + Util.waitForIdle(r); + r.mouseRelease(InputEvent.BUTTON2_MASK); + d.removeMouseListener(exceptionListener); + + if (!exceptionHandled) + { + throw new RuntimeException("Test FAILED: exception is not handled for modal dialog"); + } + + // check the dialog is still modal + MouseListener pressedListener = new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent me) + { + mousePressed = true; + } + }; + f.addMouseListener(pressedListener); + + mousePressed = false; + r.mouseMove(fp.x + 50, fp.y + 50); + Util.waitForIdle(r); + r.mousePress(InputEvent.BUTTON1_MASK); + Util.waitForIdle(r); + r.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(r); + f.removeMouseListener(pressedListener); + + if (mousePressed) + { + throw new RuntimeException("Test FAILED: modal dialog is not modal or visible after exception"); + } + + // test is passed + d.dispose(); + f.dispose(); + } +} diff --git a/jdk/test/java/awt/Frame/FrameSize/TestFrameSize.java b/jdk/test/java/awt/Frame/FrameSize/TestFrameSize.java new file mode 100644 index 00000000000..f8a98ea3216 --- /dev/null +++ b/jdk/test/java/awt/Frame/FrameSize/TestFrameSize.java @@ -0,0 +1,67 @@ +/* + * Copyright 2009 Red Hat, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + @test + @bug 6721088 + @summary X11 Window sizes should be what we set them to + @author Omair Majid : area=awt.toplevel + @run main TestFrameSize + */ + +/** + * TestFrameSize.java + * + * Summary: test that X11 Awt windows are drawn with correct sizes + * + * Test fails if size of window is wrong + */ + +import java.awt.Dimension; +import java.awt.Frame; + +public class TestFrameSize { + + static Dimension desiredDimensions = new Dimension(200, 200); + static int ERROR_MARGIN = 15; + static Frame mainWindow; + + public static void drawGui() { + mainWindow = new Frame(""); + mainWindow.setPreferredSize(desiredDimensions); + mainWindow.pack(); + + Dimension actualDimensions = mainWindow.getSize(); + System.out.println("Desired dimensions: " + desiredDimensions.toString()); + System.out.println("Actual dimensions: " + actualDimensions.toString()); + if (Math.abs(actualDimensions.height - desiredDimensions.height) > ERROR_MARGIN) { + throw new RuntimeException("Incorrect widow size"); + } + } + + public static void main(String[] args) { + try { + drawGui(); + } finally { + if (mainWindow != null) { + mainWindow.dispose(); + } + } + } +} diff --git a/jdk/test/java/awt/Mixing/HWDisappear.java b/jdk/test/java/awt/Mixing/HWDisappear.java new file mode 100644 index 00000000000..875c49f567d --- /dev/null +++ b/jdk/test/java/awt/Mixing/HWDisappear.java @@ -0,0 +1,426 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test %W% %E% + @bug 6769511 + @summary AWT components are invisible for a while after frame is moved & menu items are visible + @author anthony.petrov@...: area=awt.mixing + @library ../regtesthelpers + @build Util + @run main HWDisappear +*/ + +/** + * HWDisappear.java + * + * summary: AWT components are invisible for a while after frame is moved & menu items are visible + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import test.java.awt.regtesthelpers.Util; + +public class HWDisappear +{ + + static volatile boolean clickPassed = false; + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + + // Create the frame and the button + JFrame f = new JFrame(); + f.setBounds(100, 100, 400, 300); + + JMenuBar menubar = new JMenuBar(); + f.setJMenuBar(menubar); + + // Create lightweight-enabled menu + JMenu lmenu = new JMenu("Lite Menu"); + lmenu.add("Salad"); + lmenu.add("Fruit Plate"); + lmenu.add("Water"); + menubar.add(lmenu); + + Button b = new Button("OK"); + + f.setLayout(null); + f.add(b); + b.setBounds(50, 50, 200, 50); + + b.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent e) { + clickPassed = true; + } + }); + + f.setVisible(true); + + Robot robot = Util.createRobot(); + robot.setAutoDelay(20); + + Util.waitForIdle(robot); + + // Move quite far to ensure the button is hidden completely + f.setLocation(500, 200); + + Util.waitForIdle(robot); + + // Activate the menu + Point lLoc = lmenu.getLocationOnScreen(); + robot.mouseMove(lLoc.x + 5, lLoc.y + 5); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + // Click on the button. + Point bLoc = b.getLocationOnScreen(); + robot.mouseMove(bLoc.x + b.getWidth() / 2, bLoc.y + 5); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + if (clickPassed) { + pass(); + } else { + fail("The button cannot be clicked."); + } + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class HWDisappear + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + HWDisappear.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + HWDisappear.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class diff --git a/jdk/test/java/awt/Mixing/JButtonInGlassPane.java b/jdk/test/java/awt/Mixing/JButtonInGlassPane.java new file mode 100644 index 00000000000..158e438c538 --- /dev/null +++ b/jdk/test/java/awt/Mixing/JButtonInGlassPane.java @@ -0,0 +1,430 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test %W% %E% + @bug 6779670 + @summary Tests if a LW components in the glass pane affects HW in the content pane + @author anthony.petrov@...: area=awt.mixing + @library ../regtesthelpers + @build Util + @run main JButtonInGlassPane +*/ + + +/** + * JButtonInGlassPane.java + * + * summary: Tests whether a LW menu correctly overlaps a HW button + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import test.java.awt.regtesthelpers.Util; + + + +public class JButtonInGlassPane +{ + static volatile boolean failed = false; + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + JFrame frame = new JFrame("Glass Pane children test"); + frame.setLayout(null); + + final Button button = new Button("AWT Button"); + button.setBounds(100,100,100,100); + frame.add(button); + + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + failed = true; + } + }); + + frame.getGlassPane().setVisible(true); + Container glassPane = (Container) frame.getGlassPane(); + glassPane.setLayout(null); + + final JButton jbutton = new JButton("JButton"); + jbutton.setBounds(50,50,100,100); + glassPane.add(jbutton); + + jbutton.setVisible(false); + + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + Robot robot = Util.createRobot(); + robot.setAutoDelay(20); + + Util.waitForIdle(robot); + + jbutton.setVisible(true); + Util.waitForIdle(robot); + + // Click the LW button - in the area that intersects with + // the HW button. + Point lLoc = jbutton.getLocationOnScreen(); + robot.mouseMove(lLoc.x + jbutton.getWidth() - 5, lLoc.y + jbutton.getHeight() - 5); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + jbutton.setBounds(50,50,120,120); + Util.waitForIdle(robot); + + // Now click on the 'added' area of the LW button that again + // intersects with the HW. + robot.mouseMove(lLoc.x + jbutton.getWidth() - 5, lLoc.y + jbutton.getHeight() - 5); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + if (failed) { + JButtonInGlassPane.fail("The LW button did not receive the click."); + } else { + JButtonInGlassPane.pass(); + } + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class JButtonInGlassPane + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + JButtonInGlassPane.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + JButtonInGlassPane.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + + diff --git a/jdk/test/java/awt/Mixing/LWComboBox.java b/jdk/test/java/awt/Mixing/LWComboBox.java new file mode 100644 index 00000000000..8108ff9a3dc --- /dev/null +++ b/jdk/test/java/awt/Mixing/LWComboBox.java @@ -0,0 +1,425 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test %W% %E% + @bug 6637655 + @summary Tests whether a LW combobox correctly overlaps a HW button + @author anthony.petrov@...: area=awt.mixing + @library ../regtesthelpers + @build Util + @run main LWComboBox +*/ + + +/** + * LWComboBox.java + * + * summary: Tests whether a LW combobox correctly overlaps a HW button + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.util.Vector; +import test.java.awt.regtesthelpers.Util; + + + +public class LWComboBox +{ + static volatile boolean failed = false; + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + JFrame f = new JFrame("LW menu test"); + + JComboBox ch; + Button b; + + Vector v = new Vector(); + for(int i = 1 ; i <=20;i++){ + v.add("Item # "+i); + } + ch = new JComboBox(v); + + + b = new Button("AWT Button"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + failed = true; + } + }); + + f.add(ch,BorderLayout.NORTH); + f.add(b,BorderLayout.CENTER); + f.setSize(300,300); + f.setVisible(true); + + Robot robot = Util.createRobot(); + robot.setAutoDelay(20); + + Util.waitForIdle(robot); + + // Pop up the combobox + Point lLoc = ch.getLocationOnScreen(); + System.err.println("lLoc: " + lLoc); + robot.mouseMove(lLoc.x + 5, lLoc.y + 5); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + // Click on the combo popup. + // It's assumed that the popup item is located + // above the heavyweight button. + Point bLoc = b.getLocationOnScreen(); + System.err.println("bLoc: " + bLoc); + robot.mouseMove(bLoc.x + 10, bLoc.y + 10); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + if (failed) { + fail("The LW popup did not received the click."); + } else { + pass(); + } + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class LWComboBox + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + LWComboBox.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + LWComboBox.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + + diff --git a/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java b/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java new file mode 100644 index 00000000000..a1adebe829b --- /dev/null +++ b/jdk/test/java/awt/Mixing/MixingOnShrinkingHWButton.java @@ -0,0 +1,429 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test %W% %E% + @bug 6777320 + @summary PIT : Canvas is not fully painted on the internal frame & internal frame goes behind the canvas + @author dmitry.cherepanov@...: area=awt.mixing + @library ../regtesthelpers + @build Util + @run main MixingOnShrinkingHWButton +*/ + + +/** + * MixingOnDialog.java + * + * summary: Tests whether awt.Button and swing.JButton mix correctly + * when awt.Button's width got shrinked + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import test.java.awt.regtesthelpers.Util; + + + +public class MixingOnShrinkingHWButton +{ + static volatile boolean heavyClicked = false; + static volatile boolean lightClicked = false; + + private static void init() + { + //*** Create instructions for the user here *** + + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + + // Create components + final Dialog d = new Dialog((Frame)null, "Button-JButton mix test"); + final Button heavy = new Button(" Heavyweight Button "); + final JButton light = new JButton(" LW Button "); + + // Actions for the buttons add appropriate number to the test sequence + heavy.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent e) { + heavyClicked = true; + } + } + ); + + light.addActionListener(new java.awt.event.ActionListener() + { + public void actionPerformed(java.awt.event.ActionEvent e) { + lightClicked = true; + } + } + ); + + // Shrink the HW button under LW button + heavy.setBounds(30, 30, 100, 100); + light.setBounds(40, 30, 100, 100); + + // Put the components into the frame + d.setLayout(null); + d.add(light); + d.add(heavy); + d.setBounds(50, 50, 400, 400); + d.setVisible(true); + + + Robot robot = Util.createRobot(); + robot.setAutoDelay(20); + + Util.waitForIdle(robot); + + // Move the mouse pointer to the position where both + // buttons overlap + Point heavyLoc = heavy.getLocationOnScreen(); + robot.mouseMove(heavyLoc.x + 20, heavyLoc.y + 20); + + // Now perform the click at this point + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + // If the buttons are correctly mixed, the test sequence + // is equal to the check sequence. + if (lightClicked == true) { + MixingOnShrinkingHWButton.pass(); + } else { + MixingOnShrinkingHWButton.fail("The lightweight component left behind the heavyweight one."); + } + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class MixingOnDialog + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + MixingOnDialog.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + MixingOnDialog.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + + diff --git a/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java b/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java new file mode 100644 index 00000000000..e1840ee6c6f --- /dev/null +++ b/jdk/test/java/awt/Mixing/NonOpaqueInternalFrame.java @@ -0,0 +1,434 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test %W% %E% + @bug 6768332 + @summary Tests whether internal frames are always considered opaque + @author anthony.petrov@...: area=awt.mixing + @library ../regtesthelpers + @build Util + @run main NonOpaqueInternalFrame +*/ + + +/** + * NonOpaqueInternalFrame.java + * + * summary: Tests whether internal frames are always considered opaque + */ + +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyVetoException; +import javax.swing.*; +import java.util.Vector; +import test.java.awt.regtesthelpers.Util; + + + +public class NonOpaqueInternalFrame +{ + static volatile boolean failed = false; + + private static final class MyButton extends Button + implements ActionListener + { + public MyButton() { + setPreferredSize(new Dimension(100, 100)); + addActionListener(this); + } + + public void actionPerformed(ActionEvent e) { + failed = true; + } + } + + private static void init() + { + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + + // Create a frame with two non-opaque JInternalFrame's containing + // heavyweight buttons. + JFrame jframe = new JFrame("mixing test"); + JDesktopPane desktop = new JDesktopPane(); + jframe.setContentPane(desktop); + JInternalFrame iframe1 = new JInternalFrame("iframe 1"); + iframe1.setIconifiable(true); + iframe1.add(new MyButton()); + iframe1.setBounds(10, 10, 100, 100); + iframe1.setOpaque(false); + iframe1.setVisible(true); + desktop.add(iframe1); + JInternalFrame iframe2 = new JInternalFrame("iframe 2"); + iframe2.setIconifiable(true); + iframe2.add(new MyButton()); + iframe2.setBounds(50, 50, 100, 100); + iframe2.setOpaque(false); + iframe2.setVisible(true); + desktop.add(iframe2); + jframe.setSize(300, 300); + jframe.setVisible(true); + + Robot robot = Util.createRobot(); + robot.setAutoDelay(20); + + Util.waitForIdle(robot); + + // Try selecting the bottommost frame + try { + iframe2.setSelected(true); + } catch (PropertyVetoException ex) { + ex.printStackTrace(); + } + + // Click the title bar of the internal frame + Point lLoc = iframe2.getLocationOnScreen(); + System.err.println("lLoc: " + lLoc); + robot.mouseMove(lLoc.x + 10, lLoc.y + 10); + Util.waitForIdle(robot); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + + if (failed) { + fail("The JInternalFrame is considered non-opaque."); + } else { + pass(); + } + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class NonOpaqueInternalFrame + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + NonOpaqueInternalFrame.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + NonOpaqueInternalFrame.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + + diff --git a/jdk/test/java/awt/Mixing/OpaqueTest.java b/jdk/test/java/awt/Mixing/OpaqueTest.java index 6d00f4393be..7d215316faf 100644 --- a/jdk/test/java/awt/Mixing/OpaqueTest.java +++ b/jdk/test/java/awt/Mixing/OpaqueTest.java @@ -42,6 +42,7 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import test.java.awt.regtesthelpers.Util; +import com.sun.awt.AWTUtilities; @@ -78,6 +79,7 @@ public class OpaqueTest { public void actionPerformed(java.awt.event.ActionEvent e) { p.setComponentZOrder(light, 0); + f.validate(); testSeq = testSeq + "0"; } } @@ -87,6 +89,7 @@ public class OpaqueTest { public void actionPerformed(java.awt.event.ActionEvent e) { p.setComponentZOrder(heavy, 0); + f.validate(); testSeq = testSeq + "1"; } } @@ -120,10 +123,12 @@ public class OpaqueTest // flag value. for (int i = 0; i < 9; ++i) { if (i == 3) { - light.setOpaque(false); + AWTUtilities.setComponentMixingCutoutShape(light, + new Rectangle()); } if (i == 6) { - light.setOpaque(true); + AWTUtilities.setComponentMixingCutoutShape(light, + null); } robot.mousePress(InputEvent.BUTTON1_MASK); diff --git a/jdk/test/java/awt/Mixing/OverlappingButtons.java b/jdk/test/java/awt/Mixing/OverlappingButtons.java index 85faba8d742..dc80852aa8a 100644 --- a/jdk/test/java/awt/Mixing/OverlappingButtons.java +++ b/jdk/test/java/awt/Mixing/OverlappingButtons.java @@ -78,6 +78,7 @@ public class OverlappingButtons { public void actionPerformed(java.awt.event.ActionEvent e) { p.setComponentZOrder(light, 0); + f.validate(); testSeq = testSeq + "0"; } } @@ -87,6 +88,7 @@ public class OverlappingButtons { public void actionPerformed(java.awt.event.ActionEvent e) { p.setComponentZOrder(heavy, 0); + f.validate(); testSeq = testSeq + "1"; } } diff --git a/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html b/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html new file mode 100644 index 00000000000..81d845c6ca0 --- /dev/null +++ b/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html @@ -0,0 +1,42 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + + + + + + +

bug 6176814
Bug ID: 6176814

+ +

This is an AUTOMATIC test, simply wait for completion

+ + + + diff --git a/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java b/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java new file mode 100644 index 00000000000..6f6b51cd605 --- /dev/null +++ b/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + test + @bug 6176814 + @summary Metalworks frame maximizes after the move + @author Andrei.Dmitriev area=Event + @run applet MaximizedFrameTest.html +*/ + +import java.applet.Applet; +import javax.swing.*; +import java.awt.event.*; +import java.awt.*; + +public class MaximizedFrameTest extends Applet +{ + final int ITERATIONS_COUNT = 20; + Robot robot; + Point framePosition; + Point newFrameLocation; + JFrame frame; + Rectangle gcBounds; + public static Object LOCK = new Object(); + + public void init() + { + String[] instructions = + { + "This is an AUTOMATIC test", + "simply wait until it is done" + }; + JFrame.setDefaultLookAndFeelDecorated(true); + frame = new JFrame("JFrame Maximization Test"); + frame.pack(); + frame.setSize(450, 260); + }//End init() + + public void start () + { + frame.setVisible(true); + validate(); + JLayeredPane lPane = frame.getLayeredPane(); + // System.out.println("JFrame's LayeredPane " + lPane ); + Component titleComponent = null; + boolean titleFound = false; + for (int j=0; j < lPane.getComponentsInLayer(JLayeredPane.FRAME_CONTENT_LAYER.intValue()).length; j++){ + titleComponent = lPane.getComponentsInLayer(JLayeredPane.FRAME_CONTENT_LAYER.intValue())[j]; + if (titleComponent.getClass().getName().equals("javax.swing.plaf.metal.MetalTitlePane")){ + titleFound = true; + break; + } + } + if ( !titleFound ){ + throw new RuntimeException("Test Failed. Unable to determine title's size."); + } + //-------------------------------- + // it is sufficient to get maximized Frame only once. + Point tempMousePosition; + framePosition = frame.getLocationOnScreen(); + try { + robot = new Robot(); + tempMousePosition = new Point(framePosition.x + + frame.getWidth()/2, + framePosition.y + + titleComponent.getHeight()/2); + robot.mouseMove(tempMousePosition.x, tempMousePosition.y); + for (int iteration=0; iteration < ITERATIONS_COUNT; iteration++){ + robot.mousePress(InputEvent.BUTTON1_MASK); + gcBounds = + GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getConfigurations()[0].getBounds(); + //Moving a mouse pointer less than a few pixels + //leads to rising a double click event. + //We have to use exceeded the AWT_MULTICLICK_SMUDGE + //const value (which is 4 by default on GNOME) to test that. + tempMousePosition.x += 5; + robot.mouseMove(tempMousePosition.x, tempMousePosition.y); + robot.delay(70); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + if ( frame.getExtendedState() != 0 ){ + throw new RuntimeException ("Test failed. JFrame was maximized. ExtendedState is : "+frame.getExtendedState()); + } + robot.delay(500); + } //for iteration + + }catch(AWTException e) { + throw new RuntimeException("Test Failed. AWTException thrown."); + } + System.out.println("Test passed."); + }// start() +}// class diff --git a/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java new file mode 100644 index 00000000000..e49736ca875 --- /dev/null +++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java @@ -0,0 +1,131 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that drag events are coming for every button if the property is set to true + @author Andrei Dmitriev : area=awt.mouse + @run main ExtraButtonDrag + */ + +//events from standard should also come + +import java.awt.*; +import java.awt.event.*; + +public class ExtraButtonDrag extends Frame { + static String tk = Toolkit.getDefaultToolkit().getClass().getName(); + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + volatile static boolean dragged = false; + volatile static boolean moved = false; + + public ExtraButtonDrag(){ + super("ExtraButtonDrag"); + } + + public static void main(String []s){ + Frame frame = new ExtraButtonDrag(); + + MouseAdapter ma = new MouseAdapter() { + public void mouseDragged(MouseEvent e) { + System.out.println("Dragged "+e);// +" : "+ e.getButton() + " : " +e.getButtonState(e.getButton())); + dragged = true; + } + public void mouseMoved(MouseEvent e) { + System.out.println("Moved "+e); + moved = true; + } + public void mousePressed(MouseEvent e) { + System.out.println(">>> "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println(">>> "+e); + } + + }; + + frame.addMouseMotionListener(ma); + frame.addMouseListener(ma); + + frame.setSize(300, 300); + frame.setVisible(true); + + int [] buttonMask = new int [MouseInfo.getNumberOfButtons()]; //InputEvent.getButtonMasks(); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMask[i] = InputEvent.getMaskForButton(i+1); + // System.out.println("TEST: "+tmp[i]); + } + + try { + robot = new Robot(); + robot.delay(1000); + Point centerFrame = new Point(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + Point outboundsFrame = new Point(frame.getLocationOnScreen().x + frame.getWidth()*3/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("areExtraMouseButtonsEnabled() == " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() ); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to drag = " +(i+1) + " : value passed to robot = " +buttonMask[i]); + + try { + dragMouse(buttonMask[i], centerFrame.x, centerFrame.y, outboundsFrame.x, outboundsFrame.y); + } catch (IllegalArgumentException e){ + throw new RuntimeException("Test failed. Exception occured.", e); + } + + robot.delay(500); + //this is a choice-case for X protocol issue: native events from extra buttons doesn't contain + // the correct state so it's unable to decide if there is a drag or move. By default we send MOVED event. + //XToolkit: extra buttons should report MOVED events only + //WToolkit: extra buttons should report DRAGGED events only + if (i > 2){ //extra buttons only + if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (!moved || dragged) { + throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); + } + } else { //WToolkit + if (moved || !dragged) { + throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); + } + } + } else { + if (moved || !dragged){ + throw new RuntimeException("Test failed. Button = " +(i+1) + " not dragged."); + } + } + } + } catch (Exception e){ + throw new RuntimeException("", e); + } + } + + public static void dragMouse(int button, int x0, int y0, int x1, int y1){ + int curX = x0; + int curY = y0; + int dx = x0 < x1 ? 1 : -1; + int dy = y0 < y1 ? 1 : -1; + robot.mouseMove(x0, y0); + + robot.delay(200); + dragged = false; + moved = false; + + robot.mousePress(button); + + while (curX != x1){ + curX += dx; + robot.mouseMove(curX, curY); + robot.delay(5); + } + while (curY != y1 ){ + curY += dy; + robot.mouseMove(curX, curY); + robot.delay(5); + } + robot.mouseRelease(button); + } + +} + diff --git a/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ModifierPermutation.java b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ModifierPermutation.java new file mode 100644 index 00000000000..2c22669a4da --- /dev/null +++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/ModifierPermutation.java @@ -0,0 +1,320 @@ +/* + test %I% %E% + @bug 6315717 + @summary presses buttons in all permutations and verifies modifiers + @author Andrei Dmitriev : area=awt.mouse + @run main ModifierPermutation + */ +//package modifierpermutation; + +/* +The test will try to press-release every button present on the mouse in different order. +Here are some abbreviations: + BUTTON1 press = P1 + BUTTON2 press = P2 etc. + BUTTON1 release = R1 + BUTTON2 release = R2 etc. +Only sequences alike below are possible : . +Sequences like will not be covered by this test due to its probable complexity. + */ + +import java.awt.*; +import sun.awt.SunToolkit; +import java.awt.event.*; +import java.util.Arrays; + +public class ModifierPermutation { + static boolean failed = false; + final static int BUTTONSNUMBER = MouseInfo.getNumberOfButtons(); + +/* + * Because of some problems with BUTTONx_MASK + * (they are not ordered. Instead, their values are: 16 8 4) + * We have to use array [1..n] and make every permutation on its + * containment. After each permutation, make the same thing with + * array of buttons and array of expected modifiers. + */ + static SunToolkit st = (SunToolkit)(Toolkit.getDefaultToolkit()); + //all button masks + static int [] mouseButtons = new int [BUTTONSNUMBER]; //BUTTONx_MASK + static int [] mouseButtonsDown = new int [BUTTONSNUMBER]; //BUTTONx_DOWN_MASK + + //used to store mouse buttons sequences to press/to release + static int [] affectedButtonsToPressRelease; +// static int [] buttonsToRelease; +// static int [] modifiersToVerifyOnPressRelease; + + static Robot robot; + static CheckingAdapter adapterTest1; + static Frame f; + + static { + for (int i = 0; i < BUTTONSNUMBER; i++){ + mouseButtons[i] = InputEvent.getMaskForButton(i+1); //then change first three elements here to BUTTONx_MASK + mouseButtonsDown[i] = InputEvent.getMaskForButton(i+1); + } + //mouseButtons initially has following values : 16 8 4. +/* mouseButtons[0] = InputEvent.BUTTON1_MASK; + mouseButtons[1] = InputEvent.BUTTON2_MASK; + mouseButtons[2] = InputEvent.BUTTON3_MASK; + */ + } + + public static void main(String s[]){ + init(); + + try { + robot = new Robot(); + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException("Test failed.", e); + } + robot.delay(500); + robot.mouseMove(f.getLocationOnScreen().x + f.getWidth()/2, f.getLocationOnScreen().y + f.getHeight()/2); + robot.delay(500); + //Top limit is the factorial of the number of existing buttons + for (int k = 0; k < factorial(mouseButtons.length)-1; k++){ + //now we will press 2 up to maximum buttons and release them in different order and listen for + // PRESSED events and check it's ExModifiers + for (int buttonsToPressNumber = 2; buttonsToPressNumber <= BUTTONSNUMBER; buttonsToPressNumber++ ){ + System.out.println(">>>"); + + //Now get the slice of affected buttons + affectedButtonsToPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber); +// modifiersToVerifyOnPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber); + + //Now press all these buttons in the order as they are in array affectedButtonsToPressRelease + //And release all these buttons in back order. + + dumpArray("Affected Buttons ", affectedButtonsToPressRelease); + pressAllButtons(affectedButtonsToPressRelease); + releaseAllButtonsForwardOrder(affectedButtonsToPressRelease); +// nextPermutation(i, buttonsToRelease); + //TODO: press buttons and release them backward + //All I have to add is : +// pressAllButtons(affectedButtonsToPressRelease); +// releaseAllButtonsBackwardOrder(affectedButtonsToPressRelease); + + System.out.println("<<<"); + } + nextPermutation(k, mouseButtons); +// PermutationGenerator.nextPermutation(k, mouseButtonsDown); + dumpArray("mouseButtons (step="+k+")", mouseButtons); +// dumpArray("mouseButtonsDown (step="+k+")", mouseButtonsDown); + } + } + + private static void init(){ + adapterTest1 = new CheckingAdapter(); + f = new Frame("Robot presses mouse here"); + f.setSize(300, 300); + f.setVisible(true); + f.addMouseListener(adapterTest1); + } + public static int factorial(int t){ + if (t <=1 ) { + return 1; + } else { + return t*factorial(t-1); + } + } + + // use this variable to get current button on EDT in checkModifiers() + static volatile int currentButtonIndexUnderAction; + + public static void pressAllButtons(int []array){ + for (int i = 0; i =0) { + if (array[i] < array[i+1]){ + leftEl = i; + // System.out.println("leftEl = "+leftEl); + break; + } + i--; + } + + i = array.length - 1; + while (i>=0) { + if (array[i] > array[leftEl]) { + rightEl = i; + // System.out.println("rightEl = "+rightEl); + break; + } + i--; + } + swapElements(array, leftEl, rightEl); + if (leftEl + 2 < array.length){ + // System.out.println("sort"); + Arrays.sort(array, leftEl + 1 , array.length); + } + } + + public static void swapElements(int [] array, int leftEl, int rightEl){ + int tmp = array[leftEl]; + array[leftEl] = array[rightEl]; + array[rightEl] = tmp; + } + + public static void checkModifiersOnRelease(MouseEvent e){ + System.out.println("CheckModifiersOnRelease. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); + for (int i = currentButtonIndexUnderAction+1; i=0) { + if (buttonIndicesToPermutate[i] < buttonIndicesToPermutate[i+1]){ + leftEl = i; + // System.out.println("leftEl = "+leftEl); + break; + } + i--; + } + + i = array.length - 1; + while (i>=0) { + if (buttonIndicesToPermutate[i] >buttonIndicesToPermutate[leftEl]) { + rightEl = i; + // System.out.println("rightEl = "+rightEl); + break; + } + i--; + } + swapElements(array, leftEl, rightEl); + swapElements(buttonIndicesToPermutate, leftEl, rightEl); + + if (leftEl + 2 < array.length){ + // System.out.println("sort"); +//need to make our own sorting because arraysort makes this on actual values in array... + Arrays.sort(array, leftEl + 1 , array.length); + Arrays.sort(buttonIndicesToPermutate, leftEl + 1 , buttonIndicesToPermutate.length); +// sortArray(array, leftEl + 1 , array.length); + } + } + public static void swapElements(int [] array, int leftEl, int rightEl){ + int tmp = array[leftEl]; + array[leftEl] = array[rightEl]; + array[rightEl] = tmp; + } +} +*/ diff --git a/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java new file mode 100644 index 00000000000..f70b8dd691b --- /dev/null +++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java @@ -0,0 +1,490 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that modifiers are correct for extra buttons + @author Andrei Dmitriev : area=awt.mouse + @run main MouseModifiersUnitTest_Extra + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.Vector; + +// will process extra buttons only +// asking parameters from CMD: manual/automatic, modifier to test + +public class MouseModifiersUnitTest_Extra extends Frame { + static final int NONE = 0; + static final int SHIFT = 1; + static final int CTRL = 2; + static final int ALT = 3; + static CheckingModifierAdapter adapterTest1; + static CheckingModifierAdapter adapterTest2; + static CheckingModifierAdapter adapterTest3; + static CheckingModifierAdapter adapterTest4; + + static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception + static boolean autorun = false; //use robot or manual run + static int testModifier = NONE; + + static int [] mouseButtons; + static int [] mouseButtonDownMasks; + + //an arrays representing a modifiersEx of extra mouse buttons while using ALT/CTRL/SHIFT or none of them + static int [] modifiersExStandard; + static int [] modifiersExStandardSHIFT; + static int [] modifiersExStandardCTRL; + static int [] modifiersExStandardALT; + + // final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK}; + // BUTTON1, 2, 3 press-release. + final static int modifiersStandard = 0; //InputEvent.BUTTON_DOWN_MASK; + + public static void checkPressedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Pressed. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ +// System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers"); + MessageLogger.reportError("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnPress(testModifier, paramStringElements, button); + } + + public static void checkExtModifiersOnReleaseClick(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift"; + break; + } + case ALT:{ + ethalon = "Alt"; + break; + } + case CTRL:{ + ethalon = "Ctrl"; + break; + } + } + // + if (h.get("extModifiers") == null){ + h.put("extModifiers", ""); + } + if (!ethalon.equals(h.get("extModifiers"))) { + MessageLogger.reportError("Test failed : Released/Clicked. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + + public static void checkExtModifiersOnPress(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + } + ethalon = ethalon + "Button" +button; + + if (!h.get("extModifiers").equals(ethalon)) { + MessageLogger.reportError("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + + public static void checkModifiers(int testModifier, HashMap h, int button){ + // none of modifiers for extra button should be null + if (h.get("modifiers") != null) { + MessageLogger.reportError("Test failed : modifiers != null"); + } + } + + public static void checkButton(HashMap h, int button){ + if (h.get("button") == null) { + MessageLogger.reportError("Test failed : checkButton(). button is absent in paramString()"); + } + if (Integer.parseInt(h.get("button")) != button) { + MessageLogger.reportError("Test failed : checkButton. button in paramString() doesn't equal to button being pressed."); + } + } + public static HashMap tokenizeParamString(String param){ + HashMap params = new HashMap(); + StringTokenizer st = new StringTokenizer(param, ",="); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); +// System.out.println("PARSER : "+tmp); + if (tmp.equals("button") || + tmp.equals("modifiers") || + tmp.equals("extModifiers")) { + params.put(tmp, st.nextToken()); + } + } + return params; + } + + public static Vector tokenizeModifiers(String modifierList){ + Vector modifiers = new Vector(); + StringTokenizer st = new StringTokenizer(modifierList, "+"); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); + modifiers.addElement(tmp); + System.out.println("MODIFIER PARSER : "+tmp); + } + return modifiers; + } + + public static void checkReleasedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3 + 1; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Released. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ + MessageLogger.reportError("Test failed : Released. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + System.out.println("paramStringElements = "+paramStringElements); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + public static void checkClickedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3 + 2; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Clicked. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ + MessageLogger.reportError("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + private static int[] getStandardExArray(int testModifier) { + int [] curStandardExModifiers; + switch (testModifier){ + case SHIFT: + curStandardExModifiers = modifiersExStandardSHIFT; + break; + case CTRL: + curStandardExModifiers = modifiersExStandardCTRL; + break; + case ALT: + curStandardExModifiers = modifiersExStandardALT; + break; + default: //NONE by default + curStandardExModifiers = modifiersExStandard; + } + return curStandardExModifiers; + } + + static Robot robot; + public void init() { + this.setLayout(new BorderLayout()); + + String[] instructions = + { + "This test should be used with the mouse having more then three buttons.", + "Currently, " + MouseInfo.getNumberOfButtons() +" buttons are available.", + "If there are less then three buttons, press PASS.", + "1. Press each extra mouse button.", + "2. For each mouse event its modifiers and ExModifiers will be printed.", + "3. Verify that they are correct.", + "4. Press Pass or Fail accordingly." + }; +// Sysout.createDialogWithInstructions( instructions ); + +// addMouseListener(adapterTest1); + try { + robot = new Robot(); + } catch (Exception e) { + MessageLogger.reportError("Test failed. "+e); + } + }//End init() + + public void start() { + //Get things going. Request focus, set size, et cetera + setSize(200,200); + setVisible(true); + validate(); + if (autorun) { + testNONE(); + testSHIFT(); + testCTRL(); + testALT(); + } else { + switch (testModifier){ + case SHIFT: + this.addMouseListener(adapterTest2); + break; + case CTRL: + this.addMouseListener(adapterTest3); + break; + case ALT: + this.addMouseListener(adapterTest4); + break; + default: //NONE by default + this.addMouseListener(adapterTest1); + } + } + }// start() + + //000000000000000000000000000000000000000000000000000000000000000 + public void testNONE(){ + this.addMouseListener(adapterTest1); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + System.out.println("testNONE() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + } + robot.delay(1000); + this.removeMouseListener(adapterTest1); + } + + public void testSHIFT(){ + this.addMouseListener(adapterTest2); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_SHIFT); + System.out.println("testSHIFT() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_SHIFT); + } + robot.delay(1000); + this.removeMouseListener(adapterTest2); + } + + public void testCTRL(){ + this.addMouseListener(adapterTest3); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_CONTROL); + System.out.println("testCTRL() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + robot.delay(1000); + this.removeMouseListener(adapterTest3); + } + + public void testALT(){ + this.addMouseListener(adapterTest4); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_ALT); + System.out.println("testALT() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_ALT); + } + robot.delay(1000); + this.removeMouseListener(adapterTest4); + } + + //************************************************************************************************** + public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){ + System.out.println("Button = "+button + "Modifiers = "+ modifiers + "standard = "+ modifiersStandard); + System.out.println("Button = "+button + "ModifiersEx = "+ modifiersEx + "standardEx = "+ modifiersExStandard); + } + + public static void initParams(String []s){ + if (s.length != 3){ + autorun = true; + debug = false; + testModifier = NONE; + } else { + autorun = Boolean.valueOf(s[0]); + debug = Boolean.valueOf(s[1]); + + if (s[2].equals("NONE")){ + testModifier = NONE; + } + if (s[2].equals("SHIFT")){ + testModifier = SHIFT; + } + if (s[2].equals("CTRL")){ + testModifier = CTRL; + } + if (s[2].equals("ALT")){ + testModifier = ALT; + } + } + MessageLogger.setDebug(debug); + System.out.println("Autorun : " +autorun); + System.out.println("Debug mode : " +debug); + System.out.println("Modifier to verify : " + testModifier); + } + + public static void initAdapters(){ + adapterTest1 = new CheckingModifierAdapter(NONE); + adapterTest2 = new CheckingModifierAdapter(SHIFT); + adapterTest3 = new CheckingModifierAdapter(CTRL); + adapterTest4 = new CheckingModifierAdapter(ALT); + } + + public static void initVars(){ + int [] tmp = new int [MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + tmp[i] = InputEvent.getMaskForButton(i+1); + // System.out.println("TEST: "+tmp[i]); + } + + mouseButtons = Arrays.copyOf(tmp, tmp.length); + + for (int i = 0; i < mouseButtons.length; i++){ + System.out.println("MouseArray [i] == "+mouseButtons[i]); + } + + mouseButtonDownMasks = Arrays.copyOf(tmp, tmp.length); + + // So we need to get the number of extra buttons on the mouse: "MouseInfo.getNumberOfButtons() - 3" + // and multyply on 3 because each button will generate three events : PRESS, RELEASE and CLICK. + tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3]; + Arrays.fill(tmp, 0); + + for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){ + tmp[i] = mouseButtonDownMasks[j]; + } + modifiersExStandard = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.SHIFT_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardSHIFT = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.CTRL_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardCTRL = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.ALT_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardALT = Arrays.copyOf(tmp, tmp.length); + } + + public static void main(String []s){ + if (MouseInfo.getNumberOfButtons() < 4){ + System.out.println("There are less then 4 buttons on the mouse. The test may not be accomplished. Skipping."); + return; + } + initVars(); + MouseModifiersUnitTest_Extra frame = new MouseModifiersUnitTest_Extra(); + frame.initParams(s); + frame.init(); + initAdapters(); + frame.start(); + } + +}// class + +/* A class that invoke appropriate verification + * routine with current modifier. + */ +class CheckingModifierAdapter extends MouseAdapter{ + int modifier; + public CheckingModifierAdapter(int modifier){ + this.modifier = modifier; + } + + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkPressedModifiersTest(modifier, e); + } + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkReleasedModifiersTest(modifier, e); + } + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkClickedModifiersTest(modifier, e); + } + } +} +//Utility class that could report a message depending on current purpose of the test run +class MessageLogger{ + private static boolean debug; + + public static void setDebug(boolean d){ + debug = d; + log("Switch to "+ ((debug)?"debug":"trial") +" mode"); + } + + public static void log(String message){ + System.out.println(message); + } + + public static void reportError(String message){ + if (debug){ + System.out.println(message); + } else { + throw new RuntimeException(message); + } + } +} diff --git a/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java new file mode 100644 index 00000000000..cd2dab03039 --- /dev/null +++ b/jdk/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java @@ -0,0 +1,598 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that modifiers are correct for standard (1, 2, 3, wheel) mouse buttons + @author Andrei Dmitriev : area=awt.mouse + @run main MouseModifiersUnitTest_Standard + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.Vector; + +//the test verifies: +// 1) verifies that modifiers are correct for standard (1, 2, 3) mouse buttons +// TODO: 2) verifies that modifiers are correct for wheel +// TODO: 3) +// Case1. the test posts BUTTONx_MASK and verifies that paramString() contains correct modifiers and exModifiers +// Case2. the test posts BUTTONx_DOWN_MASK and verifies that paramString() contains correct modifiers and exModifiers +// Case3. the test posts getMaskForButton(n) and verifies that paramString() contains correct modifiers and exModifiers +// repeat all cases with SHIFT/ALT/CTRL modifiers verify that paramString() contains correct modifiers and exModifiers +// I'm verifying button, modifiers and extModifiers for now. + +public class MouseModifiersUnitTest_Standard { + static final int NONE = 0; + static final int SHIFT = 1; + static final int CTRL = 2; + static final int ALT = 3; + static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception + static boolean autorun = false; //use robot or manual run + static int testModifier = NONE; + // static String testModifier = "NONE"; + static CheckingModifierAdapter adapterTest1; + static CheckingModifierAdapter adapterTest2; + static CheckingModifierAdapter adapterTest3; + static CheckingModifierAdapter adapterTest4; + static Frame f; + final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK}; + // BUTTON1, 2, 3 press-release. + final static int [] modifiersStandardTestNONE = new int[] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON1_MASK, + MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON2_MASK, + MouseEvent.BUTTON3_MASK, MouseEvent.BUTTON3_MASK, MouseEvent.BUTTON3_MASK }; + final static int [] modifiersExStandardTestNONE = new int[] {MouseEvent.BUTTON1_DOWN_MASK, 0, 0, + MouseEvent.BUTTON2_DOWN_MASK, 0, 0, + MouseEvent.BUTTON3_DOWN_MASK, 0, 0}; + // BUTTON1, 2, 3 press-release with shift modifier + final static int [] modifiersStandardTestSHIFT = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK }; + final static int [] modifiersExStandardTestSHIFT = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK}; + // BUTTON1, 2, 3 press-release with CTRL modifier + final static int [] modifiersStandardTestCTRL = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK }; + final static int [] modifiersExStandardTestCTRL = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK}; + + // BUTTON1, 2, 3 press-release with ALT modifier + final static int [] modifiersStandardTestALT = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK }; + final static int [] modifiersExStandardTestALT = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK}; + + static Robot robot; + + public static void main(String s[]){ + initParams(s); + initAdapters(); + f = new Frame(); + final int [] modifiers = {InputEvent.SHIFT_MASK, InputEvent.CTRL_MASK}; + final String [] modifierNames = {"InputEvent.SHIFT_MASK", "InputEvent.CTRL_MASK"}; + f.setLayout(new FlowLayout()); + f.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + System.out.println("WHEEL "+e); + } + }); + f.setSize(300, 300); + f.setVisible(true); + + try { + robot = new Robot(); + robot.delay(500); + robot.mouseMove(f.getLocationOnScreen().x + f.getWidth()/2, f.getLocationOnScreen().y + f.getHeight()/2); + if (autorun) { + //testing buttons 1, 2, 3 only + testPlainButtons(); + robot.delay(500); + + //testing buttons 1, 2, 3 with SHIFT, CTRL, ALT keyboard modifiers + testButtonsWithShift(); + robot.delay(500); + + testButtonsWithControl(); + robot.delay(500); + + testButtonsWithAlt(); + robot.delay(500); + } else { + switch (testModifier){ + case SHIFT: + f.addMouseListener(adapterTest2); + break; + case CTRL: + f.addMouseListener(adapterTest3); + break; + case ALT: + f.addMouseListener(adapterTest4); + break; + default: //NONE inclusive + f.addMouseListener(adapterTest1); + } + } + } catch (Exception e){ + throw new RuntimeException("Test failed."); + } + + } + + public static void initAdapters(){ + adapterTest1 = new CheckingModifierAdapter(NONE); + adapterTest2 = new CheckingModifierAdapter(SHIFT); + adapterTest3 = new CheckingModifierAdapter(CTRL); + adapterTest4 = new CheckingModifierAdapter(ALT); + } + + /*======================================================================*/ + public static void checkPressedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3; + // int index = (button - 4)*3; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Pressed. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Pressed. modifiers != modifiersStandard"); + } + } + + if (modifiersEx != curStandardExModifiers[index]){ +// System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers"); + if (debug){ + System.out.println("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } + } + HashMap paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnPress(testModifier, paramStringElements, button); + } + + public static void checkButton(HashMap h, int button){ + if (h.get("button") == null) { + throw new RuntimeException("Test failed : Clicked. button is absent in paramString()"); + } + if (Integer.parseInt(h.get("button")) != button) { + throw new RuntimeException("Test failed : Clicked. button in paramString() doesn't equal to button being pressed."); + } + } + + public static void checkExtModifiersOnPress(int testModifier, HashMap h, int button){ + String ethalon = ""; + if (h.get("extModifiers") == null) { + System.out.println("Test failed : Pressed. extModifiers == null"); + throw new RuntimeException("Test failed : Pressed. extModifiers == null"); + } + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + default: { + ethalon = ""; + } + ethalon = ethalon + "Button" +button; + + if (!h.get("extModifiers").equals(ethalon)) { + System.out.println("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + throw new RuntimeException("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + } + + + + public static void checkModifiers(int testModifier, HashMap h, int button){ + // none of modifiers should be null + if (h.get("modifiers") == null) { + System.out.println("Test failed : modifiers == null"); + throw new RuntimeException("Test failed : modifiers == null"); + } + Vector modifierElements = tokenizeModifiers(h.get("modifiers")); + //check that ButtonX is there + String buttonEthalon = "Button" + button; + if (modifierElements.contains(buttonEthalon)){ + modifierElements.remove(buttonEthalon); + } else { + System.out.println("Test failed : modifiers doesn't contain Button "+h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain Button "+h.get("modifiers")); + } + + + //Check all explicitly pressed modifires +// boolean altIncluded = false; //don't duplicate Alt when ALT is pressed and BUTTON2_MASK. + String excplicitModifier = ""; + boolean altIncluded = false; + switch (testModifier){ + case SHIFT:{ + excplicitModifier = "Shift"; + break; + } + case ALT:{ + excplicitModifier = "Alt"; + altIncluded = true; //there should be only on "Alt" for two modifiers. So check it. + break; + } + case CTRL:{ + excplicitModifier = "Ctrl"; + break; + } + } + if (!excplicitModifier.equals("")){ + if (modifierElements.contains(excplicitModifier)){ + modifierElements.remove(excplicitModifier); + } else { + System.out.println("Test failed : modifiers doesn't contain explicit modifier "+excplicitModifier + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain explicit modifier "+excplicitModifier + " in "+ h.get("modifiers")); + } + } + + //Button 2 and 3 reports about Alt+Button2 and Meta+Button3 respectively. + //Check these values too + String extraModifiers = ""; + String extraModifiersButton3 = ""; + switch (button){ + //BUTTON1 with ALT reports about Alt+Button1+Button2. + //We should fix this but I would not change this. + case 1: { + //Alt+Button1+Button2: + // 1) we already handled "Alt" in excplicitModifier + // 2) we already took "Button1" in buttonEthalon + // 3) so "Button2" is only remained. + // This should only happen when ALT+Button1 is pressed + if (altIncluded){ + extraModifiers = "Button2"; + } + break; + } + case 2: { + //Alt+Button2 report about "Alt+Button2". + extraModifiers = "Alt"; + break; + } + case 3: { + //ALT+BUTTON3 reports about "Alt+Meta+Button2+Button3" + // This should only happen when ALT+Button3 is pressed + extraModifiers = "Meta"; + if (altIncluded){ + extraModifiersButton3 = "Button2"; + } + break; + } + }//switch + + if (!extraModifiers.equals("")){ + if (modifierElements.contains(extraModifiers)){ + modifierElements.remove(extraModifiers); + } else { + //we may already removed "Alt" when filtered explicit modifiers. + //Here is no failure in this case. + if (!altIncluded) { + System.out.println("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiers + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiers + " in "+ h.get("modifiers")); + } + } + } + + if (!extraModifiersButton3.equals("")){ + if (modifierElements.contains(extraModifiersButton3)){ + modifierElements.remove(extraModifiersButton3); + } else { + System.out.println("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiersButton3 + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiersButton3 + " in "+ h.get("modifiers")); + } + } + + //the length of vector should now be zero + if (!modifierElements.isEmpty()){ + System.out.println("Test failed : there is some more elements in modifiers that shouldn't be there: "+h.get("modifiers")); + throw new RuntimeException("Test failed : there is some more elements in modifiers that shouldn't be there: "+h.get("modifiers")); + } + } + + public static void checkExtModifiersOnReleaseClick(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + default: { + if (h.get("extModifiers") != null) { + System.out.println("Test failed : Released. extModifiers != null but no modifiers keys are pressed"); + throw new RuntimeException("Test failed : Released. extModifiers != null but no modifiers keys are pressed"); + } else { + //no modifiers + return; + } + } + } + if (h.get("extModifiers").equals(ethalon)) { + System.out.println("Test failed : Released. extModifiers = "+ h.get("extModifiers") +" instead of : "+ethalon); + throw new RuntimeException("Test failed : Released. extModifiers = "+ h.get("extModifiers") +" instead of : "+ethalon); + } + } + + public static void checkReleasedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + // int index = (button - 4)*3 + 1; + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3 + 1; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Released. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Released. modifiers != modifiersStandard"); + } + } + if (modifiersEx != curStandardExModifiers[index]){ + if (debug){ + System.out.println("Test failed : Released. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Released. modifiersEx != curStandardExModifiers"); + } + } + HashMap paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + public static void checkClickedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + // int index = (button - 4)*3 + 2; + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3 + 2; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Clicked. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Clicked. modifiers != modifiersStandard"); + } + } + if (modifiersEx != curStandardExModifiers[index]){ + if (debug){ + System.out.println("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } + } + HashMap paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + /*======================================================================*/ + + public static HashMap tokenizeParamString(String param){ + HashMap params = new HashMap(); + StringTokenizer st = new StringTokenizer(param, ",="); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); +// System.out.println("PARSER : "+tmp); + if (tmp.equals("button") || + tmp.equals("modifiers") || + tmp.equals("extModifiers")) { + params.put(tmp, st.nextToken()); + } + } + return params; + } + + public static Vector tokenizeModifiers(String modifierList){ + Vector modifiers = new Vector(); + StringTokenizer st = new StringTokenizer(modifierList, "+"); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); + modifiers.addElement(tmp); + System.out.println("MODIFIER PARSER : "+tmp); + } + return modifiers; + } + + + //test BUTTON1, 2 and 3 without any modifiers keys + public static void testPlainButtons(){ + System.out.println("Testing buttons without modifiers."); + f.addMouseListener(adapterTest1); + for (int button : mouseButtons){ + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + } + robot.delay(1000); + f.removeMouseListener(adapterTest1); + } + + //test BUTTON1, 2 and 3 with SHIFT key + public static void testButtonsWithShift(){ + System.out.println("Testing buttons with SHIFT modifier."); + f.addMouseListener(adapterTest2); + + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_SHIFT); + } + robot.delay(1000); + f.removeMouseListener(adapterTest2); + } + + //test BUTTON1, 2 and 3 with CTRL key + public static void testButtonsWithControl(){ + System.out.println("Testing buttons with CONTROL modifier."); + f.addMouseListener(adapterTest3); + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + robot.delay(1000); + f.removeMouseListener(adapterTest3); + } + + //test BUTTON1, 2 and 3 with ALT key + public static void testButtonsWithAlt(){ + System.out.println("Testing buttons with ALT modifier."); + f.addMouseListener(adapterTest4); + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_ALT); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_ALT); + } + robot.delay(1000); + f.removeMouseListener(adapterTest4); + } + + public static void initParams(String []s){ + if (s.length != 3){ + autorun = true; + debug = false; + testModifier = NONE; + } else { + autorun = Boolean.valueOf(s[0]); + debug = Boolean.valueOf(s[1]); + + if (s[2].equals("NONE")){ + testModifier = NONE; + } + if (s[2].equals("SHIFT")){ + testModifier = SHIFT; + } + if (s[2].equals("CTRL")){ + testModifier = CTRL; + } + if (s[2].equals("ALT")){ + testModifier = ALT; + } + } + System.out.println("Autorun : " +autorun); + System.out.println("Debug mode : " +debug); + System.out.println("Modifier to verify : " + testModifier); + } + + public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){ + System.out.println("Button = "+button + "Modifiers = "+ modifiers + " standard = "+ modifiersStandard); + System.out.println(" ModifiersEx = "+ modifiersEx + " standardEx = "+ modifiersExStandard); + } + + private static int[] getStandardExArray(int testModifier) { + int [] curStandardExModifiers; + switch (testModifier){ + case SHIFT: + curStandardExModifiers = modifiersExStandardTestSHIFT; + break; + case CTRL: + curStandardExModifiers = modifiersExStandardTestCTRL; + break; + case ALT: + curStandardExModifiers = modifiersExStandardTestALT; + break; + default: //NONE by default + curStandardExModifiers = modifiersExStandardTestNONE; + } + return curStandardExModifiers; + } + + private static int[] getStandardArray(int testModifier) { + int [] curStandardModifiers; + switch (testModifier){ + case SHIFT: + curStandardModifiers = modifiersStandardTestSHIFT; + break; + case CTRL: + curStandardModifiers = modifiersStandardTestCTRL; + break; + case ALT: + curStandardModifiers = modifiersStandardTestALT; + break; + default: //NONE by default + curStandardModifiers = modifiersStandardTestNONE; + } + return curStandardModifiers; + } + +} + + +/* A class that invoke appropriate verification + * routine with current modifier. + */ +class CheckingModifierAdapter extends MouseAdapter{ + int modifier; + public CheckingModifierAdapter(int modifier){ + this.modifier = modifier; + } + + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkPressedModifiersTest(modifier, e); // e.getButton(), e.getModifiers(), e.getModifiersEx(), + } + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkReleasedModifiersTest(modifier, e); // e.getButton(), e.getModifiers(), e.getModifiersEx() + } + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkClickedModifiersTest(modifier, e); //e.getButton(), e.getModifiers(), e.getModifiersEx() + } + } +} + diff --git a/jdk/test/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java b/jdk/test/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java new file mode 100644 index 00000000000..91b13cc131a --- /dev/null +++ b/jdk/test/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java @@ -0,0 +1,118 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that Robot is accepting extra mouse buttons + @author Andrei Dmitriev : area=awt.mouse + @library ../../regtesthelpers + @build Util + @run main AcceptExtraMouseButtons + */ + +//if we do robot.mousePress(InputEvent.BUTTON1_DOWN_MASK) the test must +// 1) accept it (i.e. don't throw an IllegalArgumentException +// 2) actually post a MouseEvent +// Also, Robot should still accept InputEvent.BUTTONx_MASKs + +import java.awt.*; +import java.awt.event.*; +import sun.awt.SunToolkit; +import test.java.awt.regtesthelpers.Util; + +public class AcceptExtraMouseButtons extends Frame { + static String tk = Toolkit.getDefaultToolkit().getClass().getName(); + static Robot robot; + static int [] standardButtonMasks = {InputEvent.BUTTON1_MASK, + InputEvent.BUTTON2_MASK, + InputEvent.BUTTON3_MASK}; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + static int buttonsNum = MouseInfo.getNumberOfButtons(); + + public static void main(String []s){ + + //MouseInfo.getNumberOfButtons() reports two more buttons on XToolkit + //as they reserved for wheel (both directions). + if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + buttonsNum = buttonsNum - 2; + } + System.out.println("Number Of Buttons = "+ buttonsNum); + if (buttonsNum < 3) { + System.out.println("Linux and Windows systems should emulate three buttons if even there are only 1 or 2 are phsically available. Setting number of buttons to 3."); + buttonsNum = 3; + } + + buttonsPressed = new int [buttonsNum]; + buttonsReleased = new int [buttonsNum]; + buttonsClicked = new int [buttonsNum]; + + AcceptExtraMouseButtons frame = new AcceptExtraMouseButtons(); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + frame.addMouseListener(ma1); + + frame.setSize(300, 300); + frame.setVisible(true); + + Util.waitForIdle(robot); //a time to show a Frame + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, + frame.getLocationOnScreen().y + frame.getHeight()/2); + + //TestCase 1: verify that all BUTTONx_DOWN_MASKs are accepted by the Robot. + + for (int i = 0; i < buttonsNum; i++){ + int buttonMask = InputEvent.getMaskForButton(i+1); + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMask); + robot.mousePress(buttonMask); + robot.delay(30); + robot.mouseRelease(buttonMask); + Util.waitForIdle(robot); + } + for (int i = 0; i < buttonsNum; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 1 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + + java.util.Arrays.fill(buttonsPressed, 0); + java.util.Arrays.fill(buttonsReleased, 0); + java.util.Arrays.fill(buttonsClicked, 0); + //TestCase 2: verify that all BUTTONx_MASKs are accepted by the Robot. + for (int i = 0; i < standardButtonMasks.length; i++){ + int buttonMask = standardButtonMasks[i]; + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMask); + robot.mousePress(buttonMask); + robot.delay(30); + robot.mouseRelease(buttonMask); + Util.waitForIdle(robot); + } + for (int i = 0; i < standardButtonMasks.length; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } +} diff --git a/jdk/test/java/awt/Robot/ManualInstructions/ManualInstructions.java b/jdk/test/java/awt/Robot/ManualInstructions/ManualInstructions.java new file mode 100644 index 00000000000..96baf9b913c --- /dev/null +++ b/jdk/test/java/awt/Robot/ManualInstructions/ManualInstructions.java @@ -0,0 +1,305 @@ +/* + test %W% %E% %I%, %G% + @bug 6315717 + @summary manual control over the Robot + @author Andrei Dmitriev : area=awt.robot + @run applet/manual=yesno ManualInstructions.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.util.Timer; +import java.util.TimerTask; + +public class ManualInstructions extends Applet +{ + final static long SEND_DELAY = 1000; + + public static void main(String s[]){ + ManualInstructions mi = new ManualInstructions(); + mi.init(); + mi.start(); + } + + static Robot robot; + Point mouseLocation; //where mouse should be pressed each time + Panel target = new Panel(); + Button pressOn = new Button("press on ..."); + Button releaseOn = new Button("release on ..."); + Button clickOn = new Button("click on ..."); + Choice buttonNumber = new Choice(); + + public void init() + { + try { + robot = new Robot(); + } catch (AWTException ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + this.setLayout (new BorderLayout ()); + + target.setBackground(Color.green); + target.setName("GreenBox");//for the ease of debug + target.setPreferredSize(new Dimension(100, 100)); + String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); + + // on X systems two buttons are reserved for wheel though they are countable by MouseInfo. + int buttonsNumber = toolkit.equals("sun.awt.windows.WToolkit")?MouseInfo.getNumberOfButtons():MouseInfo.getNumberOfButtons()-2; + + for (int i = 0; i < 8; i++){ + buttonNumber.add("BUTTON"+(i+1)+"_MASK"); + } + + pressOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now pressing : " + (buttonNumber.getSelectedIndex()+1)); + + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + }); + + releaseOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now releasing : " + (buttonNumber.getSelectedIndex()+1)); + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + }); + + clickOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now clicking : " + (buttonNumber.getSelectedIndex()+1)); + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); + robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + + }); + target.addMouseListener(new MouseAdapter(){ + public void mousePressed(MouseEvent e){ + Sysout.println(""+e); + } + public void mouseReleased(MouseEvent e){ + Sysout.println(""+e); + } + public void mouseClicked(MouseEvent e){ + Sysout.println(""+e); + } + }); + + String[] instructions = + { + "Do provide an instruction to the robot by", + "choosing the button number to act and ", + "pressing appropriate java.awt.Button on the left.", + "Inspect an output in the TextArea below.", + "Please don't generate non-natural sequences like Release-Release, etc.", + "If you use keyboard be sure that you released the keyboard shortly.", + "If events are generated well press Pass, otherwise Fail." + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + private int getMask(int button){ + return InputEvent.getMaskForButton(button); + + /* + //this only works for standard buttons and for old JDK builds + int mask = 0; + switch (button){ + case 1: { + mask = InputEvent.BUTTON1_MASK; + break; + } + case 2: { + mask = InputEvent.BUTTON2_MASK; + break; + } + case 3: { + mask = InputEvent.BUTTON3_MASK; + break; + } + } + return mask; + */ + } + + private Point updateTargetLocation() { + return new Point(target.getLocationOnScreen().x + target.getWidth()/2, target.getLocationOnScreen().y + target.getHeight()/2); + } + + public void start () + { + //Get things going. Request focus, set size, et cetera + setSize (200,200); + setVisible(true); + validate(); + Frame f = new Frame ("Set action for Robot here."); + f.setLayout(new FlowLayout()); + f.add(buttonNumber); + f.add(pressOn); + f.add(releaseOn); + f.add(clickOn); + f.add(target); + f.pack(); + f.setVisible(true); + }// start() +}// class + +/* Place other classes related to the test after this line */ + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 120; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + }// while + }// for + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class diff --git a/jdk/test/java/awt/Robot/RobotExtraButton/RobotExtraButton.java b/jdk/test/java/awt/Robot/RobotExtraButton/RobotExtraButton.java new file mode 100644 index 00000000000..83e9571239d --- /dev/null +++ b/jdk/test/java/awt/Robot/RobotExtraButton/RobotExtraButton.java @@ -0,0 +1,79 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that robot could accept extra buttons + @author Andrei Dmitriev : area=awt.mouse + @library ../../regtesthelpers + @build Util + @run main RobotExtraButton + */ + +import java.awt.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Util; + +public class RobotExtraButton extends Frame { + static Robot robot; + public static void main(String []s){ + RobotExtraButton frame = new RobotExtraButton(); + frame.setSize(300, 300); + frame.setVisible(true); + frame.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + } + }); + Util.waitForIdle(robot); + int [] buttonMask = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMask[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMask[i]); + } + + try { + robot = new Robot(); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + /* + if (MouseInfo.getNumberOfButtons() <= 3) { + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons() +". Finish!"); + return; + }*/ + + System.out.println("TEST: press 1"); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + System.out.println("TEST: press 2"); + + robot.mousePress(InputEvent.BUTTON2_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON2_MASK); + Util.waitForIdle(robot); + System.out.println("TEST: press 3"); + + robot.mousePress(InputEvent.BUTTON3_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_MASK); + Util.waitForIdle(robot); + System.out.println("--------------------------------------------------"); + for (int i = 0; i < buttonMask.length; i++){ + System.out.println("button would = " +i + " : value = " +buttonMask[i]); + robot.mousePress(buttonMask[i]); + robot.delay(50); + robot.mouseRelease(buttonMask[i]); + Util.waitForIdle(robot); + } + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException("Test failed.", e); + } + } +} diff --git a/jdk/test/java/awt/Toolkit/Headless/AWTEventListener/AWTListener.java b/jdk/test/java/awt/Toolkit/Headless/AWTEventListener/AWTListener.java new file mode 100644 index 00000000000..44098dd3e48 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/Headless/AWTEventListener/AWTListener.java @@ -0,0 +1,48 @@ +/* + @test + @bug 6738181 + @library ../../../regtesthelpers + @build Sysout + @summary Toolkit.getAWTEventListeners returns empty array + @author andrei dmitriev: area=awt.headless + @run main/othervm -Djava.awt.headless=true AWTListener +*/ + +/** + * In a headless mode add a listener for container events. + * Check if a single listener is still assigned to the Toolkit class. + */ + +import java.awt.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Sysout; + +public class AWTListener { + public static void main(String []s) { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + + AWTEventListener orig = new AWTEventListener() { + public void eventDispatched(AWTEvent event) { } + }; + + Sysout.println("Test: listener to add = " +orig); + toolkit.addAWTEventListener(orig, AWTEvent.CONTAINER_EVENT_MASK); + + for (AWTEventListener l: toolkit.getAWTEventListeners()){ + Sysout.println("Test: listener = " +l+" "); + } + + if ( toolkit.getAWTEventListeners().length == 0 ) { + throw new RuntimeException("Case 1. An empty array returned unexpectedly"); + } + + for (AWTEventListener l: toolkit.getAWTEventListeners(AWTEvent.CONTAINER_EVENT_MASK)){ + Sysout.println("Test: listener = " +l); + } + + if ( toolkit.getAWTEventListeners(AWTEvent.CONTAINER_EVENT_MASK).length == 0 ) { + throw new RuntimeException("Case 2. An empty array returned unexpectedly"); + } + Sysout.println("Test PASSED"); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_1.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_1.java new file mode 100644 index 00000000000..3fdd3bce310 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_1.java @@ -0,0 +1,36 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons is true by default + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_1 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false initially. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true by default. +// This must initlizes the Toolkit class. +//3) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true (default). +import java.awt.*; + +public class SystemPropTest_1 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("1. System.getProperty = " + propValue); + if (propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + + System.getProperties().list(System.out); + System.out.println("XXXX. System.getProperty = " + System.getProperty("sun.awt.enableExtraMouseButtons")); + + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("2. System.getProperty = " + propValue); + if (!propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_2.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_2.java new file mode 100644 index 00000000000..366dbdf5cf6 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_2.java @@ -0,0 +1,25 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to true by the command line + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=true SystemPropTest_2 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true if set through the command line. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true if the proprty is set through the command line. +import java.awt.*; + +public class SystemPropTest_2 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("System.getProperty = " + propValue); + if (!propValue){ + throw new RuntimeException("TEST FAILED : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_3.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_3.java new file mode 100644 index 00000000000..e634af90127 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_3.java @@ -0,0 +1,26 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to false by the command line + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false SystemPropTest_3 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false if set through the command line. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false if the proprty is set through the command line. +import java.awt.*; + +public class SystemPropTest_3 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("Test System.getProperty = " + System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("System.getProperty = " + propValue); + if (propValue){ + throw new RuntimeException("TEST FAILED : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_4.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_4.java new file mode 100644 index 00000000000..85a80b741a3 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_4.java @@ -0,0 +1,42 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to true by the System class API. + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_4 + */ +//1) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "true") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true. +//2) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "false") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true still. + +import java.awt.*; + +public class SystemPropTest_4 { + public static void main(String []s){ + System.out.println("STAGE 1"); + System.setProperty("sun.awt.enableExtraMouseButtons", "true"); + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (!propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(1) : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + + System.out.println("STAGE 2"); + System.setProperty("sun.awt.enableExtraMouseButtons", "false"); + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(2) : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_5.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_5.java new file mode 100644 index 00000000000..6dc2203d023 --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_5.java @@ -0,0 +1,42 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to false by the System class API. + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_5 + */ +//1) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "false") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false. +//2) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "true") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false still. + +import java.awt.*; + +public class SystemPropTest_5 { + public static void main(String []s){ + System.out.println("STAGE 1"); + System.setProperty("sun.awt.enableExtraMouseButtons", "false"); + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(1) : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + + System.out.println("STAGE 2"); + System.setProperty("sun.awt.enableExtraMouseButtons", "true"); + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (!propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(2) : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Disable.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Disable.java new file mode 100644 index 00000000000..023bbb2f3db --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Disable.java @@ -0,0 +1,143 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that sun.awt.enableExtraMouseButtons = false consumes extra events + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false ToolkitPropertyTest_Disable + */ + +import java.awt.*; +import java.awt.event.*; + +// Testcase 1: set to FALSE and check +// Testcase 2: set to FALSE and check that extra events are not coming +// check that standard events are coming + +public class ToolkitPropertyTest_Disable extends Frame { + static boolean propValue; + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + static boolean lessThenFourButtons; + + public static void main(String []s){ + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + buttonsPressed = new int [MouseInfo.getNumberOfButtons()]; + buttonsReleased = new int [MouseInfo.getNumberOfButtons()]; + buttonsClicked = new int [MouseInfo.getNumberOfButtons()]; + + ToolkitPropertyTest_Disable frame = new ToolkitPropertyTest_Disable(); + frame.setSize(300, 300); + frame.setVisible(true); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("Property = " + propValue); + testCase0(); + + testCase1(); + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + + lessThenFourButtons = (MouseInfo.getNumberOfButtons() <= 3); + if ( !lessThenFourButtons ) { + frame.addMouseListener(ma1); + testCase2(); + } + } catch (Exception e){ + e.printStackTrace(); +// throw new RuntimeException(e); + } finally { +// frame.removeMouseListener(ma1); + } + } + + public static void testCase0(){ + if (propValue){ + throw new RuntimeException("TEST FAILED (0): System property sun.awt.enableExtraMouseButtons = " + propValue); + } + } + + public static void testCase1(){ + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() == true){ + throw new RuntimeException("TEST FAILED (1): setting to FALSE. Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() = " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()); + } + } + + public static void testCase2(){ + emptyArrays(); + int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasks[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMasks[i]); + } + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMasks[i]); + try { + robot.mousePress(buttonMasks[i]); + robot.delay(70); + robot.mouseRelease(buttonMasks[i]); + robot.delay(200); + //no exception is thrown + if (i >= 3) { + throw new RuntimeException("TESTCASE 2 FAILED : robot accepted the extra button " + (i+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (i >= 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("TESTCASE 2 FAILED : exception happen on standard button.", e); + } + } + } + robot.delay(2000); + if (MouseInfo.getNumberOfButtons() < 3) { + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed."); + } + } + } else { + for (int i = 0; i < 3; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed."); + } + } + + for (int i = 3; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 0 || buttonsReleased[i] != 0 || buttonsClicked[i] != 0 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " was pressed."); + } + } + } + } + + public static void emptyArrays(){ + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonsPressed[i] = 0; + buttonsReleased[i] = 0; + buttonsClicked[i] = 0; + } + } + +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java new file mode 100644 index 00000000000..fa6a41771aa --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java @@ -0,0 +1,120 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that sun.awt.enableExtraMouseButtons is working + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=true ToolkitPropertyTest_Enable + */ + +import java.awt.*; +import java.awt.event.*; + +// Testcase 1: set to TRUE (via jtreg option) +// Testcase 2: set to TRUE and check that extra events are coming +// check that standard events are coming + +public class ToolkitPropertyTest_Enable extends Frame { + static boolean propValue; + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + public static void main(String []s){ + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + buttonsPressed = new int [MouseInfo.getNumberOfButtons()]; + buttonsReleased = new int [MouseInfo.getNumberOfButtons()]; + buttonsClicked = new int [MouseInfo.getNumberOfButtons()]; + + ToolkitPropertyTest_Enable frame = new ToolkitPropertyTest_Enable(); + frame.setSize(300, 300); + frame.setVisible(true); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + // frame.addMouseListener(ma1); + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("Property = " + propValue); + testCase0(); + + testCase1(); + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + + boolean lessThenFourButtons = (MouseInfo.getNumberOfButtons() <= 3); + if ( !lessThenFourButtons ) { + frame.addMouseListener(ma1); + testCase2(); + // testCase3(); + // testCase4(); + frame.removeMouseListener(ma1); + } + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException(e); + } + + } + + public static void testCase0(){ + if (!propValue){ + throw new RuntimeException("TEST FAILED (0) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + } + + public static void testCase1(){ + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() == false){ + throw new RuntimeException("TEST FAILED (1) : setting to TRUE. enabled = " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()); + } + } + + public static void testCase2(){ + emptyArrays(); + //we can't post a message from an unexistent button + int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasks[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMasks[i]); + } + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMasks[i]); + robot.mousePress(buttonMasks[i]); + robot.delay(70); + robot.mouseRelease(buttonMasks[i]); + robot.delay(200); + } + robot.delay(1000); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + } + + public static void emptyArrays(){ + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonsPressed[i] = 0; + buttonsReleased[i] = 0; + buttonsClicked[i] = 0; + } + } + +} diff --git a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java new file mode 100644 index 00000000000..44f43c1b3bf --- /dev/null +++ b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java @@ -0,0 +1,104 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test + @bug 6758673 + @summary Tests that windows are removed from owner's child windows list + @author art: area=awt.toplevel + @run main OwnedWindowsLeak +*/ + +import java.awt.*; +import java.awt.event.*; + +import java.lang.ref.*; +import java.lang.reflect.*; + +import java.util.*; + +public class OwnedWindowsLeak +{ + public static void main(String[] args) + { + Frame owner = new Frame("F"); + + // First, create many windows + Vector> children = + new Vector>(); + for (int i = 0; i < 1000; i++) + { + Window child = new Window(owner); + children.add(new WeakReference(child)); + } + + // Second, make sure all the memory is allocated + Vector garbage = new Vector(); + while (true) + { + try + { + garbage.add(new byte[1000]); + } + catch (OutOfMemoryError e) + { + break; + } + } + + // Third, make sure all the weak references are null + for (WeakReference ref : children) + { + if (ref.get() != null) + { + throw new RuntimeException("Test FAILED: some of child windows are not GCed"); + } + } + + // Fourth, make sure owner's children list contains no elements + try + { + Field f = Window.class.getDeclaredField("ownedWindowList"); + f.setAccessible(true); + Vector ownersChildren = (Vector)f.get(owner); + if (ownersChildren.size() > 0) + { + throw new RuntimeException("Test FAILED: some of the child windows are not removed from owner's children list"); + } + } + catch (NoSuchFieldException z) + { + System.out.println("Test PASSED: no 'ownedWindowList' field in Window class"); + return; + } + catch (Exception z) + { + throw new RuntimeException("Test FAILED: unexpected exception", z); + } + + // Test passed + System.out.println("Test PASSED"); + + owner.dispose(); + } +} diff --git a/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java b/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java new file mode 100644 index 00000000000..80823918e32 --- /dev/null +++ b/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java @@ -0,0 +1,83 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that InputEvents button masks arrays are the same + @author Andrei Dmitriev : area=awt.event + @run main ButtonArraysEquality + */ + +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +// get array InputEvent.BUTTON_MASK via reflection +// get array InputEvent.BUTTON_DOWN_MASK via reflection +// compare their lengths and values + +public class ButtonArraysEquality { + static int [] eventDownMask = new int []{InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK}; + + public static void main(String []s){ + int [] buttonDownMasksAPI = new int [MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonDownMasksAPI[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonDownMasksAPI[i]); + } + + // getButtonDownMasks() + Object obj = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + try { + Class clazz = Class.forName("java.awt.event.InputEvent"); + Method method = clazz.getDeclaredMethod("getButtonDownMasks",new Class [] {}); + if (method != null) { + method.setAccessible(true); + return method.invoke(null, (Object[])null); + } + }catch (Exception e){ + throw new RuntimeException("Test failed. Exception occured:", e); + } + return null; + } + }); + + int [] buttonDownMasks = new int [Array.getLength(obj)]; + checkNullAndPutValuesToArray(buttonDownMasks, obj); + + //check lengths: array shouldn't contain less elements then the number of buttons on a mouse + if (buttonDownMasks.length < buttonDownMasksAPI.length){ + throw new RuntimeException("Test failed. The lengths array is less then the number of buttons"); + } + + // verify values for first three buttons + for (int i = 0; i < 3; i++) { + if (eventDownMask[i] != buttonDownMasks[i]) + { + System.out.println("Test : "+ i + " | " + " | " +eventDownMask[i] + " | "+ buttonDownMasks[i]); + throw new RuntimeException("Failure: masks are not correct for standard buttons"); + } + } + + // verify values for extra buttons if any + for (int i = 3; i < MouseInfo.getNumberOfButtons(); i++) { + if (buttonDownMasksAPI[i] != buttonDownMasks[i]) { + throw new RuntimeException("Failure: masks are not the same for extra buttons"); + } + } + System.out.println("Test passed."); + } + + public static void checkNullAndPutValuesToArray(int [] array, Object obj){ + if (obj == null){ + throw new RuntimeException("Test failed. The array obtained via reflection is "+obj); + } + + for (int i = 0; i < Array.getLength(obj); i++){ + System.out.println("Test (Reflection): "+ Array.getInt(obj, i)); + array[i] = Array.getInt(obj, i); + } + } +} diff --git a/jdk/test/java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java b/jdk/test/java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java new file mode 100644 index 00000000000..802f4cfd6b2 --- /dev/null +++ b/jdk/test/java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java @@ -0,0 +1,53 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent CTOR accepts extra mouse button numbers + @author Andrei Dmitriev : area=awt.event + @run main AcceptExtraButton + */ + +//package acceptextrabutton; + +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseAdapter; + +public class AcceptExtraButton extends Frame { + static int [] eventID = new int []{MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, MouseEvent.MOUSE_CLICKED}; + + public static void main(String []s){ + AcceptExtraButton f = new AcceptExtraButton(); + f.setSize(300, 300); + f.setVisible(true); + + for (int buttonId = 0; buttonId>>"+me); + f.dispatchEvent( ( AWTEvent )me ); + } + } + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + } + }; + f.addMouseListener(ma1); + } +} diff --git a/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions.java b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions.java new file mode 100644 index 00000000000..d4611158553 --- /dev/null +++ b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions.java @@ -0,0 +1,89 @@ +/* + test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent could be constructed correctly for mouse extra buttons in regard to sun.awt.enableExtraMouseButtons property + @author Andrei Dmitriev : area=awt.event + @run main CTORRestrictions + */ + +/* + * verify that user can create the MouseEvent? with button1|2|3|4|5|... when property "sun.awt.enableExtraMouseButtons" is true by default + */ +import java.awt.*; +import java.awt.event.*; + +public class CTORRestrictions{ + static Frame frame = new Frame("MouseEvent Test Frame"); + static Point mousePosition; + static Point mousePositionOnScreen; + + public static void main(String []s){ + Robot robot = null; + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Test Failed", ex); + } + frame.setSize (200,200); + frame.setLocation (300, 400); + frame.setVisible(true); + robot.delay(1000); + System.out.println("sun.awt.enableExtraMouseButtons = "+Toolkit.getDefaultToolkit().getDesktopProperty("sun.awt.enableExtraMouseButtons")); + mousePosition = new Point(100, 100); + mousePositionOnScreen = new Point(frame.getLocationOnScreen().x + mousePosition.x, + frame.getLocationOnScreen().y + mousePosition.y); + + /* + * On Linux the native system count a wheel (both directions) as two more buttons on a mouse. + * So, MouseInfo.getNumberOfButtons() would report 5 buttons on a three-button mouse. + * On Windows it would still report that MouseInfo.getNumberOfButtons() == 3. + * We should handle XToolkit case and iterate through the buttons + * up to (MouseInfo.getNumberOfButtons() - 2) value. + */ + int numberOfButtons; + if (Toolkit.getDefaultToolkit().getClass().getName().equals("sun.awt.windows.WToolkit")){ + numberOfButtons = MouseInfo.getNumberOfButtons(); + } else { + numberOfButtons = MouseInfo.getNumberOfButtons() - 2; + } + System.out.println("Stage 1. Number of buttons = "+ numberOfButtons); + + for (int buttonId = 1; buttonId <= numberOfButtons; buttonId++){ + postMouseEventNewCtor(buttonId); + } + + System.out.println("Stage 2. Number of buttons = "+ numberOfButtons); + for (int buttonId = 1; buttonId <= numberOfButtons; buttonId++){ + postMouseEventOldCtor(buttonId); + } + System.out.println("Test passed."); + } + + public static void postMouseEventNewCtor(int buttonId) { + MouseEvent me = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + mousePositionOnScreen.x, + mousePositionOnScreen.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )me ); + } + + public static void postMouseEventOldCtor(int buttonId) { + MouseEvent meOld = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )meOld ); + } +} diff --git a/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java new file mode 100644 index 00000000000..aaf1c16c760 --- /dev/null +++ b/jdk/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java @@ -0,0 +1,101 @@ +/* + test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent could be constructed correctly for mouse extra buttons in regard to sun.awt.enableExtraMouseButtons property + @author Andrei Dmitriev : area=awt.event + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false CTORRestrictions_Disable + */ + +/* + * verify that user can't create the MouseEvent? with button4|5|... when property "sun.awt.enableExtraMouseButtons"=false + * verify that user can create the MouseEvent? with button1|2|3 when property "sun.awt.enableExtraMouseButtons"=false + */ + +import java.awt.*; +import java.awt.event.*; + +public class CTORRestrictions_Disable { + static Frame frame = new Frame("MouseEvent Test Frame"); + static Point mousePosition; + static Point mousePositionOnScreen; + + public static void main(String []s){ + Robot robot = null; + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Test Failed", ex); + } + frame.setSize (200,200); + frame.setLocation (300, 400); + frame.setVisible(true); + robot.delay(1000); + System.out.println(Toolkit.getDefaultToolkit().getDesktopProperty("sun.awt.enableExtraMouseButtons")); + mousePosition = new Point(100, 100); + mousePositionOnScreen = new Point(frame.getLocationOnScreen().x + mousePosition.x, + frame.getLocationOnScreen().y + mousePosition.y); + + System.out.println("Stage 1"); + for (int buttonId = 1; buttonId <= MouseInfo.getNumberOfButtons(); buttonId++){ + try { + postMouseEventNewCtor(buttonId); + if (buttonId > 3) { + throw new RuntimeException("Stage 1 FAILED: MouseEvent CTOR accepted the extra button " + (buttonId+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (buttonId > 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("Stage 1 FAILED : exception happen on standard button.", e); + } + } + } + + System.out.println("Stage 2"); + for (int buttonId = 1; buttonId <= MouseInfo.getNumberOfButtons(); buttonId++){ + try { + postMouseEventOldCtor(buttonId); + if (buttonId > 3) { + throw new RuntimeException("Stage 2 FAILED: MouseEvent CTOR accepted the extra button " + (buttonId+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (buttonId > 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("Stage 2 FAILED : exception happen on standard button.", e); + } + } + } + System.out.println("Test passed."); + } + + public static void postMouseEventNewCtor(int buttonId) { + MouseEvent me = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + mousePositionOnScreen.x, + mousePositionOnScreen.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )me ); + } + + public static void postMouseEventOldCtor(int buttonId) { + MouseEvent meOld = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )meOld ); + } +} + + diff --git a/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java b/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java new file mode 100644 index 00000000000..2f62521f58d --- /dev/null +++ b/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java @@ -0,0 +1,65 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that InputEvent.getMaskForButton() returns the same values as in InputEvent.BUTTON_DOWN_MASK + @author Andrei Dmitriev : area=awt.event + @run main CheckGetMaskForButton +*/ + +import java.awt.*; +import java.awt.event.InputEvent; +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +public class CheckGetMaskForButton{ + static Robot robot; + + public static void main(String []s){ + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + CheckGetMaskForButton f = new CheckGetMaskForButton(); + int [] buttonMasksViaAPI = new int[MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasksViaAPI[i] = InputEvent.getMaskForButton(i+1); + System.out.println("Test (API): "+ buttonMasksViaAPI[i]); + } + + //get same array via reflection + Object obj = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + try { + Class clazz = Class.forName("java.awt.event.InputEvent"); + Method method = clazz.getDeclaredMethod("getButtonDownMasks",new Class [] {}); + if (method != null) { + method.setAccessible(true); + return method.invoke(null, (Object[])null); + } + }catch (Exception e){ + throw new RuntimeException("Test failed. Exception occured:", e); + } + return null; + } + }); + + if (obj == null){ + throw new RuntimeException("Test failed. The value obtained via reflection is "+obj); + } + + int [] buttonDownMasksViaReflection = new int [Array.getLength(obj)]; + //check that length of API array greater or equals then Reflect array. + if (Array.getLength(obj) < buttonMasksViaAPI.length){ + throw new RuntimeException("Test failed. The length of API array greater or equals then the length of Reflect array."); + } + + //Check that the values obtained via reflection from InputEvent.BUTTON_DOWN_MASK are the + // same as for standard API. + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("Test (Reflection): "+ Array.getInt(obj, i)); + if (buttonMasksViaAPI[i] != Array.getInt(obj, i)){ + throw new RuntimeException("Test failed. Values of InputEvent array are different for API and Reflection invocations"); + } + } + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/beans/EventHandler/Test6788531.java b/jdk/test/java/beans/EventHandler/Test6788531.java new file mode 100644 index 00000000000..1754f5bc552 --- /dev/null +++ b/jdk/test/java/beans/EventHandler/Test6788531.java @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6788531 + * @summary Tests public method lookup problem in EventHandler + * @author Sergey Malenkov + */ + +import javax.swing.JButton; +import java.awt.event.ActionListener; +import java.beans.EventHandler; + +public class Test6788531 { + public static void main(String[] args) throws Exception { + JButton button = new JButton("hi"); + button.addActionListener(EventHandler.create(ActionListener.class, new Private(), "run")); + button.addActionListener(EventHandler.create(ActionListener.class, new PrivateGeneric(), "run", "generic")); + button.doClick(); + } + + public static class Public { + public void run() { + throw new Error("method is overridden"); + } + } + + static class Private extends Public { + public void run() { + System.out.println("default"); + } + } + + public static class PublicGeneric { + public void run(T object) { + throw new Error("method is overridden"); + } + } + + static class PrivateGeneric extends PublicGeneric { + public void run(String string) { + System.out.println(string); + } + } +} diff --git a/jdk/test/java/beans/PropertyEditor/TestEnumSubclass.java b/jdk/test/java/beans/PropertyEditor/TestEnumSubclass.java new file mode 100644 index 00000000000..f1d5f78c5d2 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/TestEnumSubclass.java @@ -0,0 +1,50 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6736248 + * @summary Tests PropertyEditor for value of subtype Enum with security manager + * @author Sergey Malenkov + */ + +public class TestEnumSubclass { + public static void main(String[] args) { + System.setSecurityManager(new SecurityManager()); + new TestEditor(Operation.class); + } + + public enum Operation { + PLUS { + public int run(int i, int j) { + return i + j; + } + }, + MINUS { + public int run(int i, int j) { + return i - j; + } + }; + public abstract int run(int i, int j); + } +} diff --git a/jdk/test/java/beans/PropertyEditor/TestEnumSubclassJava.java b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassJava.java new file mode 100644 index 00000000000..296d1f31d1c --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassJava.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6736248 + * @summary Tests PropertyEditor for value of subtype Enum + * @author Sergey Malenkov + */ + +public class TestEnumSubclassJava { + public static void main(String[] args) { + new TestEditor(Operation.class).testJava(Operation.PLUS); + } + + public enum Operation { + PLUS { + public int run(int i, int j) { + return i + j; + } + }, + MINUS { + public int run(int i, int j) { + return i - j; + } + }; + public abstract int run(int i, int j); + } +} diff --git a/jdk/test/java/beans/PropertyEditor/TestEnumSubclassNull.java b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassNull.java new file mode 100644 index 00000000000..2a407bf9998 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassNull.java @@ -0,0 +1,49 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6736248 + * @summary Tests PropertyEditor for null value of subtype Enum + * @author Sergey Malenkov + */ + +public class TestEnumSubclassNull { + public static void main(String[] args) { + new TestEditor(Operation.class).testJava(null); + } + + public enum Operation { + PLUS { + public int run(int i, int j) { + return i + j; + } + }, + MINUS { + public int run(int i, int j) { + return i - j; + } + }; + public abstract int run(int i, int j); + } +} diff --git a/jdk/test/java/beans/PropertyEditor/TestEnumSubclassValue.java b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassValue.java new file mode 100644 index 00000000000..5c0e970f569 --- /dev/null +++ b/jdk/test/java/beans/PropertyEditor/TestEnumSubclassValue.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6736248 + * @summary Tests PropertyEditor for value of subtype Enum + * @author Sergey Malenkov + */ + +public class TestEnumSubclassValue { + public static void main(String[] args) { + TestEditor test = new TestEditor(Operation.class); + test.testValue(Operation.PLUS, "PLUS"); + test.testValue(null, null); + test.testText("MINUS", Operation.MINUS); + test.testText(null, null); + } + + public enum Operation { + PLUS { + public int run(int i, int j) { + return i + j; + } + }, + MINUS { + public int run(int i, int j) { + return i - j; + } + }; + public abstract int run(int i, int j); + } +} diff --git a/jdk/test/java/beans/Statement/Test6788531.java b/jdk/test/java/beans/Statement/Test6788531.java new file mode 100644 index 00000000000..637b4bd7020 --- /dev/null +++ b/jdk/test/java/beans/Statement/Test6788531.java @@ -0,0 +1,62 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6788531 + * @summary Tests public method lookup problem in Statement + * @author Sergey Malenkov + */ + +import java.beans.Statement; + +public class Test6788531 { + public static void main(String[] args) throws Exception { + new Statement(new Private(), "run", null).execute(); + new Statement(new PrivateGeneric(), "run", new Object[] {"generic"}).execute(); + } + + public static class Public { + public void run() { + throw new Error("method is overridden"); + } + } + + static class Private extends Public { + public void run() { + System.out.println("default"); + } + } + + public static class PublicGeneric { + public void run(T object) { + throw new Error("method is overridden"); + } + } + + static class PrivateGeneric extends PublicGeneric { + public void run(String string) { + System.out.println(string); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/Test4864117.java b/jdk/test/java/beans/XMLDecoder/Test4864117.java new file mode 100644 index 00000000000..a3459f918c6 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/Test4864117.java @@ -0,0 +1,146 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4864117 + * @summary Tests XMLDecoder within another DefaultHandler for SAX parser + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.beans.ExceptionListener; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +public final class Test4864117 extends DefaultHandler implements ExceptionListener { + private static final String TEST = "test"; + private static final String DATA + = "\n" + + " \n" + + " Hello, world!\n" + + " \n" + + ""; + + public static void main(String[] args) { + Test4864117 test = new Test4864117(); + InputStream input = new ByteArrayInputStream(DATA.getBytes()); + Exception error = null; + try { + SAXParserFactory.newInstance().newSAXParser().parse(input, test); + } + catch (ParserConfigurationException exception) { + error = exception; + } + catch (SAXException exception) { + error = exception.getException(); + if (error == null) { + error = exception; + } + } + catch (IOException exception) { + error = exception; + } + if (error != null) { + throw new Error("unexpected error", error); + } + test.print('?', test.getMessage()); + } + + private String message; + + public String getMessage() { + if (this.message == null) { + throw new Error("owner's method is not called"); + } + return this.message; + } + + public void setMessage(String message) { + this.message = message; + print(':', this.message); + } + + // DefaultHandler implementation + + private DefaultHandler handler; + private int depth; + + @Override + public void startDocument() throws SAXException { + this.handler = XMLDecoder.createHandler(this, this, null); + this.handler.startDocument(); + } + + @Override + public void endDocument() { + this.handler = null; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + print('>', qName); + if (this.depth > 0) { + this.handler.startElement(uri, localName, qName, attributes); + } else if (!TEST.equals(qName)) { + throw new SAXException("unexpected element name: " + qName); + } + this.depth++; + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + this.depth--; + print('<', qName); + if (this.depth > 0) { + this.handler.endElement(uri, localName, qName); + } else if (!TEST.equals(qName)) { + throw new SAXException("unexpected element name: " + qName); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + this.handler.characters(ch, start, length); + } + + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } + + private void print(char ch, String name) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < this.depth; i++) sb.append(' '); + sb.append(ch).append(' ').append(name); + System.out.println(sb.toString()); + } +} diff --git a/jdk/test/java/beans/XMLDecoder/Test6341798.java b/jdk/test/java/beans/XMLDecoder/Test6341798.java index 2bc43e87565..677ff842352 100644 --- a/jdk/test/java/beans/XMLDecoder/Test6341798.java +++ b/jdk/test/java/beans/XMLDecoder/Test6341798.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ public class Test6341798 { private static final String DATA = "\n" - + " \n" + + " \n" + " \n" + " true\n" + " \n" diff --git a/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java b/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java new file mode 100644 index 00000000000..2b8abb2af9e --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/AbstractTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.beans.ExceptionListener; +import java.beans.XMLDecoder; + +import java.io.ByteArrayInputStream; + +abstract class AbstractTest implements ExceptionListener { + public void exceptionThrown(Exception exception) { + throw new Error("unexpected exception", exception); + } + + /** + * Validates the XML decoder for XML archive + * that defined in the public field of the subclass. + * + * @param decoder the initialized XML decoder + * @throws Error if validation failed + */ + protected abstract void validate(XMLDecoder decoder); + + /** + * This is entry point to start testing. + * + * @param security use {@code true} to start + * second pass in secure context + */ + final void test(boolean security) { + byte[] array = getFieldValue("XML").getBytes(); // NON-NLS: the field name + ByteArrayInputStream input = new ByteArrayInputStream(array); + XMLDecoder decoder = new XMLDecoder(input); + decoder.setExceptionListener(this); + validate(decoder); + try { + throw new Error("unexpected object" + decoder.readObject()); + } catch (ArrayIndexOutOfBoundsException exception) { + // expected exception + } + decoder.close(); + if (security) { + System.setSecurityManager(new SecurityManager()); + test(false); + } + } + + private String getFieldValue(String field) { + try { + return getClass().getField(field).get(this).toString(); + } catch (NoSuchFieldException exception) { + throw new Error("unexpected exception", exception); + } catch (IllegalAccessException exception) { + throw new Error("unexpected exception", exception); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestArray.java b/jdk/test/java/beans/XMLDecoder/spec/TestArray.java new file mode 100644 index 00000000000..7ae34a148e5 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestArray.java @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.lang.reflect.Array; + +public final class TestArray extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " -111\n" + + " 1111\n" + + " \n" + + " \n" + + " \n" + + " Hello, world!\n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestArray().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + Number[] numbers = getArray(Number.class, 2, decoder.readObject()); + if (!numbers[0].equals(Byte.valueOf("-111"))) { // NON-NLS: hardcoded in XML + throw new Error("unexpected byte value"); + } + if (!numbers[1].equals(Long.valueOf("1111"))) { // NON-NLS: hardcoded in XML + throw new Error("unexpected long value"); + } + + Object[] objects = getArray(Object.class, 3, decoder.readObject()); + if (objects[0] != null) { + throw new Error("unexpected first value"); + } + if (!objects[1].equals("Hello, world!")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected string value"); + } + if (objects[2] != null) { + throw new Error("unexpected last value"); + } + } + + private static T[] getArray(Class component, int length, Object object) { + Class type = object.getClass(); + if (!type.isArray()) { + throw new Error("array expected"); + } + if (!type.getComponentType().equals(component)) { + throw new Error("unexpected component type"); + } + if (length != Array.getLength(object)) { + throw new Error("unexpected array length"); + } + return (T[]) object; + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java b/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java new file mode 100644 index 00000000000..e24d1fb4f72 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestBoolean.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestBoolean extends AbstractTest { + public static final String XML + = "\n" + + " true\n" + + " false\n" + + ""; + + public static void main(String[] args) { + new TestBoolean().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.TRUE.equals(decoder.readObject())) { + throw new Error("true expected"); + } + if (!Boolean.FALSE.equals(decoder.readObject())) { + throw new Error("false expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestByte.java b/jdk/test/java/beans/XMLDecoder/spec/TestByte.java new file mode 100644 index 00000000000..46693d94c0b --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestByte.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestByte extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + ""; + + public static void main(String[] args) { + new TestByte().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate((byte) 0, decoder.readObject()); + validate(Byte.MAX_VALUE, decoder.readObject()); + validate(Byte.MIN_VALUE, decoder.readObject()); + } + + private static void validate(byte value, Object object) { + if (!object.equals(Byte.valueOf(value))) { + throw new Error("byte " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestChar.java b/jdk/test/java/beans/XMLDecoder/spec/TestChar.java new file mode 100644 index 00000000000..cb29b713bce --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestChar.java @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestChar extends AbstractTest { + public static final String XML + = "\n" + + " X\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestChar().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!decoder.readObject().equals(Character.valueOf('X'))) { + throw new Error("unexpected character"); + } + if (!decoder.readObject().equals(Character.valueOf((char) 0x20))) { + throw new Error("unexpected character code"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestClass.java b/jdk/test/java/beans/XMLDecoder/spec/TestClass.java new file mode 100644 index 00000000000..2c16ba75f3c --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestClass.java @@ -0,0 +1,61 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestClass extends AbstractTest { + public static final String PREFIX = "javax.swing.colorchooser."; + public static final String INTERFACE = "ColorSelectionModel"; + public static final String PUBLIC_CLASS = "DefaultColorSelectionModel"; + public static final String PRIVATE_CLASS = "DiagramComponent"; + public static final String XML + = "\n" + + " " + PREFIX + INTERFACE + "\n" + + " " + PREFIX + PUBLIC_CLASS + "\n" + + " " + PREFIX + PRIVATE_CLASS + "\n" + + ""; + + public static void main(String[] args) { + new TestClass().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(PREFIX + INTERFACE, decoder.readObject()); + validate(PREFIX + PUBLIC_CLASS, decoder.readObject()); + validate(PREFIX + PRIVATE_CLASS, decoder.readObject()); + } + + private static void validate(String name, Object object) { + Class type = (Class) object; + if (!type.getName().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java b/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java new file mode 100644 index 00000000000..8e3d918c886 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestDouble.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestDouble extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 1000\n" + + " -1.1e15\n" + + " 10.11e-123\n" + + ""; + + public static void main(String[] args) { + new TestDouble().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0.0, decoder.readObject()); + validate(1000.0, decoder.readObject()); + validate(-1.1e15, decoder.readObject()); + validate(10.11e-123, decoder.readObject()); + } + + private static void validate(double value, Object object) { + if (!object.equals(Double.valueOf(value))) { + throw new Error("double " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java b/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java new file mode 100644 index 00000000000..57a81b87740 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestFalse.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestFalse extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestFalse().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.FALSE.equals(decoder.readObject())) { + throw new Error("false expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestField.java b/jdk/test/java/beans/XMLDecoder/spec/TestField.java new file mode 100644 index 00000000000..aa84408814e --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestField.java @@ -0,0 +1,74 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestField extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " static postfix\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " postfix\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestField().test(true); + } + + public static String FIELD; + public String field; + + @Override + protected void validate(XMLDecoder decoder) { + FIELD = "static prefix"; + field = "prefix"; + decoder.setOwner(this); + validate(decoder, "static prefix"); + validate(decoder, "static postfix"); + validate(decoder, "prefix"); + validate(decoder, "postfix"); + } + + private static void validate(XMLDecoder decoder, String name) { + if (!decoder.readObject().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java b/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java new file mode 100644 index 00000000000..bb1287f8804 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestFloat.java @@ -0,0 +1,58 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestFloat extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 100\n" + + " -1e15\n" + + " 100e-20\n" + + ""; + + public static void main(String[] args) { + new TestFloat().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0.0f, decoder.readObject()); + validate(100.0f, decoder.readObject()); + validate(-1e15f, decoder.readObject()); + validate(100e-20f, decoder.readObject()); + } + + private static void validate(float value, Object object) { + if (!object.equals(Float.valueOf(value))) { + throw new Error("float " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestInt.java b/jdk/test/java/beans/XMLDecoder/spec/TestInt.java new file mode 100644 index 00000000000..531c9447b64 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestInt.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestInt extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + " 2147483647\n" + + " -2147483648\n" + + ""; + + public static void main(String[] args) { + new TestInt().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0, decoder.readObject()); + validate((int) Byte.MAX_VALUE, decoder.readObject()); + validate((int) Byte.MIN_VALUE, decoder.readObject()); + validate((int) Short.MAX_VALUE, decoder.readObject()); + validate((int) Short.MIN_VALUE, decoder.readObject()); + validate(Integer.MAX_VALUE, decoder.readObject()); + validate(Integer.MIN_VALUE, decoder.readObject()); + } + + private static void validate(int value, Object object) { + if (!object.equals(Integer.valueOf(value))) { + throw new Error("int " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestJava.java b/jdk/test/java/beans/XMLDecoder/spec/TestJava.java new file mode 100644 index 00000000000..5786195aaa0 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestJava.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestJava extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " Hello, world!\n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestJava().test(true); + } + + private String message; + + public void init(String message) { + this.message = message; + } + + @Override + protected void validate(XMLDecoder decoder) { + decoder.setOwner(this); + if (this != decoder.readObject()) { + throw new Error("owner should be the same"); + } + if (this.message == null) { + throw new Error("owner's method is not called"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestLong.java b/jdk/test/java/beans/XMLDecoder/spec/TestLong.java new file mode 100644 index 00000000000..16a7e324014 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestLong.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestLong extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + " 2147483647\n" + + " -2147483648\n" + + " 9223372036854775807\n" + + " -9223372036854775808\n" + + ""; + + public static void main(String[] args) { + new TestLong().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(0L, decoder.readObject()); + validate((long) Byte.MAX_VALUE, decoder.readObject()); + validate((long) Byte.MIN_VALUE, decoder.readObject()); + validate((long) Short.MAX_VALUE, decoder.readObject()); + validate((long) Short.MIN_VALUE, decoder.readObject()); + validate((long) Integer.MAX_VALUE, decoder.readObject()); + validate((long) Integer.MIN_VALUE, decoder.readObject()); + validate(Long.MAX_VALUE, decoder.readObject()); + validate(Long.MIN_VALUE, decoder.readObject()); + } + + private static void validate(long value, Object object) { + if (!object.equals(Long.valueOf(value))) { + throw new Error("long " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java b/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java new file mode 100644 index 00000000000..01ee5e1cf95 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestMethod.java @@ -0,0 +1,178 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestMethod extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestMethod().test(true); + } + + private NoSuchMethodException exception; + + @Override + public void exceptionThrown(Exception exception) { + if (this.exception != null) { + // only one exception allowed + super.exceptionThrown(exception); + } else if (exception instanceof NoSuchMethodException) { + // expected exception: ambiguous methods are found + this.exception = (NoSuchMethodException) exception; + } else { + super.exceptionThrown(exception); + } + } + + @Override + protected void validate(XMLDecoder decoder) { + this.exception = null; + validate(decoder, A.class); + validate(decoder, B.class); + validate(decoder, C.class); + validate(decoder, D.class); + validate(decoder, E.class); + if (this.exception == null) { + throw new Error("NoSuchMethodException expected"); + } + } + + private static void validate(XMLDecoder decoder, Class type) { + if (!type.equals(decoder.readObject().getClass())) { + throw new Error("unexpected class"); + } + } + + /** + * All ambiguous method declarations should fail. + */ + public static class A { + public void m(X x1, X x2) { + throw new Error("A.m(X,X) should not be called"); + } + + public void m(X x1, Y y2) { + throw new Error("A.m(X,Y) should not be called"); + } + + public void m(Y y1, X x2) { + throw new Error("A.m(Y,X) should not be called"); + } + } + + /** + * The most specific method in this case would be the second declaration. + */ + public static class B { + public void m(X x1, X x2) { + throw new Error("B.m(X,X) should not be called"); + } + + public void m(X x1, Y y2) { + // expected: B.m(X,Y) should be called + } + } + + /** + * The most specific method in this case would be the first declaration. + */ + public static class C { + public void m(Y y1, Y y2) { + // expected: C.m(Y,Y) should be called + } + + public void m(X x1, X x2) { + throw new Error("C.m(X,X) should not be called"); + } + } + + /** + * Same as the previous case but flip methods. + */ + public static class D { + public void m(X x1, X x2) { + throw new Error("D.m(X,X) should not be called"); + } + + public void m(Y y1, Y y2) { + // expected: D.m(Y,Y) should be called + } + } + + /** + * The method should be called with (Z,Z). + */ + public static class E { + public void m(X x1, X x2) { + // expected: E.m(X,X) should be called + } + } + + public static class X { + } + + public static class Y extends X { + } + + public static class Z extends Y { + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestNew.java b/jdk/test/java/beans/XMLDecoder/spec/TestNew.java new file mode 100644 index 00000000000..3e1e86d9951 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestNew.java @@ -0,0 +1,90 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import java.util.ArrayList; +import java.util.List; + +public final class TestNew extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " single\n" + + " \n" + + " \n" + + " first\n" + + " second\n" + + " third\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestNew().test(true); + } + + private List list; + + public TestNew(String...messages) { + if (messages != null) { + this.list = new ArrayList(); + for (String message : messages) { + this.list.add(message); + } + } + } + + @Override + public boolean equals(Object object) { + if (object instanceof TestNew) { + TestNew test = (TestNew) object; + return (test.list == null) + ? this.list == null + : test.list.equals(this.list); + } + return false; + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(decoder.readObject()); + validate(decoder.readObject(), null); + validate(decoder.readObject(), "single"); + validate(decoder.readObject(), "first", "second", "third"); + } + + private static void validate(Object object, String...messages) { + if (!object.equals(new TestNew(messages))) { + throw new Error("expected object"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestNull.java b/jdk/test/java/beans/XMLDecoder/spec/TestNull.java new file mode 100644 index 00000000000..e14bf951e58 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestNull.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestNull extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestNull().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (null != decoder.readObject()) { + throw new Error("null value expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestObject.java b/jdk/test/java/beans/XMLDecoder/spec/TestObject.java new file mode 100644 index 00000000000..d9531b3d646 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestObject.java @@ -0,0 +1,84 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +public final class TestObject extends AbstractTest { + public static final String XML // TODO + = "\n" + + " \n" + + " \n" + + " \n" + + " button\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " label\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestObject().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + JPanel panel = (JPanel) decoder.readObject(); + if (2 != panel.getComponents().length) { + throw new Error("unexpected component count"); + } + JButton button = (JButton) panel.getComponents()[0]; + if (!button.getText().equals("button")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected button text"); + } + if (SwingConstants.CENTER != button.getVerticalAlignment()) { + throw new Error("unexpected vertical alignment"); + } + JLabel label = (JLabel) panel.getComponents()[1]; + if (!label.getText().equals("label")) { // NON-NLS: hardcoded in XML + throw new Error("unexpected label text"); + } + if (button != label.getLabelFor()) { + throw new Error("unexpected component"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java b/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java new file mode 100644 index 00000000000..e1f9c77e445 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestProperty.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestProperty extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " message\n" + + " \n" + + " \n" + + " \n" + + " indexed\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestProperty().test(true); + } + + private int index; + private String message; + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getIndexed(int index) { + if (this.index != index) { + throw new Error("unexpected index"); + } + return this.message; + } + + public void setIndexed(int index, String message) { + this.index = index; + this.message = message; + } + + @Override + protected void validate(XMLDecoder decoder) { + decoder.setOwner(this); + validate(decoder, "message"); + validate(decoder, "indexed"); + } + + private static void validate(XMLDecoder decoder, String name) { + if (!decoder.readObject().equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestShort.java b/jdk/test/java/beans/XMLDecoder/spec/TestShort.java new file mode 100644 index 00000000000..99a0c57d357 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestShort.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestShort extends AbstractTest { + public static final String XML + = "\n" + + " 0\n" + + " 127\n" + + " -128\n" + + " 32767\n" + + " -32768\n" + + ""; + + public static void main(String[] args) { + new TestShort().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate((short) 0, decoder.readObject()); + validate((short) Byte.MAX_VALUE, decoder.readObject()); + validate((short) Byte.MIN_VALUE, decoder.readObject()); + validate(Short.MAX_VALUE, decoder.readObject()); + validate(Short.MIN_VALUE, decoder.readObject()); + } + + private static void validate(short value, Object object) { + if (!object.equals(Short.valueOf(value))) { + throw new Error("short " + value + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestString.java b/jdk/test/java/beans/XMLDecoder/spec/TestString.java new file mode 100644 index 00000000000..d41b1bbce38 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestString.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestString extends AbstractTest { + public static final String PREFIX = " prefix "; + public static final String POSTFIX = " postfix "; + public static final String XML + = "\n" + + " " + PREFIX + "\n" + + " " + POSTFIX + "\n" + + " " + PREFIX + POSTFIX + "\n" + + " " + PREFIX + "" + POSTFIX + "\n" + + ""; + + public static void main(String[] args) { + new TestString().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + validate(PREFIX, decoder.readObject()); + validate(POSTFIX, decoder.readObject()); + validate(PREFIX + POSTFIX, decoder.readObject()); + validate(PREFIX + '\u0000' + POSTFIX, decoder.readObject()); + } + + private static void validate(String name, Object object) { + if (!object.equals(name)) { + throw new Error(name + " expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java b/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java new file mode 100644 index 00000000000..934d28e4f63 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestTrue.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestTrue extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestTrue().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + if (!Boolean.TRUE.equals(decoder.readObject())) { + throw new Error("true expected"); + } + } +} diff --git a/jdk/test/java/beans/XMLDecoder/spec/TestVar.java b/jdk/test/java/beans/XMLDecoder/spec/TestVar.java new file mode 100644 index 00000000000..701edad79a8 --- /dev/null +++ b/jdk/test/java/beans/XMLDecoder/spec/TestVar.java @@ -0,0 +1,54 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary Tests element + * @author Sergey Malenkov + */ + +import java.beans.XMLDecoder; + +public final class TestVar extends AbstractTest { + public static final String XML + = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public static void main(String[] args) { + new TestVar().test(true); + } + + @Override + protected void validate(XMLDecoder decoder) { + for (int i = 0; i < 3; i++) { + if (decoder != decoder.readObject()) { + throw new Error("decoder instance expected"); + } + } + } +} diff --git a/jdk/test/java/lang/Boolean/Factory.java b/jdk/test/java/lang/Boolean/Factory.java new file mode 100644 index 00000000000..dbf7704194b --- /dev/null +++ b/jdk/test/java/lang/Boolean/Factory.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4262398 + * @summary Basic test for Boolean.valueOf(boolean b). + */ + +public class Factory { + public static void main(String[] args) throws Exception { + if (Boolean.valueOf(true) != Boolean.TRUE) + throw new Exception("Truth failure"); + if (Boolean.valueOf(false) != Boolean.FALSE) + throw new Exception("Major fallacy"); + } +} diff --git a/jdk/test/java/lang/Boolean/GetBoolean.java b/jdk/test/java/lang/Boolean/GetBoolean.java new file mode 100644 index 00000000000..b452a1bdf43 --- /dev/null +++ b/jdk/test/java/lang/Boolean/GetBoolean.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4252308 + * @summary test Boolean.getBoolean method with empty key + */ + +public class GetBoolean { + public static void main(String[] args) throws Exception { + Boolean.getBoolean(""); + Boolean.getBoolean(null); + } +} diff --git a/jdk/test/java/lang/Boolean/MakeBooleanComparable.java b/jdk/test/java/lang/Boolean/MakeBooleanComparable.java new file mode 100644 index 00000000000..b84a4a27f59 --- /dev/null +++ b/jdk/test/java/lang/Boolean/MakeBooleanComparable.java @@ -0,0 +1,57 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4329937 + * @summary Basic test for making Boolean implement Comparable + * @author Josh Bloch + * + * @compile -source 1.5 MakeBooleanComparable.java + * @run main MakeBooleanComparable + */ + +import java.util.*; + +public class MakeBooleanComparable { + public static void main(String args[]) { + Random rnd = new Random(); + List list = new ArrayList(); + int numFalse = 0; + for (int i = 0; i < 1000; i++) { + boolean element = rnd.nextBoolean(); + if (!element) + numFalse++; + list.add(element); // Autoboxing! + } + + Collections.sort(list); + + for (int i = 0; i < numFalse; i++) + if (list.get(i).booleanValue()) // Autounboxing doesn't work yet! + throw new RuntimeException("False positive: " + i); + for (int i = numFalse; i < 1000; i++) + if (!list.get(i).booleanValue()) // Autounboxing doesn't work yet! + throw new RuntimeException("False negative: " + i); + } +} diff --git a/jdk/test/java/lang/Boolean/ParseBoolean.java b/jdk/test/java/lang/Boolean/ParseBoolean.java new file mode 100644 index 00000000000..997b4f0a313 --- /dev/null +++ b/jdk/test/java/lang/Boolean/ParseBoolean.java @@ -0,0 +1,53 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4253773 + * @summary test Boolean.parseBoolean + */ + +public class ParseBoolean { + public static void main(String[] args) throws Exception { + checkTrue(Boolean.parseBoolean("TRUE")); + checkTrue(Boolean.parseBoolean("true")); + checkTrue(Boolean.parseBoolean("TrUe")); + + checkFalse(Boolean.parseBoolean("false")); + checkFalse(Boolean.parseBoolean("FALSE")); + checkFalse(Boolean.parseBoolean("FaLse")); + checkFalse(Boolean.parseBoolean(null)); + checkFalse(Boolean.parseBoolean("garbage")); + checkFalse(Boolean.parseBoolean("TRUEE")); + } + + static void checkTrue(boolean b) { + if (!b) + throw new RuntimeException("test failed"); + } + + static void checkFalse(boolean b) { + if (b) + throw new RuntimeException("test failed"); + } +} diff --git a/jdk/test/java/lang/Byte/Decode.java b/jdk/test/java/lang/Byte/Decode.java new file mode 100644 index 00000000000..4642eacb1e6 --- /dev/null +++ b/jdk/test/java/lang/Byte/Decode.java @@ -0,0 +1,98 @@ +/* + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4242173 5017980 6576055 + * @summary Test Byte.decode method + * @author madbot + * @author Joseph D. Darcy + */ + +/** + * There are six methods in java.lang.Byte which transform strings + * into a byte or Byte value: + * + * public Byte(String s) + * public static Byte decode(String nm) + * public static byte parseByte(String s, int radix) + * public static byte parseByte(String s) + * public static Byte valueOf(String s, int radix) + * public static Byte valueOf(String s) + * + * However, of these only decode has a nontrivial implementation + * in that class. + */ +public class Decode { + + private static void check(String val, byte expected) { + byte n = (Byte.decode(val)).byteValue(); + if (n != expected) + throw new RuntimeException("Byte.decode failed. String:" + + val + " Result:" + n); + } + + private static void checkFailure(String val, String message) { + try { + byte n = (Byte.decode(val)).byteValue(); + throw new RuntimeException(message); + } catch (NumberFormatException e) { /* Okay */} + } + + public static void main(String[] args) throws Exception { + check(new String(""+Byte.MIN_VALUE), Byte.MIN_VALUE); + check(new String(""+Byte.MAX_VALUE), Byte.MAX_VALUE); + + check("10", (byte)10); + check("0x10", (byte)16); + check("0X10", (byte)16); + check("010", (byte)8); + check("#10", (byte)16); + + check("+10", (byte)10); + check("+0x10", (byte)16); + check("+0X10", (byte)16); + check("+010", (byte)8); + check("+#10", (byte)16); + + check("-10", (byte)-10); + check("-0x10", (byte)-16); + check("-0X10", (byte)-16); + check("-010", (byte)-8); + check("-#10", (byte)-16); + + check(Integer.toString((int)Byte.MIN_VALUE), Byte.MIN_VALUE); + check(Integer.toString((int)Byte.MAX_VALUE), Byte.MAX_VALUE); + + checkFailure("0x-10", "Byte.decode allows negative sign in wrong position."); + checkFailure("0x+10", "Byte.decode allows positive sign in wrong position."); + + checkFailure("+", "Raw plus sign allowed."); + checkFailure("-", "Raw minus sign allowed."); + + checkFailure(Integer.toString((int)Byte.MIN_VALUE - 1), "Out of range"); + checkFailure(Integer.toString((int)Byte.MAX_VALUE + 1), "Out of range"); + + checkFailure("", "Empty String"); + } +} diff --git a/jdk/test/java/lang/Double/BitwiseConversion.java b/jdk/test/java/lang/Double/BitwiseConversion.java new file mode 100644 index 00000000000..0d44e49fa70 --- /dev/null +++ b/jdk/test/java/lang/Double/BitwiseConversion.java @@ -0,0 +1,82 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5037596 + * @summary Verify bitwise conversion works for non-canonical NaN values + * @author Joseph D. Darcy + */ + +import static java.lang.Double.*; +import static sun.misc.DoubleConsts.*; + +public class BitwiseConversion { + static int testNanCase(long x) { + int errors = 0; + // Strip out sign and exponent bits + long y = x & SIGNIF_BIT_MASK; + + double values[] = { + longBitsToDouble(EXP_BIT_MASK | y), + longBitsToDouble(SIGN_BIT_MASK | EXP_BIT_MASK | y) + }; + + for(double value: values) { + if (!isNaN(value)) { + throw new RuntimeException("Invalid input " + y + + "yielded non-NaN" + value); + } + long converted = doubleToLongBits(value); + if (converted != 0x7ff8000000000000L) { + errors++; + System.err.format("Non-canoncial NaN bits returned: %x%n", + converted); + } + } + return errors; + } + + public static void main(String... argv) { + int errors = 0; + + for (int i = 0; i < SIGNIFICAND_WIDTH-1; i++) { + errors += testNanCase(1L< 0) + throw new RuntimeException(); + } +} diff --git a/jdk/test/java/lang/Double/Constants.java b/jdk/test/java/lang/Double/Constants.java new file mode 100644 index 00000000000..bf14e92db06 --- /dev/null +++ b/jdk/test/java/lang/Double/Constants.java @@ -0,0 +1,69 @@ +/* + * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @compile Constants.java + * @bug 4397405 4826652 + * @summary Testing constant-ness of Double.{MIN_VALUE, MAX_VALUE}, etc. + * @author Joseph D. Darcy + */ + +public class Constants { + /* + * This compile-only test is to make sure that the primitive + * public static final fields in java.lang.Double are "constant + * expressions" as defined by "The Java Language Specification, + * 2nd edition" section 15.28; a different test checks the values + * of those fields. + */ + public static void main(String[] args) throws Exception { + int i = 0; + switch (i) { + case (int)Double.NaN: // 0 + System.out.println("Double.NaN is a constant!"); + break; + case (int)Double.MIN_VALUE + 1: // 0 + 1 + System.out.println("Double.MIN_VALUE is a constant!"); + break; + case (int)Double.MIN_NORMAL + 2: // 0 + 2 + System.out.println("Double.MIN_NORMAL is a constant!"); + break; + case Double.MIN_EXPONENT: // -1022 + System.out.println("Double.MIN_EXPONENT is a constant!"); + break; + case Double.MAX_EXPONENT: // 1023 + System.out.println("Double.MAX_EXPONENT is a constant!"); + break; + case (int)Double.MAX_VALUE - 1: // Integer.MAX_VALUE - 1 + System.out.println("Double.MAX_VALUE is a constant!"); + break; + case (int)Double.POSITIVE_INFINITY: // Integer.MAX_VALUE + System.out.println("Double.POSITIVE_INFINITY is a constant!"); + break; + case (int)Double.NEGATIVE_INFINITY: // Integer.MIN_VALUE + System.out.println("Double.NEGATIVE_INFINITY is a constant!"); + break; + } + } +} diff --git a/jdk/test/java/lang/Double/Extrema.java b/jdk/test/java/lang/Double/Extrema.java new file mode 100644 index 00000000000..febb4abfed5 --- /dev/null +++ b/jdk/test/java/lang/Double/Extrema.java @@ -0,0 +1,45 @@ +/* + * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4408489 4826652 + * @summary Testing values of Double.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} + * @author Joseph D. Darcy + */ + +public class Extrema { + public static void main(String[] args) throws Exception { + if (Double.MIN_VALUE != Double.longBitsToDouble(0x1L)) + throw new RuntimeException("Double.MIN_VALUE is not equal "+ + "to longBitsToDouble(0x1L)."); + + if (Double.MIN_NORMAL != Double.longBitsToDouble(0x0010000000000000L)) + throw new RuntimeException("Double.MIN_NORMAL is not equal "+ + "to longBitsToDouble(0x0010000000000000L)."); + + if (Double.MAX_VALUE != Double.longBitsToDouble(0x7fefffffffffffffL)) + throw new RuntimeException("Double.MAX_VALUE is not equal "+ + "to longBitsToDouble(0x7fefffffffffffffL)."); + } +} diff --git a/jdk/test/java/lang/Double/NaNInfinityParsing.java b/jdk/test/java/lang/Double/NaNInfinityParsing.java new file mode 100644 index 00000000000..460d2640ae2 --- /dev/null +++ b/jdk/test/java/lang/Double/NaNInfinityParsing.java @@ -0,0 +1,169 @@ +/* + * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4428772 + * @summary Testing recognition of "NaN" and "Infinity" strings + * @author Joseph D. Darcy + */ + + +public class NaNInfinityParsing { + /* + * Regression tests for: + * 4428772 -- Establish invariant for Float & Double classes and + * their string representations + * + * Added capability for parse{Float, Double} and related methods + * to recognize "NaN" and "Infinity" strings so that + * parseDouble(toString(d)) will always return the original + * floating-point value. + */ + + static String NaNStrings[] = { + "NaN", + "+NaN", + "-NaN" + }; + + static String infinityStrings[] = { + "Infinity", + "+Infinity", + "-Infinity", + }; + + static String invalidStrings[] = { + "+", + "-", + "@", + "N", + "Na", + "Nan", + "NaNf", + "NaNd", + "NaNF", + "NaND", + "+N", + "+Na", + "+Nan", + "+NaNf", + "+NaNd", + "+NaNF", + "+NaND", + "-N", + "-Na", + "-Nan", + "-NaNf", + "-NaNd", + "-NaNF", + "-NaND", + "I", + "In", + "Inf", + "Infi", + "Infin", + "Infini", + "Infinit", + "InfinitY", + "Infinityf", + "InfinityF", + "Infinityd", + "InfinityD", + "+I", + "+In", + "+Inf", + "+Infi", + "+Infin", + "+Infini", + "+Infinit", + "+InfinitY", + "+Infinityf", + "+InfinityF", + "+Infinityd", + "+InfinityD", + "-I", + "-In", + "-Inf", + "-Infi", + "-Infin", + "-Infini", + "-Infinit", + "-InfinitY", + "-Infinityf", + "-InfinityF", + "-Infinityd", + "-InfinityD", + "NaNInfinity", + "InfinityNaN", + "nan", + "infinity" + }; + + public static void main(String [] argv) throws Exception { + int i; + double d; + + // Test valid NaN strings + for(i = 0; i < NaNStrings.length; i++) { + if(!Double.isNaN(d=Double.parseDouble(NaNStrings[i]))) { + throw new RuntimeException("NaN string ``" + NaNStrings[i] + + "'' did not parse as a NaN; returned " + + d + " instead."); + } + } + + // Test valid Infinity strings + for(i = 0; i < infinityStrings.length; i++) { + if(!Double.isInfinite(d=Double.parseDouble(infinityStrings[i]))) { + throw new RuntimeException("Infinity string ``" + + infinityStrings[i] + + "'' did not parse as infinity; returned " + + d + "instead."); + } + // check sign of result + + boolean negative = (infinityStrings[i].charAt(0) == '-'); + if(d != (negative?Double.NEGATIVE_INFINITY: + Double.POSITIVE_INFINITY)) + throw new RuntimeException("Infinity has wrong sign;" + + (negative?"positive instead of negative.": + "negative instead of positive.")); + } + + // Test almost valid strings + for(i = 0; i < invalidStrings.length; i++) { + try { + double result; + d = Double.parseDouble(invalidStrings[i]); + throw new RuntimeException("Invalid string ``" + + invalidStrings[i] + +"'' parsed as " + d + "."); + } + catch(NumberFormatException e) { + // expected + } + } + + } +} diff --git a/jdk/test/java/lang/Double/ParseDouble.java b/jdk/test/java/lang/Double/ParseDouble.java new file mode 100644 index 00000000000..54194b18977 --- /dev/null +++ b/jdk/test/java/lang/Double/ParseDouble.java @@ -0,0 +1,562 @@ +/* + * Copyright 2001-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4160406 4705734 4707389 4826774 4895911 + * @summary Test for Double.parseDouble method and acceptance regex + */ + +import java.util.regex.*; + +public class ParseDouble { + + private static void check(String val, double expected) { + double n = Double.parseDouble(val); + if (n != expected) + throw new RuntimeException("Double.parseDouble failed. String:" + + val + " Result:" + n); + } + + private static void rudimentaryTest() { + check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE); + check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE); + + check("10", (double) 10.0); + check("10.0", (double) 10.0); + check("10.01", (double) 10.01); + + check("-10", (double) -10.0); + check("-10.00", (double) -10.0); + check("-10.01", (double) -10.01); + } + + + static String badStrings[] = { + "", + "+", + "-", + "+e", + "-e", + "+e170", + "-e170", + + // Make sure intermediate white space is not deleted. + "1234 e10", + "-1234 e10", + + // Control characters in the interior of a string are not legal + "1\u0007e1", + "1e\u00071", + + // NaN and infinity can't have trailing type suffices or exponents + "NaNf", + "NaNF", + "NaNd", + "NaND", + "-NaNf", + "-NaNF", + "-NaNd", + "-NaND", + "+NaNf", + "+NaNF", + "+NaNd", + "+NaND", + "Infinityf", + "InfinityF", + "Infinityd", + "InfinityD", + "-Infinityf", + "-InfinityF", + "-Infinityd", + "-InfinityD", + "+Infinityf", + "+InfinityF", + "+Infinityd", + "+InfinityD", + + "NaNe10", + "-NaNe10", + "+NaNe10", + "Infinitye10", + "-Infinitye10", + "+Infinitye10", + + // Non-ASCII digits are not recognized + "\u0661e\u0661", // 1e1 in Arabic-Indic digits + "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits + "\u0967e\u0967", // 1e1 in Devanagari digits + + // JCK test lex03592m3 + ".", + + // JCK test lex03592m4 + "e42", + + // JCK test lex03592m5 + ".e42", + + // JCK test lex03592m6 + "d", + + // JCK test lex03592m7 + ".d", + + // JCK test lex03592m8 + "e42d", + + // JCK test lex03592m9 + ".e42d", + + // JCK test lex03593m10 + "1A01.01125e-10d", + + // JCK test lex03593m11 + "2;3.01125e-10d", + + // JCK test lex03593m12 + "1_34.01125e-10d", + + // JCK test lex03593m14 + "202..01125e-10d", + + // JCK test lex03593m15 + "202,01125e-10d", + + // JCK test lex03593m16 + "202.03b4e-10d", + + // JCK test lex03593m18 + "202.06_3e-10d", + + // JCK test lex03593m20 + "202.01125e-f0d", + + // JCK test lex03593m21 + "202.01125e_3d", + + // JCK test lex03593m22 + "202.01125e -5d", + + // JCK test lex03593m24 + "202.01125e-10r", + + // JCK test lex03593m25 + "202.01125e-10ff", + + // JCK test lex03593m26 + "1234L.01", + + // JCK test lex03593m27 + "12ee-2", + + // JCK test lex03593m28 + "12e-2.2.2", + + // JCK test lex03593m29 + "12.01e+", + + // JCK test lex03593m30 + "12.01E", + + // Bad hexadecimal-style strings + + // Two leading zeros + "00x1.0p1", + + // Must have hex specifier + "1.0p1", + "00010p1", + "deadbeefp1", + + // Need an explicit fully-formed exponent + "0x1.0p", + "0x1.0", + + // Exponent must be in decimal + "0x1.0pa", + "0x1.0pf", + + // Exponent separated by "p" + "0x1.0e22", + "0x1.0e22", + + // Need a signifcand + "0xp22" + }; + + static String goodStrings[] = { + "NaN", + "+NaN", + "-NaN", + "Infinity", + "+Infinity", + "-Infinity", + "1.1e-23f", + ".1e-23f", + "1e-23", + "1f", + "0", + "-0", + "+0", + "00", + "00", + "-00", + "+00", + "0000000000", + "-0000000000", + "+0000000000", + "1", + "2", + "1234", + "-1234", + "+1234", + "2147483647", // Integer.MAX_VALUE + "2147483648", + "-2147483648", // Integer.MIN_VALUE + "-2147483649", + + "16777215", + "16777216", // 2^24 + "16777217", + + "-16777215", + "-16777216", // -2^24 + "-16777217", + + "9007199254740991", + "9007199254740992", // 2^53 + "9007199254740993", + + "-9007199254740991", + "-9007199254740992", // -2^53 + "-9007199254740993", + + "9223372036854775807", + "9223372036854775808", // Long.MAX_VALUE + "9223372036854775809", + + "-9223372036854775808", + "-9223372036854775809", // Long.MIN_VALUE + "-9223372036854775810", + + // Culled from JCK test lex03591m1 + "54.07140d", + "7.01e-324d", + "2147483647.01d", + "1.2147483647f", + "000000000000000000000000001.F", + "1.00000000000000000000000000e-2F", + + // Culled from JCK test lex03592m2 + "2.", + ".0909", + "122112217090.0", + "7090e-5", + "2.E-20", + ".0909e42", + "122112217090.0E+100", + "7090f", + "2.F", + ".0909d", + "122112217090.0D", + "7090e-5f", + "2.E-20F", + ".0909e42d", + "122112217090.0E+100D", + + // Culled from JCK test lex03594m31 -- unicode escapes + "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D", + "1290873\u002E12301e100", + "1.1E-10\u0066", + + // Culled from JCK test lex03595m1 + "0.0E-10", + "1E10", + + // Culled from JCK test lex03691m1 + "0.f", + "1f", + "0.F", + "1F", + "0.12d", + "1e-0d", + "12.e+1D", + "0e-0D", + "12.e+01", + "1e-01", + + // Good hex strings + // Vary capitalization of separators. + + "0x1p1", + "0X1p1", + "0x1P1", + "0X1P1", + "0x1p1f", + "0X1p1f", + "0x1P1f", + "0X1P1f", + "0x1p1F", + "0X1p1F", + "0x1P1F", + "0X1P1F", + "0x1p1d", + "0X1p1d", + "0x1P1d", + "0X1P1d", + "0x1p1D", + "0X1p1D", + "0x1P1D", + "0X1P1D", + + "-0x1p1", + "-0X1p1", + "-0x1P1", + "-0X1P1", + "-0x1p1f", + "-0X1p1f", + "-0x1P1f", + "-0X1P1f", + "-0x1p1F", + "-0X1p1F", + "-0x1P1F", + "-0X1P1F", + "-0x1p1d", + "-0X1p1d", + "-0x1P1d", + "-0X1P1d", + "-0x1p1D", + "-0X1p1D", + "-0x1P1D", + "-0X1P1D", + + "0x1p-1", + "0X1p-1", + "0x1P-1", + "0X1P-1", + "0x1p-1f", + "0X1p-1f", + "0x1P-1f", + "0X1P-1f", + "0x1p-1F", + "0X1p-1F", + "0x1P-1F", + "0X1P-1F", + "0x1p-1d", + "0X1p-1d", + "0x1P-1d", + "0X1P-1d", + "0x1p-1D", + "0X1p-1D", + "0x1P-1D", + "0X1P-1D", + + "-0x1p-1", + "-0X1p-1", + "-0x1P-1", + "-0X1P-1", + "-0x1p-1f", + "-0X1p-1f", + "-0x1P-1f", + "-0X1P-1f", + "-0x1p-1F", + "-0X1p-1F", + "-0x1P-1F", + "-0X1P-1F", + "-0x1p-1d", + "-0X1p-1d", + "-0x1P-1d", + "-0X1P-1d", + "-0x1p-1D", + "-0X1p-1D", + "-0x1P-1D", + "-0X1P-1D", + + + // Try different significand combinations + "0xap1", + "0xbp1", + "0xcp1", + "0xdp1", + "0xep1", + "0xfp1", + + "0x1p1", + "0x.1p1", + "0x1.1p1", + + "0x001p23", + "0x00.1p1", + "0x001.1p1", + + "0x100p1", + "0x.100p1", + "0x1.100p1", + + "0x00100p1", + "0x00.100p1", + "0x001.100p1" + }; + + static String paddedBadStrings[]; + static String paddedGoodStrings[]; + static { + String pad = " \t\n\r\f\u0001\u000b\u001f"; + paddedBadStrings = new String[badStrings.length]; + for(int i = 0 ; i < badStrings.length; i++) + paddedBadStrings[i] = pad + badStrings[i] + pad; + + paddedGoodStrings = new String[goodStrings.length]; + for(int i = 0 ; i < goodStrings.length; i++) + paddedGoodStrings[i] = pad + goodStrings[i] + pad; + + } + + + /* + * Throws an exception if Input is + * exceptionalInput and {@link Double.parseDouble + * parseDouble} does not throw an exception or if + * Input is not exceptionalInput and + * parseDouble throws an exception. This method does + * not attempt to test whether the string is converted to the + * proper value; just whether the input is accepted appropriately + * or not. + */ + private static void testParsing(String [] input, + boolean exceptionalInput) { + for(int i = 0; i < input.length; i++) { + double d; + + try { + d = Double.parseDouble(input[i]); + } + catch (NumberFormatException e) { + if (! exceptionalInput) { + throw new RuntimeException("Double.parseDouble rejected " + + "good string `" + input[i] + + "'."); + } + break; + } + if (exceptionalInput) { + throw new RuntimeException("Double.parseDouble accepted " + + "bad string `" + input[i] + + "'."); + } + } + } + + /* + * Throws an exception if Input is + * exceptionalInput and the regular expression + * matches one of the strings or if Input is not + * exceptionalInput and the regular expression fails + * to match an input string. + */ + private static void testRegex(String [] input, boolean exceptionalInput) { + /* + * The regex below is taken from the JavaDoc for + * Double.valueOf. + */ + + final String Digits = "(\\p{Digit}+)"; + final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + final String Exp = "[eE][+-]?"+Digits; + final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?))|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + Pattern fpPattern = Pattern.compile(fpRegex); + + for(int i = 0; i < input.length; i++) { + Matcher m = fpPattern.matcher(input[i]); + if (m.matches() != ! exceptionalInput) { + throw new RuntimeException("Regular expression " + + (exceptionalInput? + "accepted bad": + "rejected good") + + " string `" + + input[i] + "'."); + } + } + + } + + public static void main(String[] args) throws Exception { + rudimentaryTest(); + + testParsing(goodStrings, false); + testParsing(paddedGoodStrings, false); + testParsing(badStrings, true); + testParsing(paddedBadStrings, true); + + testRegex(goodStrings, false); + testRegex(paddedGoodStrings, false); + testRegex(badStrings, true); + testRegex(paddedBadStrings, true); + } +} diff --git a/jdk/test/java/lang/Double/ParseHexFloatingPoint.java b/jdk/test/java/lang/Double/ParseHexFloatingPoint.java new file mode 100644 index 00000000000..d2897f9f962 --- /dev/null +++ b/jdk/test/java/lang/Double/ParseHexFloatingPoint.java @@ -0,0 +1,448 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4826774 + * @summary Numerical tests for hexadecimal inputs to parseDouble, parseFloat + * @author Joseph D. Darcy + */ + + +import java.util.regex.*; +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class ParseHexFloatingPoint { + private ParseHexFloatingPoint(){} + + public static final double infinityD = Double.POSITIVE_INFINITY; + public static final double NaND = Double.NaN; + + static int test(String testName, String input, + double result, double expected) { + int failures =0; + + if (Double.compare(result, expected) != 0 ) { + System.err.println("Failure for " + testName + + ": For input " + input + + " expected " + expected + + " got " + result + "."); + } + + return failures; + } + + static int testCase(String input, double expected) { + int failures =0; + + + // Try different combination of letter components + input = input.toLowerCase(java.util.Locale.US); + + String [] suffices = {"", "f", "F", "d", "D"}; + String [] signs = {"", "-", "+"}; + + for(int i = 0; i < 2; i++) { + String s1 = input; + if(i == 1) + s1 = s1.replace('x', 'X'); + + for(int j = 0; j < 2; j++) { + String s2 = s1; + if(j == 1) + s2 = s2.replace('p', 'P'); + + for(int k = 0; k < 2; k++) { + String s3 = s2; + if(k == 1) + s3 = upperCaseHex(s3); + + + for(int m = 0; m < suffices.length; m++) { + String s4 = s3 + suffices[m]; + + + for(int n = 0; n < signs.length; n++) { + String s5 = signs[n] + s4; + + double result = Double.parseDouble(s5); + failures += test("Double.parseDouble", + s5, result, (signs[n].equals("-") ? + -expected: + expected)); + } + } + } + } + } + + return failures; + } + + static String upperCaseHex(String s) { + return s.replace('a', 'A').replace('b', 'B').replace('c', 'C'). + replace('d', 'D').replace('e','E').replace('f', 'F'); + } + + /* + * Test easy and tricky double rounding cases. + */ + static int doubleTests() { + + /* + * A String, double pair + */ + class PairSD { + public String s; + public double d; + PairSD(String s, double d) { + this.s = s; + this.d = d; + } + } + int failures = 0; + + + + // Hex strings that convert to three; test basic functionality + // of significand and exponent shift adjusts along with the + // no-op of adding leading zeros. These cases don't exercise + // the rounding code. + String leadingZeros = "0x0000000000000000000"; + String [] threeTests = { + "0x.003p12", + "0x.006p11", + "0x.00cp10", + "0x.018p9", + + "0x.3p4", + "0x.6p3", + "0x.cp2", + "0x1.8p1", + + "0x3p0", + "0x6.0p-1", + "0xc.0p-2", + "0x18.0p-3", + + "0x3000000p-24", + "0x3.0p0", + "0x3.000000p0", + }; + for(int i=0; i < threeTests.length; i++) { + String input = threeTests[i]; + failures += testCase(input, 3.0); + + input.replaceFirst("^0x", leadingZeros); + failures += testCase(input, 3.0); + } + + long bigExponents [] = { + 2*DoubleConsts.MAX_EXPONENT, + 2*DoubleConsts.MIN_EXPONENT, + + (long)Integer.MAX_VALUE-1, + (long)Integer.MAX_VALUE, + (long)Integer.MAX_VALUE+1, + + (long)Integer.MIN_VALUE-1, + (long)Integer.MIN_VALUE, + (long)Integer.MIN_VALUE+1, + + Long.MAX_VALUE-1, + Long.MAX_VALUE, + + Long.MIN_VALUE+1, + Long.MIN_VALUE, + }; + + // Test zero significand with large exponents. + for(int i = 0; i < bigExponents.length; i++) { + failures += testCase("0x0.0p"+Long.toString(bigExponents[i]) , 0.0); + } + + // Test nonzero significand with large exponents. + for(int i = 0; i < bigExponents.length; i++) { + long exponent = bigExponents[i]; + failures += testCase("0x10000.0p"+Long.toString(exponent) , + (exponent <0?0.0:infinityD)); + } + + // Test significands with different lengths and bit patterns. + { + long signif = 0; + for(int i = 1; i <= 0xe; i++) { + signif = (signif <<4) | (long)i; + failures += testCase("0x"+Long.toHexString(signif)+"p0", signif); + } + } + + PairSD [] testCases = { + new PairSD("0x0.0p0", 0.0/16.0), + new PairSD("0x0.1p0", 1.0/16.0), + new PairSD("0x0.2p0", 2.0/16.0), + new PairSD("0x0.3p0", 3.0/16.0), + new PairSD("0x0.4p0", 4.0/16.0), + new PairSD("0x0.5p0", 5.0/16.0), + new PairSD("0x0.6p0", 6.0/16.0), + new PairSD("0x0.7p0", 7.0/16.0), + new PairSD("0x0.8p0", 8.0/16.0), + new PairSD("0x0.9p0", 9.0/16.0), + new PairSD("0x0.ap0", 10.0/16.0), + new PairSD("0x0.bp0", 11.0/16.0), + new PairSD("0x0.cp0", 12.0/16.0), + new PairSD("0x0.dp0", 13.0/16.0), + new PairSD("0x0.ep0", 14.0/16.0), + new PairSD("0x0.fp0", 15.0/16.0), + + // Half-way case between zero and MIN_VALUE rounds down to + // zero + new PairSD("0x1.0p-1075", 0.0), + + // Slighly more than half-way case between zero and + // MIN_VALUES rounds up to zero. + new PairSD("0x1.1p-1075", Double.MIN_VALUE), + new PairSD("0x1.000000000001p-1075", Double.MIN_VALUE), + new PairSD("0x1.000000000000001p-1075", Double.MIN_VALUE), + + // More subnormal rounding tests + new PairSD("0x0.fffffffffffff7fffffp-1022", FpUtils.nextDown(DoubleConsts.MIN_NORMAL)), + new PairSD("0x0.fffffffffffff8p-1022", DoubleConsts.MIN_NORMAL), + new PairSD("0x0.fffffffffffff800000001p-1022",DoubleConsts.MIN_NORMAL), + new PairSD("0x0.fffffffffffff80000000000000001p-1022",DoubleConsts.MIN_NORMAL), + new PairSD("0x1.0p-1022", DoubleConsts.MIN_NORMAL), + + + // Large value and overflow rounding tests + new PairSD("0x1.fffffffffffffp1023", Double.MAX_VALUE), + new PairSD("0x1.fffffffffffff0000000p1023", Double.MAX_VALUE), + new PairSD("0x1.fffffffffffff4p1023", Double.MAX_VALUE), + new PairSD("0x1.fffffffffffff7fffffp1023", Double.MAX_VALUE), + new PairSD("0x1.fffffffffffff8p1023", infinityD), + new PairSD("0x1.fffffffffffff8000001p1023", infinityD), + + new PairSD("0x1.ffffffffffffep1023", FpUtils.nextDown(Double.MAX_VALUE)), + new PairSD("0x1.ffffffffffffe0000p1023", FpUtils.nextDown(Double.MAX_VALUE)), + new PairSD("0x1.ffffffffffffe8p1023", FpUtils.nextDown(Double.MAX_VALUE)), + new PairSD("0x1.ffffffffffffe7p1023", FpUtils.nextDown(Double.MAX_VALUE)), + new PairSD("0x1.ffffffffffffeffffffp1023", Double.MAX_VALUE), + new PairSD("0x1.ffffffffffffe8000001p1023", Double.MAX_VALUE), + }; + + for (int i = 0; i < testCases.length; i++) { + failures += testCase(testCases[i].s,testCases[i].d); + } + + failures += significandAlignmentTests(); + + { + java.util.Random rand = new java.util.Random(); + // Consistency check; double => hexadecimal => double + // preserves the original value. + for(int i = 0; i < 1000; i++) { + double d = rand.nextDouble(); + failures += testCase(Double.toHexString(d), d); + } + } + + return failures; + } + + /* + * Verify rounding works the same regardless of how the + * significand is aligned on input. A useful extension could be + * to have this sort of test for strings near the overflow + * threshold. + */ + static int significandAlignmentTests() { + int failures = 0; + // baseSignif * 2^baseExp = nextDown(2.0) + long [] baseSignifs = { + 0x1ffffffffffffe00L, + 0x1fffffffffffff00L + }; + + double [] answers = { + FpUtils.nextDown(FpUtils.nextDown(2.0)), + FpUtils.nextDown(2.0), + 2.0 + }; + + int baseExp = -60; + int count = 0; + for(int i = 0; i < 2; i++) { + for(long j = 0; j <= 0xfL; j++) { + for(long k = 0; k <= 8; k+= 4) { // k = {0, 4, 8} + long base = baseSignifs[i]; + long testValue = base | (j<<4) | k; + + int offset = 0; + // Calculate when significand should be incremented + // see table 4.7 in Koren book + + if ((base & 0x100L) == 0L ) { // lsb is 0 + if ( (j >= 8L) && // round is 1 + ((j & 0x7L) != 0 || k != 0 ) ) // sticky is 1 + offset = 1; + } + else { // lsb is 1 + if (j >= 8L) // round is 1 + offset = 1; + } + + double expected = answers[i+offset]; + + for(int m = -2; m <= 3; m++) { + count ++; + + // Form equal value string and evaluate it + String s = "0x" + + Long.toHexString((m >=0) ?(testValue<>(-m))) + + "p" + (baseExp - m); + + failures += testCase(s, expected); + } + } + } + } + + return failures; + } + + + /* + * Test tricky float rounding cases. The code which + * reads in a hex string converts the string to a double value. + * If a float value is needed, the double value is cast to float. + * However, the cast be itself not always guaranteed to return the + * right result since: + * + * 1. hex string => double can discard a sticky bit which would + * influence a direct hex string => float conversion. + * + * 2. hex string => double => float can have a rounding to double + * precision which results in a larger float value while a direct + * hex string => float conversion would not round up. + * + * This method includes tests of the latter two possibilities. + */ + static int floatTests(){ + int failures = 0; + + /* + * A String, float pair + */ + class PairSD { + public String s; + public float f; + PairSD(String s, float f) { + this.s = s; + this.f = f; + } + } + + String [][] roundingTestCases = { + // Target float value hard rouding version + + {"0x1.000000p0", "0x1.0000000000001p0"}, + + // Try some values that should round up to nextUp(1.0f) + {"0x1.000002p0", "0x1.0000010000001p0"}, + {"0x1.000002p0", "0x1.00000100000008p0"}, + {"0x1.000002p0", "0x1.0000010000000fp0"}, + {"0x1.000002p0", "0x1.00000100000001p0"}, + {"0x1.000002p0", "0x1.00000100000000000000000000000000000000001p0"}, + {"0x1.000002p0", "0x1.0000010000000fp0"}, + + // Potential double rounding cases + {"0x1.000002p0", "0x1.000002fffffffp0"}, + {"0x1.000002p0", "0x1.000002fffffff8p0"}, + {"0x1.000002p0", "0x1.000002ffffffffp0"}, + + {"0x1.000002p0", "0x1.000002ffff0ffp0"}, + {"0x1.000002p0", "0x1.000002ffff0ff8p0"}, + {"0x1.000002p0", "0x1.000002ffff0fffp0"}, + + + {"0x1.000000p0", "0x1.000000fffffffp0"}, + {"0x1.000000p0", "0x1.000000fffffff8p0"}, + {"0x1.000000p0", "0x1.000000ffffffffp0"}, + + {"0x1.000000p0", "0x1.000000ffffffep0"}, + {"0x1.000000p0", "0x1.000000ffffffe8p0"}, + {"0x1.000000p0", "0x1.000000ffffffefp0"}, + + // Float subnormal cases + {"0x0.000002p-126", "0x0.0000010000001p-126"}, + {"0x0.000002p-126", "0x0.00000100000000000001p-126"}, + + {"0x0.000006p-126", "0x0.0000050000001p-126"}, + {"0x0.000006p-126", "0x0.00000500000000000001p-126"}, + + {"0x0.0p-149", "0x0.7ffffffffffffffp-149"}, + {"0x1.0p-148", "0x1.3ffffffffffffffp-148"}, + {"0x1.cp-147", "0x1.bffffffffffffffp-147"}, + + {"0x1.fffffcp-127", "0x1.fffffdffffffffp-127"}, + }; + + String [] signs = {"", "-"}; + + for(int i = 0; i < roundingTestCases.length; i++) { + for(int j = 0; j < signs.length; j++) { + String expectedIn = signs[j]+roundingTestCases[i][0]; + String resultIn = signs[j]+roundingTestCases[i][1]; + + float expected = Float.parseFloat(expectedIn); + float result = Float.parseFloat(resultIn); + + if( Float.compare(expected, result) != 0) { + failures += 1; + System.err.println("" + (i+1)); + System.err.println("Expected = " + Float.toHexString(expected)); + System.err.println("Rounded = " + Float.toHexString(result)); + System.err.println("Double = " + Double.toHexString(Double.parseDouble(resultIn))); + System.err.println("Input = " + resultIn); + System.err.println(""); + } + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += doubleTests(); + failures += floatTests(); + + if (failures != 0) { + throw new RuntimeException("" + failures + " failures while " + + "testing hexadecimal floating-point " + + "parsing."); + } + } + +} diff --git a/jdk/test/java/lang/Double/ToHexString.java b/jdk/test/java/lang/Double/ToHexString.java new file mode 100644 index 00000000000..90180340645 --- /dev/null +++ b/jdk/test/java/lang/Double/ToHexString.java @@ -0,0 +1,252 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4826774 4926547 + * @summary Tests for {Float, Double}.toHexString methods + * @author Joseph D. Darcy + */ + +import java.util.regex.*; +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class ToHexString { + private ToHexString() {} + + /* + * Given a double value, create a hexadecimal floating-point + * string via an intermediate long hex string. + */ + static String doubleToHexString(double d) { + return hexLongStringtoHexDoubleString(Long.toHexString(Double.doubleToLongBits(d))); + } + + /* + * Transform the hexadecimal long output into the equivalent + * hexadecimal double value. + */ + static String hexLongStringtoHexDoubleString(String transString) { + transString = transString.toLowerCase(); + + String zeros = ""; + StringBuffer result = new StringBuffer(24); + + for(int i = 0; i < (16 - transString.length()); i++, zeros += "0"); + transString = zeros + transString; + + // assert transString.length == 16; + + char topChar; + // Extract sign + if((topChar=transString.charAt(0)) >= '8' ) {// 8, 9, a, A, b, B, ... + result.append("-"); + // clear sign bit + transString = + Character.toString(Character.forDigit(Character.digit(topChar, 16) - 8, 16)) + + transString.substring(1,16); + } + + // check for NaN and infinity + String signifString = transString.substring(3,16); + + if( transString.substring(0,3).equals("7ff") ) { + if(signifString.equals("0000000000000")) { + result.append("Infinity"); + } + else + result.append("NaN"); + } + else { // finite value + // Extract exponent + int exponent = Integer.parseInt(transString.substring(0,3), 16) - + DoubleConsts.EXP_BIAS; + result.append("0x"); + + if (exponent == DoubleConsts.MIN_EXPONENT - 1) { // zero or subnormal + if(signifString.equals("0000000000000")) { + result.append("0.0p0"); + } + else { + result.append("0." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") + + "p-1022"); + } + } + else { // normal value + result.append("1." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") + + "p" + exponent); + } + } + return result.toString(); + } + + public static int toHexStringTests() { + int failures = 0; + String [][] testCases1 = { + {"Infinity", "Infinity"}, + {"-Infinity", "-Infinity"}, + {"NaN", "NaN"}, + {"-NaN", "NaN"}, + {"0.0", "0x0.0p0"}, + {"-0.0", "-0x0.0p0"}, + {"1.0", "0x1.0p0"}, + {"-1.0", "-0x1.0p0"}, + {"2.0", "0x1.0p1"}, + {"3.0", "0x1.8p1"}, + {"0.5", "0x1.0p-1"}, + {"0.25", "0x1.0p-2"}, + {"1.7976931348623157e+308", "0x1.fffffffffffffp1023"}, // MAX_VALUE + {"2.2250738585072014E-308", "0x1.0p-1022"}, // MIN_NORMAL + {"2.225073858507201E-308", "0x0.fffffffffffffp-1022"}, // MAX_SUBNORMAL + {"4.9e-324", "0x0.0000000000001p-1022"} // MIN_VALUE + }; + + // Compare decimal string -> double -> hex string to hex string + for (int i = 0; i < testCases1.length; i++) { + String result; + if(! (result=Double.toHexString(Double.parseDouble(testCases1[i][0]))). + equals(testCases1[i][1])) { + failures ++; + System.err.println("For floating-point string " + testCases1[i][0] + + ", expected hex output " + testCases1[i][1] + ", got " + result +"."); + } + } + + + // Except for float subnormals, the output for numerically + // equal float and double values should be the same. + // Therefore, we will explicitly test float subnormal values. + String [][] floatTestCases = { + {"Infinity", "Infinity"}, + {"-Infinity", "-Infinity"}, + {"NaN", "NaN"}, + {"-NaN", "NaN"}, + {"0.0", "0x0.0p0"}, + {"-0.0", "-0x0.0p0"}, + {"1.0", "0x1.0p0"}, + {"-1.0", "-0x1.0p0"}, + {"2.0", "0x1.0p1"}, + {"3.0", "0x1.8p1"}, + {"0.5", "0x1.0p-1"}, + {"0.25", "0x1.0p-2"}, + {"3.4028235e+38f", "0x1.fffffep127"}, // MAX_VALUE + {"1.17549435E-38f", "0x1.0p-126"}, // MIN_NORMAL + {"1.1754942E-38", "0x0.fffffep-126"}, // MAX_SUBNORMAL + {"1.4e-45f", "0x0.000002p-126"} // MIN_VALUE + }; + // Compare decimal string -> double -> hex string to hex string + for (int i = 0; i < floatTestCases.length; i++) { + String result; + if(! (result=Float.toHexString(Float.parseFloat(floatTestCases[i][0]))). + equals(floatTestCases[i][1])) { + failures++; + System.err.println("For floating-point string " + floatTestCases[i][0] + + ", expected hex output\n" + floatTestCases[i][1] + ", got\n" + result +"."); + } + } + + // Particular floating-point values and hex equivalents, mostly + // taken from fdlibm source. + String [][] testCases2 = { + {"+0.0", "0000000000000000"}, + {"-0.0", "8000000000000000"}, + {"+4.9e-324", "0000000000000001"}, + {"-4.9e-324", "8000000000000001"}, + + // fdlibm k_sin.c + {"+5.00000000000000000000e-01", "3FE0000000000000"}, + {"-1.66666666666666324348e-01", "BFC5555555555549"}, + {"+8.33333333332248946124e-03", "3F8111111110F8A6"}, + {"-1.98412698298579493134e-04", "BF2A01A019C161D5"}, + {"+2.75573137070700676789e-06", "3EC71DE357B1FE7D"}, + {"-2.50507602534068634195e-08", "BE5AE5E68A2B9CEB"}, + {"+1.58969099521155010221e-10", "3DE5D93A5ACFD57C"}, + + // fdlibm k_cos.c + {"+4.16666666666666019037e-02", "3FA555555555554C"}, + {"-1.38888888888741095749e-03", "BF56C16C16C15177"}, + {"+2.48015872894767294178e-05", "3EFA01A019CB1590"}, + {"-2.75573143513906633035e-07", "BE927E4F809C52AD"}, + {"+2.08757232129817482790e-09", "3E21EE9EBDB4B1C4"}, + {"-1.13596475577881948265e-11", "BDA8FAE9BE8838D4"}, + + // fdlibm e_rempio.c + {"1.67772160000000000000e+07", "4170000000000000"}, + {"6.36619772367581382433e-01", "3FE45F306DC9C883"}, + {"1.57079632673412561417e+00", "3FF921FB54400000"}, + {"6.07710050650619224932e-11", "3DD0B4611A626331"}, + {"6.07710050630396597660e-11", "3DD0B4611A600000"}, + {"2.02226624879595063154e-21", "3BA3198A2E037073"}, + {"2.02226624871116645580e-21", "3BA3198A2E000000"}, + {"8.47842766036889956997e-32", "397B839A252049C1"}, + + + // fdlibm s_cbrt.c + {"+5.42857142857142815906e-01", "3FE15F15F15F15F1"}, + {"-7.05306122448979611050e-01", "BFE691DE2532C834"}, + {"+1.41428571428571436819e+00", "3FF6A0EA0EA0EA0F"}, + {"+1.60714285714285720630e+00", "3FF9B6DB6DB6DB6E"}, + {"+3.57142857142857150787e-01", "3FD6DB6DB6DB6DB7"}, + }; + + // Compare decimal string -> double -> hex string to + // long hex string -> double hex string + for (int i = 0; i < testCases2.length; i++) { + String result; + String expected; + if(! (result=Double.toHexString(Double.parseDouble(testCases2[i][0]))). + equals( expected=hexLongStringtoHexDoubleString(testCases2[i][1]) )) { + failures ++; + System.err.println("For floating-point string " + testCases2[i][0] + + ", expected hex output " + expected + ", got " + result +"."); + } + } + + // Test random double values; + // compare double -> Double.toHexString with local doubleToHexString + java.util.Random rand = new java.util.Random(0); + for (int i = 0; i < 1000; i++) { + String result; + String expected; + double d = rand.nextDouble(); + if(! (expected=doubleToHexString(d)).equals(result=Double.toHexString(d)) ) { + failures ++; + System.err.println("For floating-point value " + d + + ", expected hex output " + expected + ", got " + result +"."); + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures = toHexStringTests(); + + if (failures != 0) { + throw new RuntimeException("" + failures + " failures while testing Double.toHexString"); + } + } +} diff --git a/jdk/test/java/lang/Enum/ValueOf.java b/jdk/test/java/lang/Enum/ValueOf.java new file mode 100644 index 00000000000..6af4a9fd8e9 --- /dev/null +++ b/jdk/test/java/lang/Enum/ValueOf.java @@ -0,0 +1,224 @@ +/* + * Copyright 2004-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4984908 5058132 6653154 + * @summary Basic test of valueOf(String) + * @author Josh Bloch + * + * @compile ValueOf.java + * @run main ValueOf + */ + +import java.util.*; +import java.lang.reflect.Method; + +public class ValueOf { + static Random rnd = new Random(); + + public static void main(String[] args) throws Exception { + test(Silly0.class); + test(Silly1.class); + test(Silly31.class); + test(Silly32.class); + test(Silly33.class); + test(Silly63.class); + test(Silly64.class); + test(Silly65.class); + test(Silly127.class); + test(Silly128.class); + test(Silly129.class); + test(Silly500.class); + test(Specialized.class); + + testMissingException(); + } + + static > void test(Class enumClass) throws Exception { + Set s = EnumSet.allOf(enumClass); + test(enumClass, s); + + // Delete half the elements from set at random + for (Iterator i = s.iterator(); i.hasNext(); ) { + i.next(); + if (rnd.nextBoolean()) + i.remove(); + } + + test(enumClass, s); + } + + static > void test(Class enumClass, Set s) + throws Exception + { + Method valueOf = enumClass.getDeclaredMethod("valueOf", String.class); + Set copy = EnumSet.noneOf(enumClass); + for (T e : s) + copy.add((T) valueOf.invoke(null, e.name())); + if (!copy.equals(s)) + throw new Exception(copy + " != " + s); + } + + static void testMissingException() { + try { + Enum.valueOf(Specialized.class, "BAZ"); + throw new RuntimeException("Expected IllegalArgumentException not thrown."); + } catch(IllegalArgumentException iae) { + String message = iae.getMessage(); + if (! "No enum constant ValueOf.Specialized.BAZ".equals(message)) + throw new RuntimeException("Unexpected detail message: ``" + message + "''."); + } + } + + enum Silly0 { }; + + enum Silly1 { e1 } + + enum Silly31 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30 + } + + enum Silly32 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31 + } + + enum Silly33 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32 + } + + enum Silly63 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62 + } + + enum Silly64 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63 + } + + enum Silly65 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63, e64 + } + + enum Silly127 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, + e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, + e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, + e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, + e118, e119, e120, e121, e122, e123, e124, e125, e126 + } + + enum Silly128 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, + e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, + e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, + e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, + e118, e119, e120, e121, e122, e123, e124, e125, e126, e127 + } + + enum Silly129 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, + e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, + e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, + e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, + e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128 + } + + enum Silly500 { + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, + e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, + e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, + e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, + e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76, + e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91, + e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105, + e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117, + e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129, + e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141, + e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153, + e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165, + e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177, + e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189, + e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201, + e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213, + e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225, + e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237, + e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249, + e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260, e261, + e262, e263, e264, e265, e266, e267, e268, e269, e270, e271, e272, e273, + e274, e275, e276, e277, e278, e279, e280, e281, e282, e283, e284, e285, + e286, e287, e288, e289, e290, e291, e292, e293, e294, e295, e296, e297, + e298, e299, e300, e301, e302, e303, e304, e305, e306, e307, e308, e309, + e310, e311, e312, e313, e314, e315, e316, e317, e318, e319, e320, e321, + e322, e323, e324, e325, e326, e327, e328, e329, e330, e331, e332, e333, + e334, e335, e336, e337, e338, e339, e340, e341, e342, e343, e344, e345, + e346, e347, e348, e349, e350, e351, e352, e353, e354, e355, e356, e357, + e358, e359, e360, e361, e362, e363, e364, e365, e366, e367, e368, e369, + e370, e371, e372, e373, e374, e375, e376, e377, e378, e379, e380, e381, + e382, e383, e384, e385, e386, e387, e388, e389, e390, e391, e392, e393, + e394, e395, e396, e397, e398, e399, e400, e401, e402, e403, e404, e405, + e406, e407, e408, e409, e410, e411, e412, e413, e414, e415, e416, e417, + e418, e419, e420, e421, e422, e423, e424, e425, e426, e427, e428, e429, + e430, e431, e432, e433, e434, e435, e436, e437, e438, e439, e440, e441, + e442, e443, e444, e445, e446, e447, e448, e449, e450, e451, e452, e453, + e454, e455, e456, e457, e458, e459, e460, e461, e462, e463, e464, e465, + e466, e467, e468, e469, e470, e471, e472, e473, e474, e475, e476, e477, + e478, e479, e480, e481, e482, e483, e484, e485, e486, e487, e488, e489, + e490, e491, e492, e493, e494, e495, e496, e497, e498, e499 + } + + enum Specialized { + FOO { + public void foo() {} + }; + abstract public void foo(); + }; + +} diff --git a/jdk/test/java/lang/Float/BitwiseConversion.java b/jdk/test/java/lang/Float/BitwiseConversion.java new file mode 100644 index 00000000000..7c3afb5cc55 --- /dev/null +++ b/jdk/test/java/lang/Float/BitwiseConversion.java @@ -0,0 +1,82 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5037596 + * @summary Verify bitwise conversion works for non-canonical NaN values + * @author Joseph D. Darcy + */ + +import static java.lang.Float.*; +import static sun.misc.FloatConsts.*; + +public class BitwiseConversion { + static int testNanCase(int x) { + int errors = 0; + // Strip out sign and exponent bits + int y = x & SIGNIF_BIT_MASK; + + float values[] = { + intBitsToFloat(EXP_BIT_MASK | y), + intBitsToFloat(SIGN_BIT_MASK | EXP_BIT_MASK | y) + }; + + for(float value: values) { + if (!isNaN(value)) { + throw new RuntimeException("Invalid input " + y + + "yielded non-NaN" + value); + } + int converted = floatToIntBits(value); + if (converted != 0x7fc00000) { + errors++; + System.err.format("Non-canoncial NaN bits returned: %x%n", + converted); + } + } + return errors; + } + + public static void main(String... argv) { + int errors = 0; + + for (int i = 0; i < SIGNIFICAND_WIDTH-1; i++) { + errors += testNanCase(1< 0) + throw new RuntimeException(); + } +} diff --git a/jdk/test/java/lang/Float/Constants.java b/jdk/test/java/lang/Float/Constants.java new file mode 100644 index 00000000000..a73a3b3901c --- /dev/null +++ b/jdk/test/java/lang/Float/Constants.java @@ -0,0 +1,69 @@ +/* + * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @compile Constants.java + * @bug 4397405 4826652 + * @summary Testing constant-ness of Float.{MIN_VALUE, MAX_VALUE}, etc. + * @author Joseph D. Darcy + */ + +public class Constants { + /* + * This compile-only test is to make sure that the primitive + * public static final fields in java.lang.Float are "constant + * expressions" as defined by "The Java Language Specification, + * 2nd edition" section 15.28; a different test checks the values + * of those fields. + */ + public static void main(String[] args) throws Exception { + int i = 0; + switch (i) { + case (int)Float.NaN: // 0 + System.out.println("Float.NaN is a constant!"); + break; + case (int)Float.MIN_VALUE + 1: // 0 + 1 + System.out.println("Float.MIN_VALUE is a constant!"); + break; + case (int)Float.MIN_NORMAL + 2: // 0 + 2 + System.out.println("Float.MIN_NORMAL is a constant!"); + break; + case Float.MIN_EXPONENT: // -126 + System.out.println("Float.MIN_EXPONENT is a constant!"); + break; + case Float.MAX_EXPONENT: // 127 + System.out.println("Float.MAX_EXPONENT is a constant!"); + break; + case (int)Float.MAX_VALUE - 1: // Integer.MAX_VALUE - 1 + System.out.println("Float.MAX_VALUE is a constant!"); + break; + case (int)Float.POSITIVE_INFINITY: // Integer.MAX_VALUE + System.out.println("Float.POSITIVE_INFINITY is a constant!"); + break; + case (int)Float.NEGATIVE_INFINITY: // Integer.MIN_VALUE + System.out.println("Float.NEGATIVE_INFINITY is a constant!"); + break; + } + } +} diff --git a/jdk/test/java/lang/Float/Extrema.java b/jdk/test/java/lang/Float/Extrema.java new file mode 100644 index 00000000000..397b69bfa9a --- /dev/null +++ b/jdk/test/java/lang/Float/Extrema.java @@ -0,0 +1,45 @@ +/* + * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4408489 4826652 + * @summary Testing values of Float.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} + * @author Joseph D. Darcy + */ + +public class Extrema { + public static void main(String[] args) throws Exception { + if (Float.MIN_VALUE != Float.intBitsToFloat(0x1)) + throw new RuntimeException("Float.MIN_VALUE is not equal "+ + "to intBitsToFloat(0x1)."); + + if (Float.MIN_NORMAL != Float.intBitsToFloat(0x00800000)) + throw new RuntimeException("Float.MIN_NORMAL is not equal "+ + "to intBitsToFloat(0x00800000)."); + + if (Float.MAX_VALUE != Float.intBitsToFloat(0x7f7fffff)) + throw new RuntimeException("Float.MAX_VALUE is not equal "+ + "to intBitsToFloat(0x7f7fffff)."); + } +} diff --git a/jdk/test/java/lang/Float/NaNInfinityParsing.java b/jdk/test/java/lang/Float/NaNInfinityParsing.java new file mode 100644 index 00000000000..fd060958b87 --- /dev/null +++ b/jdk/test/java/lang/Float/NaNInfinityParsing.java @@ -0,0 +1,169 @@ +/* + * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4428772 + * @summary Testing recognition of "NaN" and "Infinity" strings + * @author Joseph D. Darcy + */ + + +public class NaNInfinityParsing { + /* + * Regression tests for: + * 4428772 -- Establish invariant for Float & Double classes and + * their string representations + * + * Added capability for parse{Float, Double} and related methods + * to recognize "NaN" and "Infinity" strings so that + * parseFloat(toString(d)) will always return the original + * floating-point value. + */ + + static String NaNStrings[] = { + "NaN", + "+NaN", + "-NaN" + }; + + static String infinityStrings[] = { + "Infinity", + "+Infinity", + "-Infinity", + }; + + static String invalidStrings[] = { + "+", + "-", + "@", + "N", + "Na", + "Nan", + "NaNf", + "NaNd", + "NaNF", + "NaND", + "+N", + "+Na", + "+Nan", + "+NaNf", + "+NaNd", + "+NaNF", + "+NaND", + "-N", + "-Na", + "-Nan", + "-NaNf", + "-NaNd", + "-NaNF", + "-NaND", + "I", + "In", + "Inf", + "Infi", + "Infin", + "Infini", + "Infinit", + "InfinitY", + "Infinityf", + "InfinityF", + "Infinityd", + "InfinityD", + "+I", + "+In", + "+Inf", + "+Infi", + "+Infin", + "+Infini", + "+Infinit", + "+InfinitY", + "+Infinityf", + "+InfinityF", + "+Infinityd", + "+InfinityD", + "-I", + "-In", + "-Inf", + "-Infi", + "-Infin", + "-Infini", + "-Infinit", + "-InfinitY", + "-Infinityf", + "-InfinityF", + "-Infinityd", + "-InfinityD", + "NaNInfinity", + "InfinityNaN", + "nan", + "infinity" + }; + + public static void main(String [] argv) throws Exception { + int i; + float d; + + // Test valid NaN strings + for(i = 0; i < NaNStrings.length; i++) { + if(!Float.isNaN(d=Float.parseFloat(NaNStrings[i]))) { + throw new RuntimeException("NaN string ``" + NaNStrings[i] + + "'' did not parse as a NaN; returned " + + d + " instead."); + } + } + + // Test valid Infinity strings + for(i = 0; i < infinityStrings.length; i++) { + if(!Float.isInfinite(d=Float.parseFloat(infinityStrings[i]))) { + throw new RuntimeException("Infinity string ``" + + infinityStrings[i] + + "'' did not parse as infinity; returned " + + d + "instead."); + } + // check sign of result + + boolean negative = (infinityStrings[i].charAt(0) == '-'); + if(d != (negative?Float.NEGATIVE_INFINITY: + Float.POSITIVE_INFINITY)) + throw new RuntimeException("Infinity has wrong sign;" + + (negative?"positive instead of negative.": + "negative instead of positive.")); + } + + // Test almost valid strings + for(i = 0; i < invalidStrings.length; i++) { + try { + float result; + d = Float.parseFloat(invalidStrings[i]); + throw new RuntimeException("Invalid string ``" + + invalidStrings[i] + +"'' parsed as " + d + "."); + } + catch(NumberFormatException e) { + // expected + } + } + + } +} diff --git a/jdk/test/java/lang/Float/ParseFloat.java b/jdk/test/java/lang/Float/ParseFloat.java new file mode 100644 index 00000000000..02b77be193b --- /dev/null +++ b/jdk/test/java/lang/Float/ParseFloat.java @@ -0,0 +1,210 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4160406 4705734 4707389 + * @summary Tests for Float.parseFloat method + */ + +public class ParseFloat { + + private static void check(String val, float expected) { + float n = Float.parseFloat(val); + if (n != expected) + throw new RuntimeException("Float.parseFloat failed. String:" + + val + " Result:" + n); + } + + private static void rudimentaryTest() { + check(new String(""+Float.MIN_VALUE), Float.MIN_VALUE); + check(new String(""+Float.MAX_VALUE), Float.MAX_VALUE); + + check("10", (float) 10.0); + check("10.0", (float) 10.0); + check("10.01", (float) 10.01); + + check("-10", (float) -10.0); + check("-10.00", (float) -10.0); + check("-10.01", (float) -10.01); + } + + static String badStrings[] = { + "", + "+", + "-", + "+e", + "-e", + "+e170", + "-e170", + + // Make sure intermediate white space is not deleted. + "1234 e10", + "-1234 e10", + + // Control characters in the interior of a string are not legal + "1\u0007e1", + "1e\u00071", + + // NaN and infinity can't have trailing type suffices or exponents + "NaNf", + "NaNF", + "NaNd", + "NaND", + "-NaNf", + "-NaNF", + "-NaNd", + "-NaND", + "+NaNf", + "+NaNF", + "+NaNd", + "+NaND", + "Infinityf", + "InfinityF", + "Infinityd", + "InfinityD", + "-Infinityf", + "-InfinityF", + "-Infinityd", + "-InfinityD", + "+Infinityf", + "+InfinityF", + "+Infinityd", + "+InfinityD", + + "NaNe10", + "-NaNe10", + "+NaNe10", + "Infinitye10", + "-Infinitye10", + "+Infinitye10", + + // Non-ASCII digits are not recognized + "\u0661e\u0661", // 1e1 in Arabic-Indic digits + "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits + "\u0967e\u0967" // 1e1 in Devanagari digits + }; + + static String goodStrings[] = { + "NaN", + "+NaN", + "-NaN", + "Infinity", + "+Infinity", + "-Infinity", + "1.1e-23f", + ".1e-23f", + "1e-23", + "1f", + "1", + "2", + "1234", + "-1234", + "+1234", + "2147483647", // Integer.MAX_VALUE + "2147483648", + "-2147483648", // Integer.MIN_VALUE + "-2147483649", + + "16777215", + "16777216", // 2^24 + "16777217", + + "-16777215", + "-16777216", // -2^24 + "-16777217", + + "9007199254740991", + "9007199254740992", // 2^53 + "9007199254740993", + + "-9007199254740991", + "-9007199254740992", // -2^53 + "-9007199254740993", + + "9223372036854775807", + "9223372036854775808", // Long.MAX_VALUE + "9223372036854775809", + + "-9223372036854775808", + "-9223372036854775809", // Long.MIN_VALUE + "-9223372036854775810" + }; + + static String paddedBadStrings[]; + static String paddedGoodStrings[]; + static { + String pad = " \t\n\r\f\u0001\u000b\u001f"; + paddedBadStrings = new String[badStrings.length]; + for(int i = 0 ; i < badStrings.length; i++) + paddedBadStrings[i] = pad + badStrings[i] + pad; + + paddedGoodStrings = new String[goodStrings.length]; + for(int i = 0 ; i < goodStrings.length; i++) + paddedGoodStrings[i] = pad + goodStrings[i] + pad; + + } + + /* + * Throws an exception if Input is + * exceptionalInput and {@link Float.parseFloat + * parseFloat} does not throw an exception or if + * Input is not exceptionalInput and + * parseFloat throws an exception. This method does + * not attempt to test whether the string is converted to the + * proper value; just whether the input is accepted appropriately + * or not. + */ + private static void testParsing(String [] input, + boolean exceptionalInput) { + for(int i = 0; i < input.length; i++) { + double d; + + try { + d = Float.parseFloat(input[i]); + } + catch (NumberFormatException e) { + if (! exceptionalInput) { + throw new RuntimeException("Float.parseFloat rejected " + + "good string `" + input[i] + + "'."); + } + break; + } + if (exceptionalInput) { + throw new RuntimeException("Float.parseFloat accepted " + + "bad string `" + input[i] + + "'."); + } + } + } + + public static void main(String[] args) throws Exception { + rudimentaryTest(); + + testParsing(goodStrings, false); + testParsing(paddedGoodStrings, false); + testParsing(badStrings, true); + testParsing(paddedBadStrings, true); + } +} diff --git a/jdk/test/java/lang/Integer/BitTwiddle.java b/jdk/test/java/lang/Integer/BitTwiddle.java new file mode 100644 index 00000000000..4904ea5aa3d --- /dev/null +++ b/jdk/test/java/lang/Integer/BitTwiddle.java @@ -0,0 +1,137 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4495754 + * @summary Basic test for int bit twiddling + * @author Josh Bloch + * + * @compile -source 1.5 BitTwiddle.java + * @run main BitTwiddle + */ + +import java.util.Random; +import static java.lang.Integer.*; + +public class BitTwiddle { + private static final int N = 1000; // # of repetitions per test + + public static void main(String args[]) { + Random rnd = new Random(); + + if (highestOneBit(0) != 0) + throw new RuntimeException("a"); + if (highestOneBit(-1) != MIN_VALUE) + throw new RuntimeException("b"); + if (highestOneBit(1) != 1) + throw new RuntimeException("c"); + + if (lowestOneBit(0) != 0) + throw new RuntimeException("d"); + if (lowestOneBit(-1) != 1) + throw new RuntimeException("e"); + if (lowestOneBit(MIN_VALUE) != MIN_VALUE) + throw new RuntimeException("f"); + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + if (highestOneBit(x) != reverse(lowestOneBit(reverse(x)))) + throw new RuntimeException("g: " + toHexString(x)); + } + + if (numberOfLeadingZeros(0) != SIZE) + throw new RuntimeException("h"); + if (numberOfLeadingZeros(-1) != 0) + throw new RuntimeException("i"); + if (numberOfLeadingZeros(1) != (SIZE - 1)) + throw new RuntimeException("j"); + + if (numberOfTrailingZeros(0) != SIZE) + throw new RuntimeException("k"); + if (numberOfTrailingZeros(1) != 0) + throw new RuntimeException("l"); + if (numberOfTrailingZeros(MIN_VALUE) != (SIZE - 1)) + throw new RuntimeException("m"); + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + if (numberOfLeadingZeros(x) != numberOfTrailingZeros(reverse(x))) + throw new RuntimeException("n: " + toHexString(x)); + } + + if (bitCount(0) != 0) + throw new RuntimeException("o"); + + for (int i = 0; i < SIZE; i++) { + int pow2 = 1 << i; + if (bitCount(pow2) != 1) + throw new RuntimeException("p: " + i); + if (bitCount(pow2 -1) != i) + throw new RuntimeException("q: " + i); + } + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + if (bitCount(x) != bitCount(reverse(x))) + throw new RuntimeException("r: " + toHexString(x)); + } + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + int dist = rnd.nextInt(); + if (bitCount(x) != bitCount(rotateRight(x, dist))) + throw new RuntimeException("s: " + toHexString(x) + + toHexString(dist)); + if (bitCount(x) != bitCount(rotateLeft(x, dist))) + throw new RuntimeException("t: " + toHexString(x) + + toHexString(dist)); + if (rotateRight(x, dist) != rotateLeft(x, -dist)) + throw new RuntimeException("u: " + toHexString(x) + + toHexString(dist)); + if (rotateRight(x, -dist) != rotateLeft(x, dist)) + throw new RuntimeException("v: " + toHexString(x) + + toHexString(dist)); + } + + if (signum(0) != 0 || signum(1) != 1 || signum(-1) != -1 + || signum(MIN_VALUE) != -1 || signum(MAX_VALUE) != 1) + throw new RuntimeException("w"); + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + int sign = (x < 0 ? -1 : (x == 0 ? 0 : 1)); + if (signum(x) != sign) + throw new RuntimeException("x: " + toHexString(x)); + } + + if(reverseBytes(0xaabbccdd) != 0xddccbbaa) + throw new RuntimeException("y"); + + for (int i = 0; i < N; i++) { + int x = rnd.nextInt(); + if (bitCount(x) != bitCount(reverseBytes(x))) + throw new RuntimeException("z: " + toHexString(x)); + } + } +} diff --git a/jdk/test/java/lang/Integer/Decode.java b/jdk/test/java/lang/Integer/Decode.java new file mode 100644 index 00000000000..201fc2d1b88 --- /dev/null +++ b/jdk/test/java/lang/Integer/Decode.java @@ -0,0 +1,102 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4136371 5017980 6576055 + * @summary Test Integer.decode method + * @author madbot + * @author Joseph D. Darcy + */ + +/** + * There are six methods in java.lang.Integer which transform strings + * into an int or Integer value: + * + * public Integer(String s) + * public static Integer decode(String nm) + * public static int parseInteger(String s, int radix) + * public static int parseInteger(String s) + * public static Integer valueOf(String s, int radix) + * public static Integer valueOf(String s) + * + * The other five methods are tested elsewhere. + */ +public class Decode { + + private static void check(String val, int expected) { + int n = (Integer.decode(val)).intValue(); + if (n != expected) + throw new RuntimeException("Integer.decode failed. String:" + + val + " Result:" + n); + } + + private static void checkFailure(String val, String message) { + try { + int n = (Integer.decode(val)).intValue(); + throw new RuntimeException(message); + } catch (NumberFormatException e) { /* Okay */} + } + + public static void main(String[] args) throws Exception { + check(new String(""+Integer.MIN_VALUE), Integer.MIN_VALUE); + check(new String(""+Integer.MAX_VALUE), Integer.MAX_VALUE); + + check("10", 10); + check("0x10", 16); + check("0X10", 16); + check("010", 8); + check("#10", 16); + + check("+10", 10); + check("+0x10", 16); + check("+0X10", 16); + check("+010", 8); + check("+#10", 16); + + check("-10", -10); + check("-0x10", -16); + check("-0X10", -16); + check("-010", -8); + check("-#10", -16); + + check(Long.toString(Integer.MIN_VALUE), Integer.MIN_VALUE); + check(Long.toString(Integer.MAX_VALUE), Integer.MAX_VALUE); + + checkFailure("0x-10", "Integer.decode allows negative sign in wrong position."); + checkFailure("0x+10", "Integer.decode allows positive sign in wrong position."); + + checkFailure("+", "Raw plus sign allowed."); + checkFailure("-", "Raw minus sign allowed."); + + checkFailure(Long.toString((long)Integer.MIN_VALUE - 1L), "Out of range"); + checkFailure(Long.toString((long)Integer.MAX_VALUE + 1L), "Out of range"); + + checkFailure("", "Empty String"); + + try { + Integer.decode(null); + throw new RuntimeException("Integer.decode(null) expected to throw NPE"); + } catch (NullPointerException npe) {/* Okay */} + } +} diff --git a/jdk/test/java/lang/Integer/GetInteger.java b/jdk/test/java/lang/Integer/GetInteger.java new file mode 100644 index 00000000000..61a4e3c78cc --- /dev/null +++ b/jdk/test/java/lang/Integer/GetInteger.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4252315 + * @summary test Integer.getInteger method with empty key + */ + +public class GetInteger { + public static void main(String[] args) throws Exception { + Integer.getInteger("", 1); + Integer.getInteger(null, 1); + } +} diff --git a/jdk/test/java/lang/Integer/ParsingTest.java b/jdk/test/java/lang/Integer/ParsingTest.java new file mode 100644 index 00000000000..cd219fbcd11 --- /dev/null +++ b/jdk/test/java/lang/Integer/ParsingTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5017980 6576055 + * @summary Test parsing methods + * @author Joseph D. Darcy + */ + + +/** + * There are six methods in java.lang.Integer which transform strings + * into an int or Integer value: + * + * public Integer(String s) + * public static Integer decode(String nm) + * public static int parseInt(String s, int radix) + * public static int parseInt(String s) + * public static Integer valueOf(String s, int radix) + * public static Integer valueOf(String s) + * + * Besides decode, all the methods and constructor call down into + * parseInt(String, int) to do the actual work. Therefore, the + * behavior of parseInt(String, int) will be tested here. + */ + +public class ParsingTest { + public static void main(String... argv) { + check("+100", +100); + check("-100", -100); + + check("+0", 0); + check("-0", 0); + check("+00000", 0); + check("-00000", 0); + + check("0", 0); + check("1", 1); + check("9", 9); + + checkFailure("\u0000"); + checkFailure("\u002f"); + checkFailure("+"); + checkFailure("-"); + checkFailure("++"); + checkFailure("+-"); + checkFailure("-+"); + checkFailure("--"); + checkFailure("++100"); + checkFailure("--100"); + checkFailure("+-6"); + checkFailure("-+6"); + checkFailure("*100"); + } + + private static void check(String val, int expected) { + int n = Integer.parseInt(val); + if (n != expected) + throw new RuntimeException("Integer.parsedInt failed. String:" + + val + " Result:" + n); + } + + private static void checkFailure(String val) { + int n = 0; + try { + n = Integer.parseInt(val); + System.err.println("parseInt(" + val + ") incorrectly returned " + n); + throw new RuntimeException(); + } catch (NumberFormatException nfe) { + ; // Expected + } + } +} diff --git a/jdk/test/java/lang/Long/BitTwiddle.java b/jdk/test/java/lang/Long/BitTwiddle.java new file mode 100644 index 00000000000..fb1affd41dd --- /dev/null +++ b/jdk/test/java/lang/Long/BitTwiddle.java @@ -0,0 +1,137 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4495754 + * @summary Basic test for long bit twiddling + * @author Josh Bloch + * + * @compile -source 1.5 BitTwiddle.java + * @run main BitTwiddle + */ + +import java.util.Random; +import static java.lang.Long.*; + +public class BitTwiddle { + private static final int N = 1000; // # of repetitions per test + + public static void main(String args[]) { + Random rnd = new Random(); + + if (highestOneBit(0) != 0) + throw new RuntimeException("a"); + if (highestOneBit(-1) != MIN_VALUE) + throw new RuntimeException("b"); + if (highestOneBit(1) != 1) + throw new RuntimeException("c"); + + if (lowestOneBit(0) != 0) + throw new RuntimeException("d"); + if (lowestOneBit(-1) != 1) + throw new RuntimeException("e"); + if (lowestOneBit(MIN_VALUE) != MIN_VALUE) + throw new RuntimeException("f"); + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + if (highestOneBit(x) != reverse(lowestOneBit(reverse(x)))) + throw new RuntimeException("g: " + toHexString(x)); + } + + if (numberOfLeadingZeros(0) != SIZE) + throw new RuntimeException("h"); + if (numberOfLeadingZeros(-1) != 0) + throw new RuntimeException("i"); + if (numberOfLeadingZeros(1) != (SIZE - 1)) + throw new RuntimeException("j"); + + if (numberOfTrailingZeros(0) != SIZE) + throw new RuntimeException("k"); + if (numberOfTrailingZeros(1) != 0) + throw new RuntimeException("l"); + if (numberOfTrailingZeros(MIN_VALUE) != (SIZE - 1)) + throw new RuntimeException("m"); + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + if (numberOfLeadingZeros(x) != numberOfTrailingZeros(reverse(x))) + throw new RuntimeException("n: " + toHexString(x)); + } + + if (bitCount(0) != 0) + throw new RuntimeException("o"); + + for (int i = 0; i < SIZE; i++) { + long pow2 = 1L << i; + if (bitCount(pow2) != 1) + throw new RuntimeException("p: " + i); + if (bitCount(pow2 -1) != i) + throw new RuntimeException("q: " + i); + } + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + if (bitCount(x) != bitCount(reverse(x))) + throw new RuntimeException("r: " + toHexString(x)); + } + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + int dist = rnd.nextInt(); + if (bitCount(x) != bitCount(rotateRight(x, dist))) + throw new RuntimeException("s: " + toHexString(x) + + toHexString(dist)); + if (bitCount(x) != bitCount(rotateLeft(x, dist))) + throw new RuntimeException("t: " + toHexString(x) + + toHexString(dist)); + if (rotateRight(x, dist) != rotateLeft(x, -dist)) + throw new RuntimeException("u: " + toHexString(x) + + toHexString(dist)); + if (rotateRight(x, -dist) != rotateLeft(x, dist)) + throw new RuntimeException("v: " + toHexString(x) + + toHexString(dist)); + } + + if (signum(0) != 0 || signum(1) != 1 || signum(-1) != -1 + || signum(MIN_VALUE) != -1 || signum(MAX_VALUE) != 1) + throw new RuntimeException("w"); + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + int sign = (x < 0 ? -1 : (x == 0 ? 0 : 1)); + if (signum(x) != sign) + throw new RuntimeException("x: " + toHexString(x)); + } + + if(reverseBytes(0xaabbccdd11223344L) != 0x44332211ddccbbaaL) + throw new RuntimeException("y"); + + for (int i = 0; i < N; i++) { + long x = rnd.nextLong(); + if (bitCount(x) != bitCount(reverseBytes(x))) + throw new RuntimeException("z: " + toHexString(x)); + } + } +} diff --git a/jdk/test/java/lang/Long/Decode.java b/jdk/test/java/lang/Long/Decode.java new file mode 100644 index 00000000000..ae4c9cf6425 --- /dev/null +++ b/jdk/test/java/lang/Long/Decode.java @@ -0,0 +1,106 @@ +/* + * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4136371 5017980 6576055 + * @summary Test Long.decode method + * @author madbot + * @author Joseph D. Darcy + */ + +import java.math.BigInteger; + +/** + * There are six methods in java.lang.Integer which transform strings + * into a long or Long value: + * + * public Long(String s) + * public static Long decode(String nm) + * public static long parseLong(String s, int radix) + * public static long parseLong(String s) + * public static Long valueOf(String s, int radix) + * public static Long valueOf(String s) + * + * The other five methods are tested elsewhere. + */ +public class Decode { + + private static void check(String val, long expected) { + long n = (Long.decode(val)).longValue(); + if (n != expected) + throw new RuntimeException("Long.decode failed. String:" + + val + " Result:" + n); + } + + private static void checkFailure(String val, String message) { + try { + long n = (Long.decode(val)).longValue(); + throw new RuntimeException(message); + } catch (NumberFormatException e) { /* Okay */} + } + + public static void main(String[] args) throws Exception { + check(new String(""+Long.MIN_VALUE), Long.MIN_VALUE); + check(new String(""+Long.MAX_VALUE), Long.MAX_VALUE); + + check("10", 10L); + check("0x10", 16L); + check("0X10", 16L); + check("010", 8L); + check("#10", 16L); + + check("+10", 10L); + check("+0x10", 16L); + check("+0X10", 16L); + check("+010", 8L); + check("+#10", 16L); + + check("-10", -10L); + check("-0x10", -16L); + check("-0X10", -16L); + check("-010", -8L); + check("-#10", -16L); + + check(Long.toString(Long.MIN_VALUE), Long.MIN_VALUE); + check(Long.toString(Long.MAX_VALUE), Long.MAX_VALUE); + + checkFailure("0x-10", "Long.decode allows negative sign in wrong position."); + checkFailure("0x+10", "Long.decode allows positive sign in wrong position."); + + checkFailure("+", "Raw plus sign allowed."); + checkFailure("-", "Raw minus sign allowed."); + + checkFailure(BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE).toString(), + "Out of range"); + checkFailure(BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE).toString(), + "Out of range"); + + checkFailure("", "Empty String"); + + try { + Long.decode(null); + throw new RuntimeException("Long.decode(null) expected to throw NPE"); + } catch (NullPointerException npe) {/* Okay */} + } +} diff --git a/jdk/test/java/lang/Long/GetLong.java b/jdk/test/java/lang/Long/GetLong.java new file mode 100644 index 00000000000..120271dfb3e --- /dev/null +++ b/jdk/test/java/lang/Long/GetLong.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4252322 + * @summary test Long.getLong method with empty key + */ + +public class GetLong { + public static void main(String[] args) throws Exception { + Long.getLong("", 1); + Long.getLong(null, 1); + } +} diff --git a/jdk/test/java/lang/Long/ParsingTest.java b/jdk/test/java/lang/Long/ParsingTest.java new file mode 100644 index 00000000000..8fbc08204de --- /dev/null +++ b/jdk/test/java/lang/Long/ParsingTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5017980 6576055 + * @summary Test parsing methods + * @author Joseph D. Darcy + */ + + +/** + * There are six methods in java.lang.Long which transform strings + * into a long or Long value: + * + * public Long(String s) + * public static Long decode(String nm) + * public static long parseLong(String s, int radix) + * public static long parseLong(String s) + * public static Long valueOf(String s, int radix) + * public static Long valueOf(String s) + * + * Besides decode, all the methods and constructor call down into + * parseLong(String, int) to do the actual work. Therefore, the + * behavior of parseLong(String, int) will be tested here. + */ + +public class ParsingTest { + public static void main(String... argv) { + check("+100", +100L); + check("-100", -100L); + + check("+0", 0L); + check("-0", 0L); + check("+00000", 0L); + check("-00000", 0L); + + check("0", 0L); + check("1", 1L); + check("9", 9L); + + checkFailure("\u0000"); + checkFailure("\u002f"); + checkFailure("+"); + checkFailure("-"); + checkFailure("++"); + checkFailure("+-"); + checkFailure("-+"); + checkFailure("--"); + checkFailure("++100"); + checkFailure("--100"); + checkFailure("+-6"); + checkFailure("-+6"); + checkFailure("*100"); + } + + private static void check(String val, long expected) { + long n = Long.parseLong(val); + if (n != expected) + throw new RuntimeException("Long.parsedLong failed. String:" + + val + " Result:" + n); + } + + private static void checkFailure(String val) { + long n = 0L; + try { + n = Long.parseLong(val); + System.err.println("parseLong(" + val + ") incorrectly returned " + n); + throw new RuntimeException(); + } catch (NumberFormatException nfe) { + ; // Expected + } + } +} diff --git a/jdk/test/java/lang/Math/AbsPositiveZero.java b/jdk/test/java/lang/Math/AbsPositiveZero.java new file mode 100644 index 00000000000..bfb8eeabebf --- /dev/null +++ b/jdk/test/java/lang/Math/AbsPositiveZero.java @@ -0,0 +1,73 @@ +/* + * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 4096278 + @summary Math.abs(+0.0) wrong + @author Anand Palaniswamy + */ +public class AbsPositiveZero { + private static boolean isPositiveZero(float f) { + return Float.floatToIntBits(f) == Float.floatToIntBits(0.0f); + } + + private static boolean isPositiveZero(double d) { + return Double.doubleToLongBits(d) == Double.doubleToLongBits(0.0d); + } + + public static void main(String[] args) throws Exception { + if (!isPositiveZero(Math.abs(-0.0d))) { + throw new Exception("abs(-0.0d) failed"); + } + if (!isPositiveZero(Math.abs(+0.0d))) { + throw new Exception("abs(+0.0d) failed"); + } + if (Math.abs(Double.POSITIVE_INFINITY) != Double.POSITIVE_INFINITY) { + throw new Exception("abs(+Inf) failed"); + } + if (Math.abs(Double.NEGATIVE_INFINITY) != Double.POSITIVE_INFINITY) { + throw new Exception("abs(-Inf) failed"); + } + double dnanval = Math.abs(Double.NaN); + if (dnanval == dnanval) { + throw new Exception("abs(NaN) failed"); + } + + if (!isPositiveZero(Math.abs(-0.0f))) { + throw new Exception("abs(-0.0f) failed"); + } + if (!isPositiveZero(Math.abs(+0.0f))) { + throw new Exception("abs(+0.0f) failed"); + } + if (Math.abs(Float.POSITIVE_INFINITY) != Float.POSITIVE_INFINITY) { + throw new Exception("abs(+Inf) failed"); + } + if (Math.abs(Float.NEGATIVE_INFINITY) != Float.POSITIVE_INFINITY) { + throw new Exception("abs(-Inf) failed"); + } + float fnanval = Math.abs(Float.NaN); + if (fnanval == fnanval) { + throw new Exception("abs(NaN) failed"); + } + } +} diff --git a/jdk/test/java/lang/Math/Atan2Tests.java b/jdk/test/java/lang/Math/Atan2Tests.java new file mode 100644 index 00000000000..0660ff3744c --- /dev/null +++ b/jdk/test/java/lang/Math/Atan2Tests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4984407 + * @summary Tests for {Math, StrictMath}.atan2 + * @compile -source 1.5 Atan2Tests.java + * @run main Atan2Tests + * @author Joseph D. Darcy + */ + +public class Atan2Tests { + private Atan2Tests(){} + + static int testAtan2Case(double input1, double input2, double expected) { + int failures = 0; + failures += Tests.test("StrictMath.atan2(double, double)", input1, input2, + StrictMath.atan2(input1, input2), expected); + failures += Tests.test("Math.atan2(double, double)", input1, input2, + Math.atan2(input1, input2), expected); + + return failures; + } + + static int testAtan2() { + int failures = 0; + + double [][] testCases = { + {-3.0, Double.POSITIVE_INFINITY, -0.0}, + }; + + for (double[] testCase : testCases) { + failures+=testAtan2Case(testCase[0], testCase[1], testCase[2]); + } + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testAtan2(); + + if (failures > 0) { + System.err.println("Testing atan2 incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/Math/CubeRootTests.java b/jdk/test/java/lang/Math/CubeRootTests.java new file mode 100644 index 00000000000..9b5bd329a3a --- /dev/null +++ b/jdk/test/java/lang/Math/CubeRootTests.java @@ -0,0 +1,336 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4347132 4939441 + * @summary Tests for {Math, StrictMath}.cbrt + * @author Joseph D. Darcy + */ + +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class CubeRootTests { + private CubeRootTests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + static final double NaNd = Double.NaN; + + // Initialize shared random number generator + static java.util.Random rand = new java.util.Random(); + + static int testCubeRootCase(double input, double expected) { + int failures=0; + + double minus_input = -input; + double minus_expected = -expected; + + failures+=Tests.test("Math.cbrt(double)", input, + Math.cbrt(input), expected); + failures+=Tests.test("Math.cbrt(double)", minus_input, + Math.cbrt(minus_input), minus_expected); + failures+=Tests.test("StrictMath.cbrt(double)", input, + StrictMath.cbrt(input), expected); + failures+=Tests.test("StrictMath.cbrt(double)", minus_input, + StrictMath.cbrt(minus_input), minus_expected); + + return failures; + } + + static int testCubeRoot() { + int failures = 0; + double [][] testCases = { + {NaNd, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY}, + {+0.0, +0.0}, + {-0.0, -0.0}, + {+1.0, +1.0}, + {-1.0, -1.0}, + {+8.0, +2.0}, + {-8.0, -2.0} + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testCubeRootCase(testCases[i][0], + testCases[i][1]); + } + + // Test integer perfect cubes less than 2^53. + for(int i = 0; i <= 208063; i++) { + double d = i; + failures += testCubeRootCase(d*d*d, (double)i); + } + + // Test cbrt(2^(3n)) = 2^n. + for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) { + failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i), + FpUtils.scalb(1.0, i) ); + } + + // Test cbrt(2^(-3n)) = 2^-n. + for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) { + failures += testCubeRootCase(FpUtils.scalb(1.0, 3*i), + FpUtils.scalb(1.0, i) ); + } + + // Test random perfect cubes. Create double values with + // modest exponents but only have at most the 17 most + // significant bits in the significand set; 17*3 = 51, which + // is less than the number of bits in a double's significand. + long exponentBits1 = + Double.doubleToLongBits(FpUtils.scalb(1.0, 55)) & + DoubleConsts.EXP_BIT_MASK; + long exponentBits2= + Double.doubleToLongBits(FpUtils.scalb(1.0, -55)) & + DoubleConsts.EXP_BIT_MASK; + for(int i = 0; i < 100; i++) { + // Take 16 bits since the 17th bit is implicit in the + // exponent + double input1 = + Double.longBitsToDouble(exponentBits1 | + // Significand bits + ((long) (rand.nextInt() & 0xFFFF))<< + (DoubleConsts.SIGNIFICAND_WIDTH-1-16)); + failures += testCubeRootCase(input1*input1*input1, input1); + + double input2 = + Double.longBitsToDouble(exponentBits2 | + // Significand bits + ((long) (rand.nextInt() & 0xFFFF))<< + (DoubleConsts.SIGNIFICAND_WIDTH-1-16)); + failures += testCubeRootCase(input2*input2*input2, input2); + } + + // Directly test quality of implementation properties of cbrt + // for values that aren't perfect cubes. Verify returned + // result meets the 1 ulp test. That is, we want to verify + // that for positive x > 1, + // y = cbrt(x), + // + // if (err1=x - y^3 ) < 0, abs((y_pp^3 -x )) < err1 + // if (err1=x - y^3 ) > 0, abs((y_mm^3 -x )) < err1 + // + // where y_mm and y_pp are the next smaller and next larger + // floating-point value to y. In other words, if y^3 is too + // big, making y larger does not improve the result; likewise, + // if y^3 is too small, making y smaller does not improve the + // result. + // + // ...-----|--?--|--?--|-----... Where is the true result? + // y_mm y y_pp + // + // The returned value y should be one of the floating-point + // values braketing the true result. However, given y, a + // priori we don't know if the true result falls in [y_mm, y] + // or [y, y_pp]. The above test looks at the error in x-y^3 + // to determine which region the true result is in; e.g. if + // y^3 is smaller than x, the true result should be in [y, + // y_pp]. Therefore, it would be an error for y_mm to be a + // closer approximation to x^(1/3). In this case, it is + // permissible, although not ideal, for y_pp^3 to be a closer + // approximation to x^(1/3) than y^3. + // + // We will use pow(y,3) to compute y^3. Although pow is not + // correctly rounded, StrictMath.pow should have at most 1 ulp + // error. For y > 1, pow(y_mm,3) and pow(y_pp,3) will differ + // from pow(y,3) by more than one ulp so the comparision of + // errors should still be valid. + + for(int i = 0; i < 1000; i++) { + double d = 1.0 + rand.nextDouble(); + double err, err_adjacent; + + double y1 = Math.cbrt(d); + double y2 = StrictMath.cbrt(d); + + err = d - StrictMath.pow(y1, 3); + if (err != 0.0) { + if(FpUtils.isNaN(err)) { + failures++; + System.err.println("Encountered unexpected NaN value: d = " + d + + "\tcbrt(d) = " + y1); + } else { + if (err < 0.0) { + err_adjacent = StrictMath.pow(FpUtils.nextUp(y1), 3) - d; + } + else { // (err > 0.0) + err_adjacent = StrictMath.pow(FpUtils.nextAfter(y1,0.0), 3) - d; + } + + if (Math.abs(err) > Math.abs(err_adjacent)) { + failures++; + System.err.println("For Math.cbrt(" + d + "), returned result " + + y1 + "is not as good as adjacent value."); + } + } + } + + + err = d - StrictMath.pow(y2, 3); + if (err != 0.0) { + if(FpUtils.isNaN(err)) { + failures++; + System.err.println("Encountered unexpected NaN value: d = " + d + + "\tcbrt(d) = " + y2); + } else { + if (err < 0.0) { + err_adjacent = StrictMath.pow(FpUtils.nextUp(y2), 3) - d; + } + else { // (err > 0.0) + err_adjacent = StrictMath.pow(FpUtils.nextAfter(y2,0.0), 3) - d; + } + + if (Math.abs(err) > Math.abs(err_adjacent)) { + failures++; + System.err.println("For StrictMath.cbrt(" + d + "), returned result " + + y2 + "is not as good as adjacent value."); + } + } + } + + + } + + // Test monotonicity properites near perfect cubes; test two + // numbers before and two numbers after; i.e. for + // + // pcNeighbors[] = + // {nextDown(nextDown(pc)), + // nextDown(pc), + // pc, + // nextUp(pc), + // nextUp(nextUp(pc))} + // + // test that cbrt(pcNeighbors[i]) <= cbrt(pcNeighbors[i+1]) + { + + double pcNeighbors[] = new double[5]; + double pcNeighborsCbrt[] = new double[5]; + double pcNeighborsStrictCbrt[] = new double[5]; + + // Test near cbrt(2^(3n)) = 2^n. + for(int i = 18; i <= DoubleConsts.MAX_EXPONENT/3; i++) { + double pc = FpUtils.scalb(1.0, 3*i); + + pcNeighbors[2] = pc; + pcNeighbors[1] = FpUtils.nextDown(pc); + pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); + pcNeighbors[3] = FpUtils.nextUp(pc); + pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + + for(int j = 0; j < pcNeighbors.length; j++) { + pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]); + pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]); + } + + for(int j = 0; j < pcNeighborsCbrt.length-1; j++) { + if(pcNeighborsCbrt[j] > pcNeighborsCbrt[j+1] ) { + failures++; + System.err.println("Monotonicity failure for Math.cbrt on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsCbrt[j] + " and " + + pcNeighborsCbrt[j+1] ); + } + + if(pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j+1] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.cbrt on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsStrictCbrt[j] + " and " + + pcNeighborsStrictCbrt[j+1] ); + } + + + } + + } + + // Test near cbrt(2^(-3n)) = 2^-n. + for(int i = -1; i >= FpUtils.ilogb(Double.MIN_VALUE)/3; i--) { + double pc = FpUtils.scalb(1.0, 3*i); + + pcNeighbors[2] = pc; + pcNeighbors[1] = FpUtils.nextDown(pc); + pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); + pcNeighbors[3] = FpUtils.nextUp(pc); + pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + + for(int j = 0; j < pcNeighbors.length; j++) { + pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]); + pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]); + } + + for(int j = 0; j < pcNeighborsCbrt.length-1; j++) { + if(pcNeighborsCbrt[j] > pcNeighborsCbrt[j+1] ) { + failures++; + System.err.println("Monotonicity failure for Math.cbrt on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsCbrt[j] + " and " + + pcNeighborsCbrt[j+1] ); + } + + if(pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j+1] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.cbrt on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsStrictCbrt[j] + " and " + + pcNeighborsStrictCbrt[j+1] ); + } + + + } + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += testCubeRoot(); + + if (failures > 0) { + System.err.println("Testing cbrt incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/Expm1Tests.java b/jdk/test/java/lang/Math/Expm1Tests.java new file mode 100644 index 00000000000..a9ff06b4aa9 --- /dev/null +++ b/jdk/test/java/lang/Math/Expm1Tests.java @@ -0,0 +1,231 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 4900189 4939441 + * @summary Tests for {Math, StrictMath}.expm1 + * @author Joseph D. Darcy + */ + +import sun.misc.DoubleConsts; +import sun.misc.FpUtils; + +/* + * The Taylor expansion of expxm1(x) = exp(x) -1 is + * + * 1 + x/1! + x^2/2! + x^3/3| + ... -1 = + * + * x + x^2/2! + x^3/3 + ... + * + * Therefore, for small values of x, expxm1 ~= x. + * + * For large values of x, expxm1(x) ~= exp(x) + * + * For large negative x, expxm1(x) ~= -1. + */ + +public class Expm1Tests { + + private Expm1Tests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + static final double NaNd = Double.NaN; + + static int testExpm1() { + int failures = 0; + + double [][] testCases = { + {Double.NaN, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {infinityD, infinityD}, + {-infinityD, -1.0}, + {-0.0, -0.0}, + {+0.0, +0.0}, + }; + + // Test special cases + for(int i = 0; i < testCases.length; i++) { + failures += testExpm1CaseWithUlpDiff(testCases[i][0], + testCases[i][1], 0, null); + } + + + // For |x| < 2^-54 expm1(x) ~= x + for(int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) { + double d = FpUtils.scalb(2, i); + failures += testExpm1Case(d, d); + failures += testExpm1Case(-d, -d); + } + + + // For values of y where exp(y) > 2^54, expm1(x) ~= exp(x). + // The least such y is ln(2^54) ~= 37.42994775023705; exp(x) + // overflows for x > ~= 709.8 + + // Use a 2-ulp error threshold to account for errors in the + // exp implementation; the increments of d in the loop will be + // exact. + for(double d = 37.5; d <= 709.5; d += 1.0) { + failures += testExpm1CaseWithUlpDiff(d, StrictMath.exp(d), 2, null); + } + + // For x > 710, expm1(x) should be infinity + for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = FpUtils.scalb(2, i); + failures += testExpm1Case(d, infinityD); + } + + // By monotonicity, once the limit is reached, the + // implemenation should return the limit for all smaller + // values. + boolean reachedLimit [] = {false, false}; + + // Once exp(y) < 0.5 * ulp(1), expm1(y) ~= -1.0; + // The greatest such y is ln(2^-53) ~= -36.7368005696771. + for(double d = -36.75; d >= -127.75; d -= 1.0) { + failures += testExpm1CaseWithUlpDiff(d, -1.0, 1, + reachedLimit); + } + + for(int i = 7; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = -FpUtils.scalb(2, i); + failures += testExpm1CaseWithUlpDiff(d, -1.0, 1, reachedLimit); + } + + // Test for monotonicity failures near multiples of log(2). + // Test two numbers before and two numbers after each chosen + // value; i.e. + // + // pcNeighbors[] = + // {nextDown(nextDown(pc)), + // nextDown(pc), + // pc, + // nextUp(pc), + // nextUp(nextUp(pc))} + // + // and we test that expm1(pcNeighbors[i]) <= expm1(pcNeighbors[i+1]) + { + double pcNeighbors[] = new double[5]; + double pcNeighborsExpm1[] = new double[5]; + double pcNeighborsStrictExpm1[] = new double[5]; + + for(int i = -50; i <= 50; i++) { + double pc = StrictMath.log(2)*i; + + pcNeighbors[2] = pc; + pcNeighbors[1] = FpUtils.nextDown(pc); + pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); + pcNeighbors[3] = FpUtils.nextUp(pc); + pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + + for(int j = 0; j < pcNeighbors.length; j++) { + pcNeighborsExpm1[j] = Math.expm1(pcNeighbors[j]); + pcNeighborsStrictExpm1[j] = StrictMath.expm1(pcNeighbors[j]); + } + + for(int j = 0; j < pcNeighborsExpm1.length-1; j++) { + if(pcNeighborsExpm1[j] > pcNeighborsExpm1[j+1] ) { + failures++; + System.err.println("Monotonicity failure for Math.expm1 on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsExpm1[j] + " and " + + pcNeighborsExpm1[j+1] ); + } + + if(pcNeighborsStrictExpm1[j] > pcNeighborsStrictExpm1[j+1] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.expm1 on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsStrictExpm1[j] + " and " + + pcNeighborsStrictExpm1[j+1] ); + } + + + } + + } + } + + return failures; + } + + public static int testExpm1Case(double input, + double expected) { + return testExpm1CaseWithUlpDiff(input, expected, 1, null); + } + + public static int testExpm1CaseWithUlpDiff(double input, + double expected, + double ulps, + boolean [] reachedLimit) { + int failures = 0; + double mathUlps = ulps, strictUlps = ulps; + double mathOutput; + double strictOutput; + + if (reachedLimit != null) { + if (reachedLimit[0]) + mathUlps = 0; + + if (reachedLimit[1]) + strictUlps = 0; + } + + failures += Tests.testUlpDiffWithLowerBound("Math.expm1(double)", + input, mathOutput=Math.expm1(input), + expected, mathUlps, -1.0); + failures += Tests.testUlpDiffWithLowerBound("StrictMath.expm1(double)", + input, strictOutput=StrictMath.expm1(input), + expected, strictUlps, -1.0); + if (reachedLimit != null) { + reachedLimit[0] |= (mathOutput == -1.0); + reachedLimit[1] |= (strictOutput == -1.0); + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += testExpm1(); + + if (failures > 0) { + System.err.println("Testing expm1 incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/Math/HyperbolicTests.java b/jdk/test/java/lang/Math/HyperbolicTests.java new file mode 100644 index 00000000000..c93ea4b795a --- /dev/null +++ b/jdk/test/java/lang/Math/HyperbolicTests.java @@ -0,0 +1,1065 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851625 4900189 4939441 + * @summary Tests for {Math, StrictMath}.{sinh, cosh, tanh} + * @author Joseph D. Darcy + */ + +import sun.misc.DoubleConsts; +import sun.misc.FpUtils; + +public class HyperbolicTests { + private HyperbolicTests(){} + + static final double NaNd = Double.NaN; + + /** + * Test accuracy of {Math, StrictMath}.sinh. The specified + * accuracy is 2.5 ulps. + * + * The defintion of sinh(x) is + * + * (e^x - e^(-x))/2 + * + * The series expansion of sinh(x) = + * + * x + x^3/3! + x^5/5! + x^7/7! +... + * + * Therefore, + * + * 1. For large values of x sinh(x) ~= signum(x)*exp(|x|)/2 + * + * 2. For small values of x, sinh(x) ~= x. + * + * Additionally, sinh is an odd function; sinh(-x) = -sinh(x). + * + */ + static int testSinh() { + int failures = 0; + /* + * Array elements below generated using a quad sinh + * implementation. Rounded to a double, the quad result + * *should* be correctly rounded, unless we are quite unlucky. + * Assuming the quad value is a correctly rounded double, the + * allowed error is 3.0 ulps instead of 2.5 since the quad + * value rounded to double can have its own 1/2 ulp error. + */ + double [][] testCases = { + // x sinh(x) + {0.0625, 0.06254069805219182172183988501029229}, + {0.1250, 0.12532577524111545698205754229137154}, + {0.1875, 0.18860056562029018382047025055167585}, + {0.2500, 0.25261231680816830791412515054205787}, + {0.3125, 0.31761115611357728583959867611490292}, + {0.3750, 0.38385106791361456875429567642050245}, + {0.4375, 0.45159088610312053032509815226723017}, + {0.5000, 0.52109530549374736162242562641149155}, + {0.5625, 0.59263591611468777373870867338492247}, + {0.6250, 0.66649226445661608227260655608302908}, + {0.6875, 0.74295294580567543571442036910465007}, + {0.7500, 0.82231673193582998070366163444691386}, + {0.8125, 0.90489373856606433650504536421491368}, + {0.8750, 0.99100663714429475605317427568995231}, + {0.9375, 1.08099191569306394011007867453992548}, + {1.0000, 1.17520119364380145688238185059560082}, + {1.0625, 1.27400259579739321279181130344911907}, + {1.1250, 1.37778219077984075760379987065228373}, + {1.1875, 1.48694549961380717221109202361777593}, + {1.2500, 1.60191908030082563790283030151221415}, + {1.3125, 1.72315219460596010219069206464391528}, + {1.3750, 1.85111856355791532419998548438506416}, + {1.4375, 1.98631821852425112898943304217629457}, + {1.5000, 2.12927945509481749683438749467763195}, + {1.5625, 2.28056089740825247058075476705718764}, + {1.6250, 2.44075368098794353221372986997161132}, + {1.6875, 2.61048376261693140366028569794027603}, + {1.7500, 2.79041436627764265509289122308816092}, + {1.8125, 2.98124857471401377943765253243875520}, + {1.8750, 3.18373207674259205101326780071803724}, + {1.9375, 3.39865608104779099764440244167531810}, + {2.0000, 3.62686040784701876766821398280126192}, + {2.0625, 3.86923677050642806693938384073620450}, + {2.1250, 4.12673225993027252260441410537905269}, + {2.1875, 4.40035304533919660406976249684469164}, + {2.2500, 4.69116830589833069188357567763552003}, + {2.3125, 5.00031440855811351554075363240262157}, + {2.3750, 5.32899934843284576394645856548481489}, + {2.4375, 5.67850746906785056212578751630266858}, + {2.5000, 6.05020448103978732145032363835040319}, + {2.5625, 6.44554279850040875063706020260185553}, + {2.6250, 6.86606721451642172826145238779845813}, + {2.6875, 7.31342093738196587585692115636603571}, + {2.7500, 7.78935201149073201875513401029935330}, + {2.8125, 8.29572014785741787167717932988491961}, + {2.8750, 8.83450399097893197351853322827892144}, + {2.9375, 9.40780885043076394429977972921690859}, + {3.0000, 10.01787492740990189897459361946582867}, + {3.0625, 10.66708606836969224165124519209968368}, + {3.1250, 11.35797907995166028304704128775698426}, + {3.1875, 12.09325364161259019614431093344260209}, + {3.2500, 12.87578285468067003959660391705481220}, + {3.3125, 13.70862446906136798063935858393686525}, + {3.3750, 14.59503283146163690015482636921657975}, + {3.4375, 15.53847160182039311025096666980558478}, + {3.5000, 16.54262728763499762495673152901249743}, + {3.5625, 17.61142364906941482858466494889121694}, + {3.6250, 18.74903703113232171399165788088277979}, + {3.6875, 19.95991268283598684128844120984214675}, + {3.7500, 21.24878212710338697364101071825171163}, + {3.8125, 22.62068164929685091969259499078125023}, + {3.8750, 24.08097197661255803883403419733891573}, + {3.9375, 25.63535922523855307175060244757748997}, + {4.0000, 27.28991719712775244890827159079382096}, + {4.0625, 29.05111111351106713777825462100160185}, + {4.1250, 30.92582287788986031725487699744107092}, + {4.1875, 32.92137796722343190618721270937061472}, + {4.2500, 35.04557405638942942322929652461901154}, + {4.3125, 37.30671148776788628118833357170042385}, + {4.3750, 39.71362570500944929025069048612806024}, + {4.4375, 42.27572177772344954814418332587050658}, + {4.5000, 45.00301115199178562180965680564371424}, + {4.5625, 47.90615077031205065685078058248081891}, + {4.6250, 50.99648471383193131253995134526177467}, + {4.6875, 54.28608852959281437757368957713936555}, + {4.7500, 57.78781641599226874961859781628591635}, + {4.8125, 61.51535145084362283008545918273109379}, + {4.8750, 65.48325905829987165560146562921543361}, + {4.9375, 69.70704392356508084094318094283346381}, + {5.0000, 74.20321057778875897700947199606456364}, + {5.0625, 78.98932788987998983462810080907521151}, + {5.1250, 84.08409771724448958901392613147384951}, + {5.1875, 89.50742798369883598816307922895346849}, + {5.2500, 95.28051047011540739630959111303975956}, + {5.3125, 101.42590362176666730633859252034238987}, + {5.3750, 107.96762069594029162704530843962700133}, + {5.4375, 114.93122359426386042048760580590182604}, + {5.5000, 122.34392274639096192409774240457730721}, + {5.5625, 130.23468343534638291488502321709913206}, + {5.6250, 138.63433897999898233879574111119546728}, + {5.6875, 147.57571121692522056519568264304815790}, + {5.7500, 157.09373875244884423880085377625986165}, + {5.8125, 167.22561348600435888568183143777868662}, + {5.8750, 178.01092593829229887752609866133883987}, + {5.9375, 189.49181995209921964640216682906501778}, + {6.0000, 201.71315737027922812498206768797872263}, + {6.0625, 214.72269333437984291483666459592578915}, + {6.1250, 228.57126288889537420461281285729970085}, + {6.1875, 243.31297962030799867970551767086092471}, + {6.2500, 259.00544710710289911522315435345489966}, + {6.3125, 275.70998400700299790136562219920451185}, + {6.3750, 293.49186366095654566861661249898332253}, + {6.4375, 312.42056915013535342987623229485223434}, + {6.5000, 332.57006480258443156075705566965111346}, + {6.5625, 354.01908521044116928437570109827956007}, + {6.6250, 376.85144288706511933454985188849781703}, + {6.6875, 401.15635576625530823119100750634165252}, + {6.7500, 427.02879582326538080306830640235938517}, + {6.8125, 454.56986017986077163530945733572724452}, + {6.8750, 483.88716614351897894746751705315210621}, + {6.9375, 515.09527172439720070161654727225752288}, + {7.0000, 548.31612327324652237375611757601851598}, + {7.0625, 583.67953198942753384680988096024373270}, + {7.1250, 621.32368116099280160364794462812762880}, + {7.1875, 661.39566611888784148449430491465857519}, + {7.2500, 704.05206901515336623551137120663358760}, + {7.3125, 749.45957067108712382864538206200700256}, + {7.3750, 797.79560188617531521347351754559776282}, + {7.4375, 849.24903675279739482863565789325699416}, + {7.5000, 904.02093068584652953510919038935849651}, + {7.5625, 962.32530605113249628368993221570636328}, + {7.6250, 1024.38998846242707559349318193113614698}, + {7.6875, 1090.45749701500081956792547346904792325}, + {7.7500, 1160.78599193425808533255719118417856088}, + {7.8125, 1235.65028334242796895820912936318532502}, + {7.8750, 1315.34290508508890654067255740428824014}, + {7.9375, 1400.17525781352742299995139486063802583}, + {8.0000, 1490.47882578955018611587663903188144796}, + {8.0625, 1586.60647216744061169450001100145859236}, + {8.1250, 1688.93381781440241350635231605477507900}, + {8.1875, 1797.86070905726094477721128358866360644}, + {8.2500, 1913.81278009067446281883262689250118009}, + {8.3125, 2037.24311615199935553277163192983440062}, + {8.3750, 2168.63402396170125867037749369723761636}, + {8.4375, 2308.49891634734644432370720900969004306}, + {8.5000, 2457.38431841538268239359965370719928775}, + {8.5625, 2615.87200310986940554256648824234335262}, + {8.6250, 2784.58126450289932429469130598902487336}, + {8.6875, 2964.17133769964321637973459949999057146}, + {8.7500, 3155.34397481384944060352507473513108710}, + {8.8125, 3358.84618707947841898217318996045550438}, + {8.8750, 3575.47316381333288862617411467285480067}, + {8.9375, 3806.07137963459383403903729660349293583}, + {9.0000, 4051.54190208278996051522359589803425598}, + {9.0625, 4312.84391255878980330955246931164633615}, + {9.1250, 4590.99845434696991399363282718106006883}, + {9.1875, 4887.09242236403719571363798584676797558}, + {9.2500, 5202.28281022453561319352901552085348309}, + {9.3125, 5537.80123121853803935727335892054791265}, + {9.3750, 5894.95873086734181634245918412592155656}, + {9.4375, 6275.15090986233399457103055108344546942}, + {9.5000, 6679.86337740502119410058225086262108741}, + {9.5625, 7110.67755625726876329967852256934334025}, + {9.6250, 7569.27686218510919585241049433331592115}, + {9.6875, 8057.45328194243077504648484392156371121}, + {9.7500, 8577.11437549816065709098061006273039092}, + {9.8125, 9130.29072986829727910801024120918114778}, + {9.8750, 9719.14389367880274015504995181862860062}, + {9.9375, 10345.97482346383208590278839409938269134}, + {10.0000, 11013.23287470339337723652455484636420303}, + }; + + for(int i = 0; i < testCases.length; i++) { + double [] testCase = testCases[i]; + failures += testSinhCaseWithUlpDiff(testCase[0], + testCase[1], + 3.0); + } + + double [][] specialTestCases = { + {0.0, 0.0}, + {NaNd, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY} + }; + + for(int i = 0; i < specialTestCases.length; i++) { + failures += testSinhCaseWithUlpDiff(specialTestCases[i][0], + specialTestCases[i][1], + 0.0); + } + + // For powers of 2 less than 2^(-27), the second and + // subsequent terms of the Taylor series expansion will get + // rounded away since |n-n^3| > 53, the binary precision of a + // double significand. + + for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { + double d = FpUtils.scalb(2.0, i); + + // Result and expected are the same. + failures += testSinhCaseWithUlpDiff(d, d, 2.5); + } + + // For values of x larger than 22, the e^(-x) term is + // insignificant to the floating-point result. Util exp(x) + // overflows around 709.8, sinh(x) ~= exp(x)/2; will will test + // 10000 values in this range. + + long trans22 = Double.doubleToLongBits(22.0); + // (approximately) largest value such that exp shouldn't + // overflow + long transExpOvfl = Double.doubleToLongBits(FpUtils.nextDown(709.7827128933841)); + + for(long i = trans22; + i < transExpOvfl; + i +=(transExpOvfl-trans22)/10000) { + + double d = Double.longBitsToDouble(i); + + // Allow 3.5 ulps of error to deal with error in exp. + failures += testSinhCaseWithUlpDiff(d, StrictMath.exp(d)*0.5, 3.5); + } + + // (approximately) largest value such that sinh shouldn't + // overflow. + long transSinhOvfl = Double.doubleToLongBits(710.4758600739439); + + // Make sure sinh(x) doesn't overflow as soon as exp(x) + // overflows. + + /* + * For large values of x, sinh(x) ~= 0.5*(e^x). Therefore, + * + * sinh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5) + * + * So, we can calculate the approximate expected result as + * exp(x + -0.693147186). However, this sum suffers from + * roundoff, limiting the accuracy of the approximation. The + * accuracy can be improved by recovering the rounded-off + * information. Since x is larger than ln(0.5), the trailing + * bits of ln(0.5) get rounded away when the two values are + * added. However, high-order bits of ln(0.5) that + * contribute to the sum can be found: + * + * offset = log(0.5); + * effective_offset = (x + offset) - x; // exact subtraction + * rounded_away_offset = offset - effective_offset; // exact subtraction + * + * Therefore, the product + * + * exp(x + offset)*exp(rounded_away_offset) + * + * will be a better approximation to the exact value of + * + * e^(x + offset) + * + * than exp(x+offset) alone. (The expected result cannot be + * computed as exp(x)*exp(offset) since exp(x) by itself would + * overflow to infinity.) + */ + double offset = StrictMath.log(0.5); + for(long i = transExpOvfl+1; i < transSinhOvfl; + i += (transSinhOvfl-transExpOvfl)/1000 ) { + double input = Double.longBitsToDouble(i); + + double expected = + StrictMath.exp(input + offset) * + StrictMath.exp( offset - ((input + offset) - input) ); + + failures += testSinhCaseWithUlpDiff(input, expected, 4.0); + } + + // sinh(x) overflows for values greater than 710; in + // particular, it overflows for all 2^i, i > 10. + for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = FpUtils.scalb(2.0, i); + + // Result and expected are the same. + failures += testSinhCaseWithUlpDiff(d, + Double.POSITIVE_INFINITY, 0.0); + } + + return failures; + } + + public static int testSinhCaseWithTolerance(double input, + double expected, + double tolerance) { + int failures = 0; + failures += Tests.testTolerance("Math.sinh(double)", + input, Math.sinh(input), + expected, tolerance); + failures += Tests.testTolerance("Math.sinh(double)", + -input, Math.sinh(-input), + -expected, tolerance); + + failures += Tests.testTolerance("StrictMath.sinh(double)", + input, StrictMath.sinh(input), + expected, tolerance); + failures += Tests.testTolerance("StrictMath.sinh(double)", + -input, StrictMath.sinh(-input), + -expected, tolerance); + return failures; + } + + public static int testSinhCaseWithUlpDiff(double input, + double expected, + double ulps) { + int failures = 0; + failures += Tests.testUlpDiff("Math.sinh(double)", + input, Math.sinh(input), + expected, ulps); + failures += Tests.testUlpDiff("Math.sinh(double)", + -input, Math.sinh(-input), + -expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.sinh(double)", + input, StrictMath.sinh(input), + expected, ulps); + failures += Tests.testUlpDiff("StrictMath.sinh(double)", + -input, StrictMath.sinh(-input), + -expected, ulps); + return failures; + } + + + /** + * Test accuracy of {Math, StrictMath}.cosh. The specified + * accuracy is 2.5 ulps. + * + * The defintion of cosh(x) is + * + * (e^x + e^(-x))/2 + * + * The series expansion of cosh(x) = + * + * 1 + x^2/2! + x^4/4! + x^6/6! +... + * + * Therefore, + * + * 1. For large values of x cosh(x) ~= exp(|x|)/2 + * + * 2. For small values of x, cosh(x) ~= 1. + * + * Additionally, cosh is an even function; cosh(-x) = cosh(x). + * + */ + static int testCosh() { + int failures = 0; + /* + * Array elements below generated using a quad cosh + * implementation. Rounded to a double, the quad result + * *should* be correctly rounded, unless we are quite unlucky. + * Assuming the quad value is a correctly rounded double, the + * allowed error is 3.0 ulps instead of 2.5 since the quad + * value rounded to double can have its own 1/2 ulp error. + */ + double [][] testCases = { + // x cosh(x) + {0.0625, 1.001953760865667607841550709632597376}, + {0.1250, 1.007822677825710859846949685520422223}, + {0.1875, 1.017629683800690526835115759894757615}, + {0.2500, 1.031413099879573176159295417520378622}, + {0.3125, 1.049226785060219076999158096606305793}, + {0.3750, 1.071140346704586767299498015567016002}, + {0.4375, 1.097239412531012567673453832328262160}, + {0.5000, 1.127625965206380785226225161402672030}, + {0.5625, 1.162418740845610783505338363214045218}, + {0.6250, 1.201753692975606324229229064105075301}, + {0.6875, 1.245784523776616395403056980542275175}, + {0.7500, 1.294683284676844687841708185390181730}, + {0.8125, 1.348641048647144208352285714214372703}, + {0.8750, 1.407868656822803158638471458026344506}, + {0.9375, 1.472597542369862933336886403008640891}, + {1.0000, 1.543080634815243778477905620757061497}, + {1.0625, 1.619593348374367728682469968448090763}, + {1.1250, 1.702434658138190487400868008124755757}, + {1.1875, 1.791928268324866464246665745956119612}, + {1.2500, 1.888423877161015738227715728160051696}, + {1.3125, 1.992298543335143985091891077551921106}, + {1.3750, 2.103958159362661802010972984204389619}, + {1.4375, 2.223839037619709260803023946704272699}, + {1.5000, 2.352409615243247325767667965441644201}, + {1.5625, 2.490172284559350293104864895029231913}, + {1.6250, 2.637665356192137582275019088061812951}, + {1.6875, 2.795465162524235691253423614360562624}, + {1.7500, 2.964188309728087781773608481754531801}, + {1.8125, 3.144494087167972176411236052303565201}, + {1.8750, 3.337087043587520514308832278928116525}, + {1.9375, 3.542719740149244276729383650503145346}, + {2.0000, 3.762195691083631459562213477773746099}, + {2.0625, 3.996372503438463642260225717607554880}, + {2.1250, 4.246165228196992140600291052990934410}, + {2.1875, 4.512549935859540340856119781585096760}, + {2.2500, 4.796567530460195028666793366876218854}, + {2.3125, 5.099327816921939817643745917141739051}, + {2.3750, 5.422013837643509250646323138888569746}, + {2.4375, 5.765886495263270945949271410819116399}, + {2.5000, 6.132289479663686116619852312817562517}, + {2.5625, 6.522654518468725462969589397439224177}, + {2.6250, 6.938506971550673190999796241172117288}, + {2.6875, 7.381471791406976069645686221095397137}, + {2.7500, 7.853279872697439591457564035857305647}, + {2.8125, 8.355774815752725814638234943192709129}, + {2.8750, 8.890920130482709321824793617157134961}, + {2.9375, 9.460806908834119747071078865866737196}, + {3.0000, 10.067661995777765841953936035115890343}, + {3.0625, 10.713856690753651225304006562698007312}, + {3.1250, 11.401916013575067700373788969458446177}, + {3.1875, 12.134528570998387744547733730974713055}, + {3.2500, 12.914557062512392049483503752322408761}, + {3.3125, 13.745049466398732213877084541992751273}, + {3.3750, 14.629250949773302934853381428660210721}, + {3.4375, 15.570616549147269180921654324879141947}, + {3.5000, 16.572824671057316125696517821376119469}, + {3.5625, 17.639791465519127930722105721028711044}, + {3.6250, 18.775686128468677200079039891415789429}, + {3.6875, 19.984947192985946987799359614758598457}, + {3.7500, 21.272299872959396081877161903352144126}, + {3.8125, 22.642774526961913363958587775566619798}, + {3.8750, 24.101726314486257781049388094955970560}, + {3.9375, 25.654856121347151067170940701379544221}, + {4.0000, 27.308232836016486629201989612067059978}, + {4.0625, 29.068317063936918520135334110824828950}, + {4.1250, 30.941986372478026192360480044849306606}, + {4.1875, 32.936562165180269851350626768308756303}, + {4.2500, 35.059838290298428678502583470475012235}, + {4.3125, 37.320111495433027109832850313172338419}, + {4.3750, 39.726213847251883288518263854094284091}, + {4.4375, 42.287547242982546165696077854963452084}, + {4.5000, 45.014120148530027928305799939930642658}, + {4.5625, 47.916586706774825161786212701923307169}, + {4.6250, 51.006288368867753140854830589583165950}, + {4.6875, 54.295298211196782516984520211780624960}, + {4.7500, 57.796468111195389383795669320243166117}, + {4.8125, 61.523478966332915041549750463563672435}, + {4.8750, 65.490894152518731617237739112888213645}, + {4.9375, 69.714216430810089539924900313140922323}, + {5.0000, 74.209948524787844444106108044487704798}, + {5.0625, 78.995657605307475581204965926043112946}, + {5.1250, 84.090043934600961683400343038519519678}, + {5.1875, 89.513013937957834087706670952561002466}, + {5.2500, 95.285757988514588780586084642381131013}, + {5.3125, 101.430833209098212357990123684449846912}, + {5.3750, 107.972251614673824873137995865940755392}, + {5.4375, 114.935573939814969189535554289886848550}, + {5.5000, 122.348009517829425991091207107262038316}, + {5.5625, 130.238522601820409078244923165746295574}, + {5.6250, 138.637945543134998069351279801575968875}, + {5.6875, 147.579099269447055276899288971207106581}, + {5.7500, 157.096921533245353905868840194264636395}, + {5.8125, 167.228603431860671946045256541679445836}, + {5.8750, 178.013734732486824390148614309727161925}, + {5.9375, 189.494458570056311567917444025807275896}, + {6.0000, 201.715636122455894483405112855409538488}, + {6.0625, 214.725021906554080628430756558271312513}, + {6.1250, 228.573450380013557089736092321068279231}, + {6.1875, 243.315034578039208138752165587134488645}, + {6.2500, 259.007377561239126824465367865430519592}, + {6.3125, 275.711797500835732516530131577254654076}, + {6.3750, 293.493567280752348242602902925987643443}, + {6.4375, 312.422169552825597994104814531010579387}, + {6.5000, 332.571568241777409133204438572983297292}, + {6.5625, 354.020497560858198165985214519757890505}, + {6.6250, 376.852769667496146326030849450983914197}, + {6.6875, 401.157602161123700280816957271992998156}, + {6.7500, 427.029966702886171977469256622451185850}, + {6.8125, 454.570960119471524953536004647195906721}, + {6.8750, 483.888199441157626584508920036981010995}, + {6.9375, 515.096242417696720610477570797503766179}, + {7.0000, 548.317035155212076889964120712102928484}, + {7.0625, 583.680388623257719787307547662358502345}, + {7.1250, 621.324485894002926216918634755431456031}, + {7.1875, 661.396422095589629755266517362992812037}, + {7.2500, 704.052779189542208784574955807004218856}, + {7.3125, 749.460237818184878095966335081928645934}, + {7.3750, 797.796228612873763671070863694973560629}, + {7.4375, 849.249625508044731271830060572510241864}, + {7.5000, 904.021483770216677368692292389446994987}, + {7.5625, 962.325825625814651122171697031114091993}, + {7.6250, 1024.390476557670599008492465853663578558}, + {7.6875, 1090.457955538048482588540574008226583335}, + {7.7500, 1160.786422676798661020094043586456606003}, + {7.8125, 1235.650687987597295222707689125107720568}, + {7.8750, 1315.343285214046776004329388551335841550}, + {7.9375, 1400.175614911635999247504386054087931958}, + {8.0000, 1490.479161252178088627715460421007179728}, + {8.0625, 1586.606787305415349050508956232945539108}, + {8.1250, 1688.934113859132470361718199038326340668}, + {8.1875, 1797.860987165547537276364148450577336075}, + {8.2500, 1913.813041349231764486365114317586148767}, + {8.3125, 2037.243361581700856522236313401822532385}, + {8.3750, 2168.634254521568851112005905503069409349}, + {8.4375, 2308.499132938297821208734949028296170563}, + {8.5000, 2457.384521883751693037774022640629666294}, + {8.5625, 2615.872194250713123494312356053193077854}, + {8.6250, 2784.581444063104750127653362960649823247}, + {8.6875, 2964.171506380845754878370650565756538203}, + {8.7500, 3155.344133275174556354775488913749659006}, + {8.8125, 3358.846335940117183452010789979584950102}, + {8.8750, 3575.473303654961482727206202358956274888}, + {8.9375, 3806.071511003646460448021740303914939059}, + {9.0000, 4051.542025492594047194773093534725371440}, + {9.0625, 4312.844028491571841588188869958240355518}, + {9.1250, 4590.998563255739769060078863130940205710}, + {9.1875, 4887.092524674358252509551443117048351290}, + {9.2500, 5202.282906336187674588222835339193136030}, + {9.3125, 5537.801321507079474415176386655744387251}, + {9.3750, 5894.958815685577062811620236195525504885}, + {9.4375, 6275.150989541692149890530417987358096221}, + {9.5000, 6679.863452256851081801173722051940058824}, + {9.5625, 7110.677626574055535297758456126491707647}, + {9.6250, 7569.276928241617224537226019600213961572}, + {9.6875, 8057.453343996777301036241026375049070162}, + {9.7500, 8577.114433792824387959788368429252257664}, + {9.8125, 9130.290784631065880205118262838330689429}, + {9.8750, 9719.143945123662919857326995631317996715}, + {9.9375, 10345.974871791805753327922796701684092861}, + {10.0000, 11013.232920103323139721376090437880844591}, + }; + + for(int i = 0; i < testCases.length; i++) { + double [] testCase = testCases[i]; + failures += testCoshCaseWithUlpDiff(testCase[0], + testCase[1], + 3.0); + } + + + double [][] specialTestCases = { + {0.0, 1.0}, + {NaNd, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY} + }; + + for(int i = 0; i < specialTestCases.length; i++ ) { + failures += testCoshCaseWithUlpDiff(specialTestCases[i][0], + specialTestCases[i][1], + 0.0); + } + + // For powers of 2 less than 2^(-27), the second and + // subsequent terms of the Taylor series expansion will get + // rounded. + + for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { + double d = FpUtils.scalb(2.0, i); + + // Result and expected are the same. + failures += testCoshCaseWithUlpDiff(d, 1.0, 2.5); + } + + // For values of x larger than 22, the e^(-x) term is + // insignificant to the floating-point result. Util exp(x) + // overflows around 709.8, cosh(x) ~= exp(x)/2; will will test + // 10000 values in this range. + + long trans22 = Double.doubleToLongBits(22.0); + // (approximately) largest value such that exp shouldn't + // overflow + long transExpOvfl = Double.doubleToLongBits(FpUtils.nextDown(709.7827128933841)); + + for(long i = trans22; + i < transExpOvfl; + i +=(transExpOvfl-trans22)/10000) { + + double d = Double.longBitsToDouble(i); + + // Allow 3.5 ulps of error to deal with error in exp. + failures += testCoshCaseWithUlpDiff(d, StrictMath.exp(d)*0.5, 3.5); + } + + // (approximately) largest value such that cosh shouldn't + // overflow. + long transCoshOvfl = Double.doubleToLongBits(710.4758600739439); + + // Make sure sinh(x) doesn't overflow as soon as exp(x) + // overflows. + + /* + * For large values of x, cosh(x) ~= 0.5*(e^x). Therefore, + * + * cosh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5) + * + * So, we can calculate the approximate expected result as + * exp(x + -0.693147186). However, this sum suffers from + * roundoff, limiting the accuracy of the approximation. The + * accuracy can be improved by recovering the rounded-off + * information. Since x is larger than ln(0.5), the trailing + * bits of ln(0.5) get rounded away when the two values are + * added. However, high-order bits of ln(0.5) that + * contribute to the sum can be found: + * + * offset = log(0.5); + * effective_offset = (x + offset) - x; // exact subtraction + * rounded_away_offset = offset - effective_offset; // exact subtraction + * + * Therefore, the product + * + * exp(x + offset)*exp(rounded_away_offset) + * + * will be a better approximation to the exact value of + * + * e^(x + offset) + * + * than exp(x+offset) alone. (The expected result cannot be + * computed as exp(x)*exp(offset) since exp(x) by itself would + * overflow to infinity.) + */ + double offset = StrictMath.log(0.5); + for(long i = transExpOvfl+1; i < transCoshOvfl; + i += (transCoshOvfl-transExpOvfl)/1000 ) { + double input = Double.longBitsToDouble(i); + + double expected = + StrictMath.exp(input + offset) * + StrictMath.exp( offset - ((input + offset) - input) ); + + failures += testCoshCaseWithUlpDiff(input, expected, 4.0); + } + + // cosh(x) overflows for values greater than 710; in + // particular, it overflows for all 2^i, i > 10. + for(int i = 10; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = FpUtils.scalb(2.0, i); + + // Result and expected are the same. + failures += testCoshCaseWithUlpDiff(d, + Double.POSITIVE_INFINITY, 0.0); + } + return failures; + } + + public static int testCoshCaseWithTolerance(double input, + double expected, + double tolerance) { + int failures = 0; + failures += Tests.testTolerance("Math.cosh(double)", + input, Math.cosh(input), + expected, tolerance); + failures += Tests.testTolerance("Math.cosh(double)", + -input, Math.cosh(-input), + expected, tolerance); + + failures += Tests.testTolerance("StrictMath.cosh(double)", + input, StrictMath.cosh(input), + expected, tolerance); + failures += Tests.testTolerance("StrictMath.cosh(double)", + -input, StrictMath.cosh(-input), + expected, tolerance); + return failures; + } + + public static int testCoshCaseWithUlpDiff(double input, + double expected, + double ulps) { + int failures = 0; + failures += Tests.testUlpDiff("Math.cosh(double)", + input, Math.cosh(input), + expected, ulps); + failures += Tests.testUlpDiff("Math.cosh(double)", + -input, Math.cosh(-input), + expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.cosh(double)", + input, StrictMath.cosh(input), + expected, ulps); + failures += Tests.testUlpDiff("StrictMath.cosh(double)", + -input, StrictMath.cosh(-input), + expected, ulps); + return failures; + } + + + /** + * Test accuracy of {Math, StrictMath}.tanh. The specified + * accuracy is 2.5 ulps. + * + * The defintion of tanh(x) is + * + * (e^x - e^(-x))/(e^x + e^(-x)) + * + * The series expansion of tanh(x) = + * + * x - x^3/3 + 2x^5/15 - 17x^7/315 + ... + * + * Therefore, + * + * 1. For large values of x tanh(x) ~= signum(x) + * + * 2. For small values of x, tanh(x) ~= x. + * + * Additionally, tanh is an odd function; tanh(-x) = -tanh(x). + * + */ + static int testTanh() { + int failures = 0; + /* + * Array elements below generated using a quad sinh + * implementation. Rounded to a double, the quad result + * *should* be correctly rounded, unless we are quite unlucky. + * Assuming the quad value is a correctly rounded double, the + * allowed error is 3.0 ulps instead of 2.5 since the quad + * value rounded to double can have its own 1/2 ulp error. + */ + double [][] testCases = { + // x tanh(x) + {0.0625, 0.06241874674751251449014289119421133}, + {0.1250, 0.12435300177159620805464727580589271}, + {0.1875, 0.18533319990813951753211997502482787}, + {0.2500, 0.24491866240370912927780113149101697}, + {0.3125, 0.30270972933210848724239738970991712}, + {0.3750, 0.35835739835078594631936023155315807}, + {0.4375, 0.41157005567402245143207555859415687}, + {0.5000, 0.46211715726000975850231848364367256}, + {0.5625, 0.50982997373525658248931213507053130}, + {0.6250, 0.55459972234938229399903909532308371}, + {0.6875, 0.59637355547924233984437303950726939}, + {0.7500, 0.63514895238728731921443435731249638}, + {0.8125, 0.67096707420687367394810954721913358}, + {0.8750, 0.70390560393662106058763026963135371}, + {0.9375, 0.73407151960434149263991588052503660}, + {1.0000, 0.76159415595576488811945828260479366}, + {1.0625, 0.78661881210869761781941794647736081}, + {1.1250, 0.80930107020178101206077047354332696}, + {1.1875, 0.82980190998595952708572559629034476}, + {1.2500, 0.84828363995751289761338764670750445}, + {1.3125, 0.86490661772074179125443141102709751}, + {1.3750, 0.87982669965198475596055310881018259}, + {1.4375, 0.89319334040035153149249598745889365}, + {1.5000, 0.90514825364486643824230369645649557}, + {1.5625, 0.91582454416876231820084311814416443}, + {1.6250, 0.92534622531174107960457166792300374}, + {1.6875, 0.93382804322259173763570528576138652}, + {1.7500, 0.94137553849728736226942088377163687}, + {1.8125, 0.94808528560440629971240651310180052}, + {1.8750, 0.95404526017994877009219222661968285}, + {1.9375, 0.95933529331468249183399461756952555}, + {2.0000, 0.96402758007581688394641372410092317}, + {2.0625, 0.96818721657637057702714316097855370}, + {2.1250, 0.97187274591350905151254495374870401}, + {2.1875, 0.97513669829362836159665586901156483}, + {2.2500, 0.97802611473881363992272924300618321}, + {2.3125, 0.98058304703705186541999427134482061}, + {2.3750, 0.98284502917257603002353801620158861}, + {2.4375, 0.98484551746427837912703608465407824}, + {2.5000, 0.98661429815143028888127603923734964}, + {2.5625, 0.98817786228751240824802592958012269}, + {2.6250, 0.98955974861288320579361709496051109}, + {2.6875, 0.99078085564125158320311117560719312}, + {2.7500, 0.99185972456820774534967078914285035}, + {2.8125, 0.99281279483715982021711715899682324}, + {2.8750, 0.99365463431502962099607366282699651}, + {2.9375, 0.99439814606575805343721743822723671}, + {3.0000, 0.99505475368673045133188018525548849}, + {3.0625, 0.99563456710930963835715538507891736}, + {3.1250, 0.99614653067334504917102591131792951}, + {3.1875, 0.99659855517712942451966113109487039}, + {3.2500, 0.99699763548652601693227592643957226}, + {3.3125, 0.99734995516557367804571991063376923}, + {3.3750, 0.99766097946988897037219469409451602}, + {3.4375, 0.99793553792649036103161966894686844}, + {3.5000, 0.99817789761119870928427335245061171}, + {3.5625, 0.99839182812874152902001617480606320}, + {3.6250, 0.99858065920179882368897879066418294}, + {3.6875, 0.99874733168378115962760304582965538}, + {3.7500, 0.99889444272615280096784208280487888}, + {3.8125, 0.99902428575443546808677966295308778}, + {3.8750, 0.99913888583735077016137617231569011}, + {3.9375, 0.99924003097049627100651907919688313}, + {4.0000, 0.99932929973906704379224334434172499}, + {4.0625, 0.99940808577297384603818654530731215}, + {4.1250, 0.99947761936180856115470576756499454}, + {4.1875, 0.99953898655601372055527046497863955}, + {4.2500, 0.99959314604388958696521068958989891}, + {4.3125, 0.99964094406130644525586201091350343}, + {4.3750, 0.99968312756179494813069349082306235}, + {4.4375, 0.99972035584870534179601447812936151}, + {4.5000, 0.99975321084802753654050617379050162}, + {4.5625, 0.99978220617994689112771768489030236}, + {4.6250, 0.99980779516900105210240981251048167}, + {4.6875, 0.99983037791655283849546303868853396}, + {4.7500, 0.99985030754497877753787358852000255}, + {4.8125, 0.99986789571029070417475400133989992}, + {4.8750, 0.99988341746867772271011794614780441}, + {4.9375, 0.99989711557251558205051185882773206}, + {5.0000, 0.99990920426259513121099044753447306}, + {5.0625, 0.99991987261554158551063867262784721}, + {5.1250, 0.99992928749851651137225712249720606}, + {5.1875, 0.99993759617721206697530526661105307}, + {5.2500, 0.99994492861777083305830639416802036}, + {5.3125, 0.99995139951851344080105352145538345}, + {5.3750, 0.99995711010315817210152906092289064}, + {5.4375, 0.99996214970350792531554669737676253}, + {5.5000, 0.99996659715630380963848952941756868}, + {5.5625, 0.99997052203605101013786592945475432}, + {5.6250, 0.99997398574306704793434088941484766}, + {5.6875, 0.99997704246374583929961850444364696}, + {5.7500, 0.99997974001803825215761760428815437}, + {5.8125, 0.99998212060739040166557477723121777}, + {5.8750, 0.99998422147482750993344503195672517}, + {5.9375, 0.99998607548749972326220227464612338}, + {6.0000, 0.99998771165079557056434885235523206}, + {6.0625, 0.99998915556205996764518917496149338}, + {6.1250, 0.99999042981101021976277974520745310}, + {6.1875, 0.99999155433311068015449574811497719}, + {6.2500, 0.99999254672143162687722782398104276}, + {6.3125, 0.99999342250186907900400800240980139}, + {6.3750, 0.99999419537602957780612639767025158}, + {6.4375, 0.99999487743557848265406225515388994}, + {6.5000, 0.99999547935140419285107893831698753}, + {6.5625, 0.99999601054055694588617385671796346}, + {6.6250, 0.99999647931357331502887600387959900}, + {6.6875, 0.99999689300449080997594368612277442}, + {6.7500, 0.99999725808558628431084200832778748}, + {6.8125, 0.99999758026863294516387464046135924}, + {6.8750, 0.99999786459425991170635407313276785}, + {6.9375, 0.99999811551081218572759991597586905}, + {7.0000, 0.99999833694394467173571641595066708}, + {7.0625, 0.99999853235803894918375164252059190}, + {7.1250, 0.99999870481040359014665019356422927}, + {7.1875, 0.99999885699910593255108365463415411}, + {7.2500, 0.99999899130518359709674536482047025}, + {7.3125, 0.99999910982989611769943303422227663}, + {7.3750, 0.99999921442759946591163427422888252}, + {7.4375, 0.99999930673475777603853435094943258}, + {7.5000, 0.99999938819554614875054970643513124}, + {7.5625, 0.99999946008444508183970109263856958}, + {7.6250, 0.99999952352618001331402589096040117}, + {7.6875, 0.99999957951331792817413683491979752}, + {7.7500, 0.99999962892179632633374697389145081}, + {7.8125, 0.99999967252462750190604116210421169}, + {7.8750, 0.99999971100399253750324718031574484}, + {7.9375, 0.99999974496191422474977283863588658}, + {8.0000, 0.99999977492967588981001883295636840}, + {8.0625, 0.99999980137613348259726597081723424}, + {8.1250, 0.99999982471505097353529823063673263}, + {8.1875, 0.99999984531157382142423402736529911}, + {8.2500, 0.99999986348794179107425910499030547}, + {8.3125, 0.99999987952853049895833839645847571}, + {8.3750, 0.99999989368430056302584289932834041}, + {8.4375, 0.99999990617672396471542088609051728}, + {8.5000, 0.99999991720124905211338798152800748}, + {8.5625, 0.99999992693035839516545287745322387}, + {8.6250, 0.99999993551626733394129009365703767}, + {8.6875, 0.99999994309330543951799157347876934}, + {8.7500, 0.99999994978001814614368429416607424}, + {8.8125, 0.99999995568102143535399207289008504}, + {8.8750, 0.99999996088863858914831986187674522}, + {8.9375, 0.99999996548434461974481685677429908}, + {9.0000, 0.99999996954004097447930211118358244}, + {9.0625, 0.99999997311918045901919121395899372}, + {9.1250, 0.99999997627775997868467948564005257}, + {9.1875, 0.99999997906519662964368381583648379}, + {9.2500, 0.99999998152510084671976114264303159}, + {9.3125, 0.99999998369595870397054673668361266}, + {9.3750, 0.99999998561173404286033236040150950}, + {9.4375, 0.99999998730239984852716512979473289}, + {9.5000, 0.99999998879440718770812040917618843}, + {9.5625, 0.99999999011109904501789298212541698}, + {9.6250, 0.99999999127307553219220251303121960}, + {9.6875, 0.99999999229851618412119275358396363}, + {9.7500, 0.99999999320346438410630581726217930}, + {9.8125, 0.99999999400207836827291739324060736}, + {9.8750, 0.99999999470685273619047001387577653}, + {9.9375, 0.99999999532881393331131526966058758}, + {10.0000, 0.99999999587769276361959283713827574}, + }; + + for(int i = 0; i < testCases.length; i++) { + double [] testCase = testCases[i]; + failures += testTanhCaseWithUlpDiff(testCase[0], + testCase[1], + 3.0); + } + + + double [][] specialTestCases = { + {0.0, 0.0}, + {NaNd, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.POSITIVE_INFINITY, 1.0} + }; + + for(int i = 0; i < specialTestCases.length; i++) { + failures += testTanhCaseWithUlpDiff(specialTestCases[i][0], + specialTestCases[i][1], + 0.0); + } + + // For powers of 2 less than 2^(-27), the second and + // subsequent terms of the Taylor series expansion will get + // rounded away since |n-n^3| > 53, the binary precision of a + // double significand. + + for(int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) { + double d = FpUtils.scalb(2.0, i); + + // Result and expected are the same. + failures += testTanhCaseWithUlpDiff(d, d, 2.5); + } + + // For values of x larger than 22, tanh(x) is 1.0 in double + // floating-point arithmetic. + + for(int i = 22; i < 32; i++) { + failures += testTanhCaseWithUlpDiff(i, 1.0, 2.5); + } + + for(int i = 5; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = FpUtils.scalb(2.0, i); + + failures += testTanhCaseWithUlpDiff(d, 1.0, 2.5); + } + + return failures; + } + + public static int testTanhCaseWithTolerance(double input, + double expected, + double tolerance) { + int failures = 0; + failures += Tests.testTolerance("Math.tanh(double", + input, Math.tanh(input), + expected, tolerance); + failures += Tests.testTolerance("Math.tanh(double", + -input, Math.tanh(-input), + -expected, tolerance); + + failures += Tests.testTolerance("StrictMath.tanh(double", + input, StrictMath.tanh(input), + expected, tolerance); + failures += Tests.testTolerance("StrictMath.tanh(double", + -input, StrictMath.tanh(-input), + -expected, tolerance); + return failures; + } + + public static int testTanhCaseWithUlpDiff(double input, + double expected, + double ulps) { + int failures = 0; + + failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)", + input, Math.tanh(input), + expected, ulps, 1.0); + failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)", + -input, Math.tanh(-input), + -expected, ulps, 1.0); + + failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)", + input, StrictMath.tanh(input), + expected, ulps, 1.0); + failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)", + -input, StrictMath.tanh(-input), + -expected, ulps, 1.0); + return failures; + } + + + public static void main(String argv[]) { + int failures = 0; + + failures += testSinh(); + failures += testCosh(); + failures += testTanh(); + + if (failures > 0) { + System.err.println("Testing the hyperbolic functions incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/HypotTests.java b/jdk/test/java/lang/Math/HypotTests.java new file mode 100644 index 00000000000..587b7b2d250 --- /dev/null +++ b/jdk/test/java/lang/Math/HypotTests.java @@ -0,0 +1,245 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 4939441 + * @summary Tests for {Math, StrictMath}.hypot + * @author Joseph D. Darcy + */ + +import sun.misc.DoubleConsts; +import sun.misc.FpUtils; + +public class HypotTests { + private HypotTests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + static final double NaNd = Double.NaN; + + /** + * Given integers m and n, assuming m < n, the triple (n^2 - m^2, + * 2mn, and n^2 + m^2) is a Pythagorean triple with a^2 + b^2 = + * c^2. This methods returns a long array holding the Pythagorean + * triple corresponding to the inputs. + */ + static long [] pythagoreanTriple(int m, int n) { + long M = m; + long N = n; + long result[] = new long[3]; + + + result[0] = Math.abs(M*M - N*N); + result[1] = Math.abs(2*M*N); + result[2] = Math.abs(M*M + N*N); + + return result; + } + + static int testHypot() { + int failures = 0; + + double [][] testCases = { + // Special cases + {infinityD, infinityD, infinityD}, + {infinityD, 0.0, infinityD}, + {infinityD, 1.0, infinityD}, + {infinityD, NaNd, infinityD}, + {NaNd, NaNd, NaNd}, + {0.0, NaNd, NaNd}, + {1.0, NaNd, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), 1.0, NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), 1.0, NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), 1.0, NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), 1.0, NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), 1.0, NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), 1.0, NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), 1.0, NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), 1.0, NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), 1.0, NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), 1.0, NaNd}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testHypotCase(testCases[i][0], testCases[i][1], + testCases[i][2]); + } + + // Verify hypot(x, 0.0) is close to x over the entire exponent + // range. + for(int i = DoubleConsts.MIN_SUB_EXPONENT; + i <= DoubleConsts.MAX_EXPONENT; + i++) { + double input = FpUtils.scalb(2, i); + failures += testHypotCase(input, 0.0, input); + } + + + // Test Pythagorean triples + + // Small ones + for(int m = 1; m < 10; m++) { + for(int n = m+1; n < 11; n++) { + long [] result = pythagoreanTriple(m, n); + failures += testHypotCase(result[0], result[1], result[2]); + } + } + + // Big ones + for(int m = 100000; m < 100100; m++) { + for(int n = m+100000; n < 200200; n++) { + long [] result = pythagoreanTriple(m, n); + failures += testHypotCase(result[0], result[1], result[2]); + } + } + + // Approaching overflow tests + + /* + * Create a random value r with an large-ish exponent. The + * result of hypot(3*r, 4*r) should be approximately 5*r. (The + * computation of 4*r is exact since it just changes the + * exponent). While the exponent of r is less than or equal + * to (MAX_EXPONENT - 3), the computation should not overflow. + */ + java.util.Random rand = new java.util.Random(); + for(int i = 0; i < 1000; i++) { + double d = rand.nextDouble(); + // Scale d to have an exponent equal to MAX_EXPONENT -15 + d = FpUtils.scalb(d, DoubleConsts.MAX_EXPONENT + -15 - FpUtils.ilogb(d)); + for(int j = 0; j <= 13; j += 1) { + failures += testHypotCase(3*d, 4*d, 5*d, 2.5); + d *= 2.0; // increase exponent by 1 + } + } + + // Test for monotonicity failures. Fix one argument and test + // two numbers before and two numbers after each chosen value; + // i.e. + // + // pcNeighbors[] = + // {nextDown(nextDown(pc)), + // nextDown(pc), + // pc, + // nextUp(pc), + // nextUp(nextUp(pc))} + // + // and we test that hypot(pcNeighbors[i]) <= hypot(pcNeighbors[i+1]) + { + double pcNeighbors[] = new double[5]; + double pcNeighborsHypot[] = new double[5]; + double pcNeighborsStrictHypot[] = new double[5]; + + + for(int i = -18; i <= 18; i++) { + double pc = FpUtils.scalb(1.0, i); + + pcNeighbors[2] = pc; + pcNeighbors[1] = FpUtils.nextDown(pc); + pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); + pcNeighbors[3] = FpUtils.nextUp(pc); + pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + + for(int j = 0; j < pcNeighbors.length; j++) { + pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]); + pcNeighborsStrictHypot[j] = StrictMath.hypot(2.0, pcNeighbors[j]); + } + + for(int j = 0; j < pcNeighborsHypot.length-1; j++) { + if(pcNeighborsHypot[j] > pcNeighborsHypot[j+1] ) { + failures++; + System.err.println("Monotonicity failure for Math.hypot on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsHypot[j] + " and " + + pcNeighborsHypot[j+1] ); + } + + if(pcNeighborsStrictHypot[j] > pcNeighborsStrictHypot[j+1] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.hypot on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsStrictHypot[j] + " and " + + pcNeighborsStrictHypot[j+1] ); + } + + + } + + } + } + + + return failures; + } + + static int testHypotCase(double input1, double input2, double expected) { + return testHypotCase(input1,input2, expected, 1); + } + + static int testHypotCase(double input1, double input2, double expected, + double ulps) { + int failures = 0; + if (expected < 0.0) { + throw new AssertionError("Result of hypot must be greater than " + + "or equal to zero"); + } + + // Test Math and StrictMath methods with no inputs negated, + // each input negated singly, and both inputs negated. Also + // test inputs in reversed order. + + for(int i = -1; i <= 1; i+=2) { + for(int j = -1; j <= 1; j+=2) { + double x = i * input1; + double y = j * input2; + failures += Tests.testUlpDiff("Math.hypot", x, y, + Math.hypot(x, y), expected, ulps); + failures += Tests.testUlpDiff("Math.hypot", y, x, + Math.hypot(y, x ), expected, ulps); + + failures += Tests.testUlpDiff("StrictMath.hypot", x, y, + StrictMath.hypot(x, y), expected, ulps); + failures += Tests.testUlpDiff("StrictMath.hypot", y, x, + StrictMath.hypot(y, x), expected, ulps); + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += testHypot(); + + if (failures > 0) { + System.err.println("Testing the hypot incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/IeeeRecommendedTests.java b/jdk/test/java/lang/Math/IeeeRecommendedTests.java new file mode 100644 index 00000000000..4123451ed5d --- /dev/null +++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java @@ -0,0 +1,1705 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4860891 4826732 4780454 4939441 4826652 + * @summary Tests for IEEE 754[R] recommended functions and similar methods + * @author Joseph D. Darcy + * @compile -source 1.5 IeeeRecommendedTests.java + * @run main IeeeRecommendedTests + */ + +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; +import sun.misc.FloatConsts; + +public class IeeeRecommendedTests { + private IeeeRecommendedTests(){} + + static final float NaNf = Float.NaN; + static final double NaNd = Double.NaN; + static final float infinityF = Float.POSITIVE_INFINITY; + static final double infinityD = Double.POSITIVE_INFINITY; + + static final float Float_MAX_VALUEmm = 0x1.fffffcP+127f; + static final float Float_MAX_SUBNORMAL = 0x0.fffffeP-126f; + static final float Float_MAX_SUBNORMALmm = 0x0.fffffcP-126f; + + static final double Double_MAX_VALUEmm = 0x1.ffffffffffffeP+1023; + static final double Double_MAX_SUBNORMAL = 0x0.fffffffffffffP-1022; + static final double Double_MAX_SUBNORMALmm = 0x0.ffffffffffffeP-1022; + + // Initialize shared random number generator + static java.util.Random rand = new java.util.Random(); + + /** + * Returns a floating-point power of two in the normal range. + */ + static double powerOfTwoD(int n) { + return Double.longBitsToDouble((((long)n + (long)DoubleConsts.MAX_EXPONENT) << + (DoubleConsts.SIGNIFICAND_WIDTH-1)) + & DoubleConsts.EXP_BIT_MASK); + } + + /** + * Returns a floating-point power of two in the normal range. + */ + static float powerOfTwoF(int n) { + return Float.intBitsToFloat(((n + FloatConsts.MAX_EXPONENT) << + (FloatConsts.SIGNIFICAND_WIDTH-1)) + & FloatConsts.EXP_BIT_MASK); + } + + /* ******************** getExponent tests ****************************** */ + + /* + * The tests for getExponent should test the special values (NaN, +/- + * infinity, etc.), test the endpoints of each binade (set of + * floating-point values with the same exponent), and for good + * measure, test some random values within each binade. Testing + * the endpoints of each binade includes testing both positive and + * negative numbers. Subnormal values with different normalized + * exponents should be tested too. Both Math and StrictMath + * methods should return the same results. + */ + + /* + * Test Math.getExponent and StrictMath.getExponent with +d and -d. + */ + static int testGetExponentCase(float f, int expected) { + float minus_f = -f; + int failures=0; + + failures+=Tests.test("Math.getExponent(float)", f, + Math.getExponent(f), expected); + failures+=Tests.test("Math.getExponent(float)", minus_f, + Math.getExponent(minus_f), expected); + + failures+=Tests.test("StrictMath.getExponent(float)", f, + StrictMath.getExponent(f), expected); + failures+=Tests.test("StrictMath.getExponent(float)", minus_f, + StrictMath.getExponent(minus_f), expected); + return failures; + } + + /* + * Test Math.getExponent and StrictMath.getExponent with +d and -d. + */ + static int testGetExponentCase(double d, int expected) { + double minus_d = -d; + int failures=0; + + failures+=Tests.test("Math.getExponent(double)", d, + Math.getExponent(d), expected); + failures+=Tests.test("Math.getExponent(double)", minus_d, + Math.getExponent(minus_d), expected); + + failures+=Tests.test("StrictMath.getExponent(double)", d, + StrictMath.getExponent(d), expected); + failures+=Tests.test("StrictMath.getExponent(double)", minus_d, + StrictMath.getExponent(minus_d), expected); + return failures; + } + + public static int testFloatGetExponent() { + int failures = 0; + float [] specialValues = {NaNf, + Float.POSITIVE_INFINITY, + +0.0f, + +1.0f, + +2.0f, + +16.0f, + +Float.MIN_VALUE, + +Float_MAX_SUBNORMAL, + +FloatConsts.MIN_NORMAL, + +Float.MAX_VALUE + }; + + int [] specialResults = {Float.MAX_EXPONENT + 1, // NaN results + Float.MAX_EXPONENT + 1, // Infinite results + Float.MIN_EXPONENT - 1, // Zero results + 0, + 1, + 4, + FloatConsts.MIN_EXPONENT - 1, + -FloatConsts.MAX_EXPONENT, + FloatConsts.MIN_EXPONENT, + FloatConsts.MAX_EXPONENT + }; + + // Special value tests + for(int i = 0; i < specialValues.length; i++) { + failures += testGetExponentCase(specialValues[i], specialResults[i]); + } + + + // Normal exponent tests + for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) { + int result; + + // Create power of two + float po2 = powerOfTwoF(i); + + failures += testGetExponentCase(po2, i); + + // Generate some random bit patterns for the significand + for(int j = 0; j < 10; j++) { + int randSignif = rand.nextInt(); + float randFloat; + + randFloat = Float.intBitsToFloat( // Exponent + (Float.floatToIntBits(po2)& + (~FloatConsts.SIGNIF_BIT_MASK)) | + // Significand + (randSignif & + FloatConsts.SIGNIF_BIT_MASK) ); + + failures += testGetExponentCase(randFloat, i); + } + + if (i > FloatConsts.MIN_EXPONENT) { + float po2minus = FpUtils.nextAfter(po2, + Float.NEGATIVE_INFINITY); + failures += testGetExponentCase(po2minus, i-1); + } + } + + // Subnormal exponent tests + + /* + * Start with MIN_VALUE, left shift, test high value, low + * values, and random in between. + * + * Use nextAfter to calculate, high value of previous binade, + * loop count i will indicate how many random bits, if any are + * needed. + */ + + float top=Float.MIN_VALUE; + for( int i = 1; + i < FloatConsts.SIGNIFICAND_WIDTH; + i++, top *= 2.0f) { + + failures += testGetExponentCase(top, + FloatConsts.MIN_EXPONENT - 1); + + // Test largest value in next smaller binade + if (i >= 3) {// (i == 1) would test 0.0; + // (i == 2) would just retest MIN_VALUE + testGetExponentCase(FpUtils.nextAfter(top, 0.0f), + FloatConsts.MIN_EXPONENT - 1); + + if( i >= 10) { + // create a bit mask with (i-1) 1's in the low order + // bits + int mask = ~((~0)<<(i-1)); + float randFloat = Float.intBitsToFloat( // Exponent + Float.floatToIntBits(top) | + // Significand + (rand.nextInt() & mask ) ) ; + + failures += testGetExponentCase(randFloat, + FloatConsts.MIN_EXPONENT - 1); + } + } + } + + return failures; + } + + + public static int testDoubleGetExponent() { + int failures = 0; + double [] specialValues = {NaNd, + infinityD, + +0.0, + +1.0, + +2.0, + +16.0, + +Double.MIN_VALUE, + +Double_MAX_SUBNORMAL, + +DoubleConsts.MIN_NORMAL, + +Double.MAX_VALUE + }; + + int [] specialResults = {Double.MAX_EXPONENT + 1, // NaN results + Double.MAX_EXPONENT + 1, // Infinite results + Double.MIN_EXPONENT - 1, // Zero results + 0, + 1, + 4, + DoubleConsts.MIN_EXPONENT - 1, + -DoubleConsts.MAX_EXPONENT, + DoubleConsts.MIN_EXPONENT, + DoubleConsts.MAX_EXPONENT + }; + + // Special value tests + for(int i = 0; i < specialValues.length; i++) { + failures += testGetExponentCase(specialValues[i], specialResults[i]); + } + + + // Normal exponent tests + for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) { + int result; + + // Create power of two + double po2 = powerOfTwoD(i); + + failures += testGetExponentCase(po2, i); + + // Generate some random bit patterns for the significand + for(int j = 0; j < 10; j++) { + long randSignif = rand.nextLong(); + double randFloat; + + randFloat = Double.longBitsToDouble( // Exponent + (Double.doubleToLongBits(po2)& + (~DoubleConsts.SIGNIF_BIT_MASK)) | + // Significand + (randSignif & + DoubleConsts.SIGNIF_BIT_MASK) ); + + failures += testGetExponentCase(randFloat, i); + } + + if (i > DoubleConsts.MIN_EXPONENT) { + double po2minus = FpUtils.nextAfter(po2, + Double.NEGATIVE_INFINITY); + failures += testGetExponentCase(po2minus, i-1); + } + } + + // Subnormal exponent tests + + /* + * Start with MIN_VALUE, left shift, test high value, low + * values, and random in between. + * + * Use nextAfter to calculate, high value of previous binade; + * loop count i will indicate how many random bits, if any are + * needed. + */ + + double top=Double.MIN_VALUE; + for( int i = 1; + i < DoubleConsts.SIGNIFICAND_WIDTH; + i++, top *= 2.0f) { + + failures += testGetExponentCase(top, + DoubleConsts.MIN_EXPONENT - 1); + + // Test largest value in next smaller binade + if (i >= 3) {// (i == 1) would test 0.0; + // (i == 2) would just retest MIN_VALUE + testGetExponentCase(FpUtils.nextAfter(top, 0.0), + DoubleConsts.MIN_EXPONENT - 1); + + if( i >= 10) { + // create a bit mask with (i-1) 1's in the low order + // bits + long mask = ~((~0L)<<(i-1)); + double randFloat = Double.longBitsToDouble( // Exponent + Double.doubleToLongBits(top) | + // Significand + (rand.nextLong() & mask ) ) ; + + failures += testGetExponentCase(randFloat, + DoubleConsts.MIN_EXPONENT - 1); + } + } + } + + return failures; + } + + + /* ******************** nextAfter tests ****************************** */ + + static int testNextAfterCase(float start, double direction, float expected) { + int failures=0; + float minus_start = -start; + double minus_direction = -direction; + float minus_expected = -expected; + + failures+=Tests.test("Math.nextAfter(float,double)", start, direction, + Math.nextAfter(start, direction), expected); + failures+=Tests.test("Math.nextAfter(float,double)", minus_start, minus_direction, + Math.nextAfter(minus_start, minus_direction), minus_expected); + + failures+=Tests.test("StrictMath.nextAfter(float,double)", start, direction, + StrictMath.nextAfter(start, direction), expected); + failures+=Tests.test("StrictMath.nextAfter(float,double)", minus_start, minus_direction, + StrictMath.nextAfter(minus_start, minus_direction), minus_expected); + return failures; + } + + static int testNextAfterCase(double start, double direction, double expected) { + int failures=0; + + double minus_start = -start; + double minus_direction = -direction; + double minus_expected = -expected; + + failures+=Tests.test("Math.nextAfter(double,double)", start, direction, + Math.nextAfter(start, direction), expected); + failures+=Tests.test("Math.nextAfter(double,double)", minus_start, minus_direction, + Math.nextAfter(minus_start, minus_direction), minus_expected); + + failures+=Tests.test("StrictMath.nextAfter(double,double)", start, direction, + StrictMath.nextAfter(start, direction), expected); + failures+=Tests.test("StrictMath.nextAfter(double,double)", minus_start, minus_direction, + StrictMath.nextAfter(minus_start, minus_direction), minus_expected); + return failures; + } + + public static int testFloatNextAfter() { + int failures=0; + + /* + * Each row of the testCases matrix represents one test case + * for nexAfter; given the input of the first two columns, the + * result in the last column is expected. + */ + float [][] testCases = { + {NaNf, NaNf, NaNf}, + {NaNf, 0.0f, NaNf}, + {0.0f, NaNf, NaNf}, + {NaNf, infinityF, NaNf}, + {infinityF, NaNf, NaNf}, + + {infinityF, infinityF, infinityF}, + {infinityF, -infinityF, Float.MAX_VALUE}, + {infinityF, 0.0f, Float.MAX_VALUE}, + + {Float.MAX_VALUE, infinityF, infinityF}, + {Float.MAX_VALUE, -infinityF, Float_MAX_VALUEmm}, + {Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}, + {Float.MAX_VALUE, 0.0f, Float_MAX_VALUEmm}, + + {Float_MAX_VALUEmm, Float.MAX_VALUE, Float.MAX_VALUE}, + {Float_MAX_VALUEmm, infinityF, Float.MAX_VALUE}, + {Float_MAX_VALUEmm, Float_MAX_VALUEmm, Float_MAX_VALUEmm}, + + {FloatConsts.MIN_NORMAL, infinityF, FloatConsts.MIN_NORMAL+ + Float.MIN_VALUE}, + {FloatConsts.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL}, + {FloatConsts.MIN_NORMAL, 1.0f, FloatConsts.MIN_NORMAL+ + Float.MIN_VALUE}, + {FloatConsts.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL}, + {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL}, + + {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL}, + {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL}, + {Float_MAX_SUBNORMAL, 0.0f, Float_MAX_SUBNORMALmm}, + + {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL}, + {Float_MAX_SUBNORMALmm, 0.0f, Float_MAX_SUBNORMALmm-Float.MIN_VALUE}, + {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm}, + + {Float.MIN_VALUE, 0.0f, 0.0f}, + {-Float.MIN_VALUE, 0.0f, -0.0f}, + {Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE}, + {Float.MIN_VALUE, 1.0f, 2*Float.MIN_VALUE}, + + // Make sure zero behavior is tested + {0.0f, 0.0f, 0.0f}, + {0.0f, -0.0f, -0.0f}, + {-0.0f, 0.0f, 0.0f}, + {-0.0f, -0.0f, -0.0f}, + {0.0f, infinityF, Float.MIN_VALUE}, + {0.0f, -infinityF, -Float.MIN_VALUE}, + {-0.0f, infinityF, Float.MIN_VALUE}, + {-0.0f, -infinityF, -Float.MIN_VALUE}, + {0.0f, Float.MIN_VALUE, Float.MIN_VALUE}, + {0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE}, + {-0.0f, Float.MIN_VALUE, Float.MIN_VALUE}, + {-0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE} + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testNextAfterCase(testCases[i][0], testCases[i][1], + testCases[i][2]); + } + + return failures; + } + + public static int testDoubleNextAfter() { + int failures =0; + + /* + * Each row of the testCases matrix represents one test case + * for nexAfter; given the input of the first two columns, the + * result in the last column is expected. + */ + double [][] testCases = { + {NaNd, NaNd, NaNd}, + {NaNd, 0.0d, NaNd}, + {0.0d, NaNd, NaNd}, + {NaNd, infinityD, NaNd}, + {infinityD, NaNd, NaNd}, + + {infinityD, infinityD, infinityD}, + {infinityD, -infinityD, Double.MAX_VALUE}, + {infinityD, 0.0d, Double.MAX_VALUE}, + + {Double.MAX_VALUE, infinityD, infinityD}, + {Double.MAX_VALUE, -infinityD, Double_MAX_VALUEmm}, + {Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE}, + {Double.MAX_VALUE, 0.0d, Double_MAX_VALUEmm}, + + {Double_MAX_VALUEmm, Double.MAX_VALUE, Double.MAX_VALUE}, + {Double_MAX_VALUEmm, infinityD, Double.MAX_VALUE}, + {Double_MAX_VALUEmm, Double_MAX_VALUEmm, Double_MAX_VALUEmm}, + + {DoubleConsts.MIN_NORMAL, infinityD, DoubleConsts.MIN_NORMAL+ + Double.MIN_VALUE}, + {DoubleConsts.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL}, + {DoubleConsts.MIN_NORMAL, 1.0f, DoubleConsts.MIN_NORMAL+ + Double.MIN_VALUE}, + {DoubleConsts.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL}, + {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL}, + + {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL,DoubleConsts.MIN_NORMAL}, + {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL}, + {Double_MAX_SUBNORMAL, 0.0d, Double_MAX_SUBNORMALmm}, + + {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL}, + {Double_MAX_SUBNORMALmm, 0.0d, Double_MAX_SUBNORMALmm-Double.MIN_VALUE}, + {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm}, + + {Double.MIN_VALUE, 0.0d, 0.0d}, + {-Double.MIN_VALUE, 0.0d, -0.0d}, + {Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE}, + {Double.MIN_VALUE, 1.0f, 2*Double.MIN_VALUE}, + + // Make sure zero behavior is tested + {0.0d, 0.0d, 0.0d}, + {0.0d, -0.0d, -0.0d}, + {-0.0d, 0.0d, 0.0d}, + {-0.0d, -0.0d, -0.0d}, + {0.0d, infinityD, Double.MIN_VALUE}, + {0.0d, -infinityD, -Double.MIN_VALUE}, + {-0.0d, infinityD, Double.MIN_VALUE}, + {-0.0d, -infinityD, -Double.MIN_VALUE}, + {0.0d, Double.MIN_VALUE, Double.MIN_VALUE}, + {0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE}, + {-0.0d, Double.MIN_VALUE, Double.MIN_VALUE}, + {-0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE} + }; + + for(int i = 0; i < testCases.length; i++) { + failures += testNextAfterCase(testCases[i][0], testCases[i][1], + testCases[i][2]); + } + return failures; + } + + /* ******************** nextUp tests ********************************* */ + + public static int testFloatNextUp() { + int failures=0; + + /* + * Each row of testCases represents one test case for nextUp; + * the first column is the input and the second column is the + * expected result. + */ + float testCases [][] = { + {NaNf, NaNf}, + {-infinityF, -Float.MAX_VALUE}, + {-Float.MAX_VALUE, -Float_MAX_VALUEmm}, + {-FloatConsts.MIN_NORMAL, -Float_MAX_SUBNORMAL}, + {-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm}, + {-Float.MIN_VALUE, -0.0f}, + {-0.0f, Float.MIN_VALUE}, + {+0.0f, Float.MIN_VALUE}, + {Float.MIN_VALUE, Float.MIN_VALUE*2}, + {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL}, + {Float_MAX_SUBNORMAL, FloatConsts.MIN_NORMAL}, + {FloatConsts.MIN_NORMAL, FloatConsts.MIN_NORMAL+Float.MIN_VALUE}, + {Float_MAX_VALUEmm, Float.MAX_VALUE}, + {Float.MAX_VALUE, infinityF}, + {infinityF, infinityF} + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("Math.nextUp(float)", + testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]); + + failures+=Tests.test("StrictMath.nextUp(float)", + testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + + public static int testDoubleNextUp() { + int failures=0; + + /* + * Each row of testCases represents one test case for nextUp; + * the first column is the input and the second column is the + * expected result. + */ + double testCases [][] = { + {NaNd, NaNd}, + {-infinityD, -Double.MAX_VALUE}, + {-Double.MAX_VALUE, -Double_MAX_VALUEmm}, + {-DoubleConsts.MIN_NORMAL, -Double_MAX_SUBNORMAL}, + {-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm}, + {-Double.MIN_VALUE, -0.0d}, + {-0.0d, Double.MIN_VALUE}, + {+0.0d, Double.MIN_VALUE}, + {Double.MIN_VALUE, Double.MIN_VALUE*2}, + {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL}, + {Double_MAX_SUBNORMAL, DoubleConsts.MIN_NORMAL}, + {DoubleConsts.MIN_NORMAL, DoubleConsts.MIN_NORMAL+Double.MIN_VALUE}, + {Double_MAX_VALUEmm, Double.MAX_VALUE}, + {Double.MAX_VALUE, infinityD}, + {infinityD, infinityD} + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("Math.nextUp(double)", + testCases[i][0], Math.nextUp(testCases[i][0]), testCases[i][1]); + + failures+=Tests.test("StrictMath.nextUp(double)", + testCases[i][0], StrictMath.nextUp(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + /* ******************** nextDown tests ********************************* */ + + public static int testFloatNextDown() { + int failures=0; + + /* + * Each row of testCases represents one test case for nextDown; + * the first column is the input and the second column is the + * expected result. + */ + float testCases [][] = { + {NaNf, NaNf}, + {-infinityF, -infinityF}, + {-Float.MAX_VALUE, -infinityF}, + {-Float_MAX_VALUEmm, -Float.MAX_VALUE}, + {-Float_MAX_SUBNORMAL, -FloatConsts.MIN_NORMAL}, + {-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL}, + {-0.0f, -Float.MIN_VALUE}, + {+0.0f, -Float.MIN_VALUE}, + {Float.MIN_VALUE, 0.0f}, + {Float.MIN_VALUE*2, Float.MIN_VALUE}, + {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm}, + {FloatConsts.MIN_NORMAL, Float_MAX_SUBNORMAL}, + {FloatConsts.MIN_NORMAL+ + Float.MIN_VALUE, FloatConsts.MIN_NORMAL}, + {Float.MAX_VALUE, Float_MAX_VALUEmm}, + {infinityF, Float.MAX_VALUE}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("FpUtils.nextDown(float)", + testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + + public static int testDoubleNextDown() { + int failures=0; + + /* + * Each row of testCases represents one test case for nextDown; + * the first column is the input and the second column is the + * expected result. + */ + double testCases [][] = { + {NaNd, NaNd}, + {-infinityD, -infinityD}, + {-Double.MAX_VALUE, -infinityD}, + {-Double_MAX_VALUEmm, -Double.MAX_VALUE}, + {-Double_MAX_SUBNORMAL, -DoubleConsts.MIN_NORMAL}, + {-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL}, + {-0.0d, -Double.MIN_VALUE}, + {+0.0d, -Double.MIN_VALUE}, + {Double.MIN_VALUE, 0.0d}, + {Double.MIN_VALUE*2, Double.MIN_VALUE}, + {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm}, + {DoubleConsts.MIN_NORMAL, Double_MAX_SUBNORMAL}, + {DoubleConsts.MIN_NORMAL+ + Double.MIN_VALUE, DoubleConsts.MIN_NORMAL}, + {Double.MAX_VALUE, Double_MAX_VALUEmm}, + {infinityD, Double.MAX_VALUE}, + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("FpUtils.nextDown(double)", + testCases[i][0], FpUtils.nextDown(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + + /* ********************** boolean tests ****************************** */ + + /* + * Combined tests for boolean functions, isFinite, isInfinite, + * isNaN, isUnordered. + */ + + public static int testFloatBooleanMethods() { + int failures = 0; + + float testCases [] = { + NaNf, + -infinityF, + infinityF, + -Float.MAX_VALUE, + -3.0f, + -1.0f, + -FloatConsts.MIN_NORMAL, + -Float_MAX_SUBNORMALmm, + -Float_MAX_SUBNORMAL, + -Float.MIN_VALUE, + -0.0f, + +0.0f, + Float.MIN_VALUE, + Float_MAX_SUBNORMALmm, + Float_MAX_SUBNORMAL, + FloatConsts.MIN_NORMAL, + 1.0f, + 3.0f, + Float_MAX_VALUEmm, + Float.MAX_VALUE + }; + + for(int i = 0; i < testCases.length; i++) { + // isNaN + failures+=Tests.test("FpUtils.isNaN(float)", testCases[i], + FpUtils.isNaN(testCases[i]), (i ==0)); + + // isFinite + failures+=Tests.test("FpUtils.isFinite(float)", testCases[i], + FpUtils.isFinite(testCases[i]), (i >= 3)); + + // isInfinite + failures+=Tests.test("FpUtils.isInfinite(float)", testCases[i], + FpUtils.isInfinite(testCases[i]), (i==1 || i==2)); + + // isUnorderd + for(int j = 0; j < testCases.length; j++) { + failures+=Tests.test("FpUtils.isUnordered(float, float)", testCases[i],testCases[j], + FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0)); + } + } + + return failures; + } + + public static int testDoubleBooleanMethods() { + int failures = 0; + boolean result = false; + + double testCases [] = { + NaNd, + -infinityD, + infinityD, + -Double.MAX_VALUE, + -3.0d, + -1.0d, + -DoubleConsts.MIN_NORMAL, + -Double_MAX_SUBNORMALmm, + -Double_MAX_SUBNORMAL, + -Double.MIN_VALUE, + -0.0d, + +0.0d, + Double.MIN_VALUE, + Double_MAX_SUBNORMALmm, + Double_MAX_SUBNORMAL, + DoubleConsts.MIN_NORMAL, + 1.0d, + 3.0d, + Double_MAX_VALUEmm, + Double.MAX_VALUE + }; + + for(int i = 0; i < testCases.length; i++) { + // isNaN + failures+=Tests.test("FpUtils.isNaN(double)", testCases[i], + FpUtils.isNaN(testCases[i]), (i ==0)); + + // isFinite + failures+=Tests.test("FpUtils.isFinite(double)", testCases[i], + FpUtils.isFinite(testCases[i]), (i >= 3)); + + // isInfinite + failures+=Tests.test("FpUtils.isInfinite(double)", testCases[i], + FpUtils.isInfinite(testCases[i]), (i==1 || i==2)); + + // isUnorderd + for(int j = 0; j < testCases.length; j++) { + failures+=Tests.test("FpUtils.isUnordered(double, double)", testCases[i],testCases[j], + FpUtils.isUnordered(testCases[i],testCases[j]), (i==0 || j==0)); + } + } + + return failures; + } + + /* ******************** copySign tests******************************** */ + + public static int testFloatCopySign() { + int failures = 0; + + // testCases[0] are logically positive numbers; + // testCases[1] are negative numbers. + float testCases [][] = { + {+0.0f, + Float.MIN_VALUE, + Float_MAX_SUBNORMALmm, + Float_MAX_SUBNORMAL, + FloatConsts.MIN_NORMAL, + 1.0f, + 3.0f, + Float_MAX_VALUEmm, + Float.MAX_VALUE, + infinityF, + }, + {-infinityF, + -Float.MAX_VALUE, + -3.0f, + -1.0f, + -FloatConsts.MIN_NORMAL, + -Float_MAX_SUBNORMALmm, + -Float_MAX_SUBNORMAL, + -Float.MIN_VALUE, + -0.0f} + }; + + float NaNs[] = {Float.intBitsToFloat(0x7fc00000), // "positive" NaN + Float.intBitsToFloat(0xFfc00000)}; // "negative" NaN + + // Tests shared between raw and non-raw versions + for(int i = 0; i < 2; i++) { + for(int j = 0; j < 2; j++) { + for(int m = 0; m < testCases[i].length; m++) { + for(int n = 0; n < testCases[j].length; n++) { + // copySign(magnitude, sign) + failures+=Tests.test("Math.copySign(float,float)", + testCases[i][m],testCases[j][n], + Math.copySign(testCases[i][m], testCases[j][n]), + (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); + + failures+=Tests.test("StrictMath.copySign(float,float)", + testCases[i][m],testCases[j][n], + StrictMath.copySign(testCases[i][m], testCases[j][n]), + (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); + } + } + } + } + + // For rawCopySign, NaN may effectively have either sign bit + // while for copySign NaNs are treated as if they always have + // a zero sign bit (i.e. as positive numbers) + for(int i = 0; i < 2; i++) { + for(int j = 0; j < NaNs.length; j++) { + for(int m = 0; m < testCases[i].length; m++) { + // copySign(magnitude, sign) + + failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) == + Math.abs(testCases[i][m])) ? 0:1; + + + failures+=Tests.test("StrictMath.copySign(float,float)", + testCases[i][m], NaNs[j], + StrictMath.copySign(testCases[i][m], NaNs[j]), + Math.abs(testCases[i][m]) ); + } + } + } + + return failures; + } + + public static int testDoubleCopySign() { + int failures = 0; + + // testCases[0] are logically positive numbers; + // testCases[1] are negative numbers. + double testCases [][] = { + {+0.0d, + Double.MIN_VALUE, + Double_MAX_SUBNORMALmm, + Double_MAX_SUBNORMAL, + DoubleConsts.MIN_NORMAL, + 1.0d, + 3.0d, + Double_MAX_VALUEmm, + Double.MAX_VALUE, + infinityD, + }, + {-infinityD, + -Double.MAX_VALUE, + -3.0d, + -1.0d, + -DoubleConsts.MIN_NORMAL, + -Double_MAX_SUBNORMALmm, + -Double_MAX_SUBNORMAL, + -Double.MIN_VALUE, + -0.0d} + }; + + double NaNs[] = {Double.longBitsToDouble(0x7ff8000000000000L), // "positive" NaN + Double.longBitsToDouble(0xfff8000000000000L), // "negative" NaN + Double.longBitsToDouble(0x7FF0000000000001L), + Double.longBitsToDouble(0xFFF0000000000001L), + Double.longBitsToDouble(0x7FF8555555555555L), + Double.longBitsToDouble(0xFFF8555555555555L), + Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), + Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), + Double.longBitsToDouble(0x7FFDeadBeef00000L), + Double.longBitsToDouble(0xFFFDeadBeef00000L), + Double.longBitsToDouble(0x7FFCafeBabe00000L), + Double.longBitsToDouble(0xFFFCafeBabe00000L)}; + + // Tests shared between Math and StrictMath versions + for(int i = 0; i < 2; i++) { + for(int j = 0; j < 2; j++) { + for(int m = 0; m < testCases[i].length; m++) { + for(int n = 0; n < testCases[j].length; n++) { + // copySign(magnitude, sign) + failures+=Tests.test("MathcopySign(double,double)", + testCases[i][m],testCases[j][n], + Math.copySign(testCases[i][m], testCases[j][n]), + (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); + + failures+=Tests.test("StrictMath.copySign(double,double)", + testCases[i][m],testCases[j][n], + StrictMath.copySign(testCases[i][m], testCases[j][n]), + (j==0?1.0f:-1.0f)*Math.abs(testCases[i][m]) ); + } + } + } + } + + // For Math.copySign, NaN may effectively have either sign bit + // while for StrictMath.copySign NaNs are treated as if they + // always have a zero sign bit (i.e. as positive numbers) + for(int i = 0; i < 2; i++) { + for(int j = 0; j < NaNs.length; j++) { + for(int m = 0; m < testCases[i].length; m++) { + // copySign(magnitude, sign) + + failures += (Math.abs(Math.copySign(testCases[i][m], NaNs[j])) == + Math.abs(testCases[i][m])) ? 0:1; + + + failures+=Tests.test("StrictMath.copySign(double,double)", + testCases[i][m], NaNs[j], + StrictMath.copySign(testCases[i][m], NaNs[j]), + Math.abs(testCases[i][m]) ); + } + } + } + + + return failures; + } + + /* ************************ scalb tests ******************************* */ + + static int testScalbCase(float value, int scale_factor, float expected) { + int failures=0; + + failures+=Tests.test("Math.scalb(float,int)", + value, scale_factor, + Math.scalb(value, scale_factor), expected); + + failures+=Tests.test("Math.scalb(float,int)", + -value, scale_factor, + Math.scalb(-value, scale_factor), -expected); + + failures+=Tests.test("StrictMath.scalb(float,int)", + value, scale_factor, + StrictMath.scalb(value, scale_factor), expected); + + failures+=Tests.test("StrictMath.scalb(float,int)", + -value, scale_factor, + StrictMath.scalb(-value, scale_factor), -expected); + return failures; + } + + public static int testFloatScalb() { + int failures=0; + int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT + + FloatConsts.SIGNIFICAND_WIDTH + 1; + + + // Arguments x, where scalb(x,n) is x for any n. + float [] identityTestCases = {NaNf, + -0.0f, + +0.0f, + infinityF, + -infinityF + }; + + float [] subnormalTestCases = { + Float.MIN_VALUE, + 3.0f*Float.MIN_VALUE, + Float_MAX_SUBNORMALmm, + Float_MAX_SUBNORMAL + }; + + float [] someTestCases = { + Float.MIN_VALUE, + 3.0f*Float.MIN_VALUE, + Float_MAX_SUBNORMALmm, + Float_MAX_SUBNORMAL, + FloatConsts.MIN_NORMAL, + 1.0f, + 2.0f, + 3.0f, + (float)Math.PI, + Float_MAX_VALUEmm, + Float.MAX_VALUE + }; + + int [] oneMultiplyScalingFactors = { + FloatConsts.MIN_EXPONENT, + FloatConsts.MIN_EXPONENT+1, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + FloatConsts.MAX_EXPONENT-1, + FloatConsts.MAX_EXPONENT + }; + + int [] manyScalingFactors = { + Integer.MIN_VALUE, + Integer.MIN_VALUE+1, + -MAX_SCALE -1, + -MAX_SCALE, + -MAX_SCALE+1, + + 2*FloatConsts.MIN_EXPONENT-1, // -253 + 2*FloatConsts.MIN_EXPONENT, // -252 + 2*FloatConsts.MIN_EXPONENT+1, // -251 + + FpUtils.ilogb(Float.MIN_VALUE)-1, // -150 + FpUtils.ilogb(Float.MIN_VALUE), // -149 + -FloatConsts.MAX_EXPONENT, // -127 + FloatConsts.MIN_EXPONENT, // -126 + + -2, + -1, + 0, + 1, + 2, + + FloatConsts.MAX_EXPONENT-1, // 126 + FloatConsts.MAX_EXPONENT, // 127 + FloatConsts.MAX_EXPONENT+1, // 128 + + 2*FloatConsts.MAX_EXPONENT-1, // 253 + 2*FloatConsts.MAX_EXPONENT, // 254 + 2*FloatConsts.MAX_EXPONENT+1, // 255 + + MAX_SCALE-1, + MAX_SCALE, + MAX_SCALE+1, + Integer.MAX_VALUE-1, + Integer.MAX_VALUE + }; + + // Test cases where scaling is always a no-op + for(int i=0; i < identityTestCases.length; i++) { + for(int j=0; j < manyScalingFactors.length; j++) { + failures += testScalbCase(identityTestCases[i], + manyScalingFactors[j], + identityTestCases[i]); + } + } + + // Test cases where result is 0.0 or infinity due to magnitude + // of the scaling factor + for(int i=0; i < someTestCases.length; i++) { + for(int j=0; j < manyScalingFactors.length; j++) { + int scaleFactor = manyScalingFactors[j]; + if (Math.abs(scaleFactor) >= MAX_SCALE) { + float value = someTestCases[i]; + failures+=testScalbCase(value, + scaleFactor, + FpUtils.copySign( (scaleFactor>0?infinityF:0.0f), value) ); + } + } + } + + // Test cases that could be done with one floating-point + // multiply. + for(int i=0; i < someTestCases.length; i++) { + for(int j=0; j < oneMultiplyScalingFactors.length; j++) { + int scaleFactor = oneMultiplyScalingFactors[j]; + float value = someTestCases[i]; + + failures+=testScalbCase(value, + scaleFactor, + value*powerOfTwoF(scaleFactor)); + } + } + + // Create 2^MAX_EXPONENT + float twoToTheMaxExp = 1.0f; // 2^0 + for(int i = 0; i < FloatConsts.MAX_EXPONENT; i++) + twoToTheMaxExp *=2.0f; + + // Scale-up subnormal values until they all overflow + for(int i=0; i < subnormalTestCases.length; i++) { + float scale = 1.0f; // 2^j + float value = subnormalTestCases[i]; + + for(int j=FloatConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow + int scaleFactor = j; + + failures+=testScalbCase(value, + scaleFactor, + (FpUtils.ilogb(value) +j > FloatConsts.MAX_EXPONENT ) ? + FpUtils.copySign(infinityF, value) : // overflow + // calculate right answer + twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); + scale*=2.0f; + } + } + + // Scale down a large number until it underflows. By scaling + // down MAX_NORMALmm, the first subnormal result will be exact + // but the next one will round -- all those results can be + // checked by halving a separate value in the loop. Actually, + // we can keep halving and checking until the product is zero + // since: + // + // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact + // it will round *up* + // + // 2. When rounding first occurs in the expected product, it + // too rounds up, to 2^-MAX_EXPONENT. + // + // Halving expected after rounding happends to give the same + // result as the scalb operation. + float expected = Float_MAX_VALUEmm *0.5f; + for(int i = -1; i > -MAX_SCALE; i--) { + failures+=testScalbCase(Float_MAX_VALUEmm, i, expected); + + expected *= 0.5f; + } + + // Tricky rounding tests: + // Scale down a large number into subnormal range such that if + // scalb is being implemented with multiple floating-point + // multiplies, the value would round twice if the multiplies + // were done in the wrong order. + + float value = 0x8.0000bP-5f; + expected = 0x1.00001p-129f; + + for(int i = 0; i < 129; i++) { + failures+=testScalbCase(value, + -127-i, + expected); + value *=2.0f; + } + + return failures; + } + + static int testScalbCase(double value, int scale_factor, double expected) { + int failures=0; + + failures+=Tests.test("Math.scalb(double,int)", + value, scale_factor, + Math.scalb(value, scale_factor), expected); + + failures+=Tests.test("Math.scalb(double,int)", + -value, scale_factor, + Math.scalb(-value, scale_factor), -expected); + + failures+=Tests.test("StrictMath.scalb(double,int)", + value, scale_factor, + StrictMath.scalb(value, scale_factor), expected); + + failures+=Tests.test("StrictMath.scalb(double,int)", + -value, scale_factor, + StrictMath.scalb(-value, scale_factor), -expected); + + return failures; + } + + public static int testDoubleScalb() { + int failures=0; + int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT + + DoubleConsts.SIGNIFICAND_WIDTH + 1; + + + // Arguments x, where scalb(x,n) is x for any n. + double [] identityTestCases = {NaNd, + -0.0, + +0.0, + infinityD, + }; + + double [] subnormalTestCases = { + Double.MIN_VALUE, + 3.0d*Double.MIN_VALUE, + Double_MAX_SUBNORMALmm, + Double_MAX_SUBNORMAL + }; + + double [] someTestCases = { + Double.MIN_VALUE, + 3.0d*Double.MIN_VALUE, + Double_MAX_SUBNORMALmm, + Double_MAX_SUBNORMAL, + DoubleConsts.MIN_NORMAL, + 1.0d, + 2.0d, + 3.0d, + Math.PI, + Double_MAX_VALUEmm, + Double.MAX_VALUE + }; + + int [] oneMultiplyScalingFactors = { + DoubleConsts.MIN_EXPONENT, + DoubleConsts.MIN_EXPONENT+1, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + DoubleConsts.MAX_EXPONENT-1, + DoubleConsts.MAX_EXPONENT + }; + + int [] manyScalingFactors = { + Integer.MIN_VALUE, + Integer.MIN_VALUE+1, + -MAX_SCALE -1, + -MAX_SCALE, + -MAX_SCALE+1, + + 2*DoubleConsts.MIN_EXPONENT-1, // -2045 + 2*DoubleConsts.MIN_EXPONENT, // -2044 + 2*DoubleConsts.MIN_EXPONENT+1, // -2043 + + FpUtils.ilogb(Double.MIN_VALUE)-1, // -1076 + FpUtils.ilogb(Double.MIN_VALUE), // -1075 + -DoubleConsts.MAX_EXPONENT, // -1023 + DoubleConsts.MIN_EXPONENT, // -1022 + + -2, + -1, + 0, + 1, + 2, + + DoubleConsts.MAX_EXPONENT-1, // 1022 + DoubleConsts.MAX_EXPONENT, // 1023 + DoubleConsts.MAX_EXPONENT+1, // 1024 + + 2*DoubleConsts.MAX_EXPONENT-1, // 2045 + 2*DoubleConsts.MAX_EXPONENT, // 2046 + 2*DoubleConsts.MAX_EXPONENT+1, // 2047 + + MAX_SCALE-1, + MAX_SCALE, + MAX_SCALE+1, + Integer.MAX_VALUE-1, + Integer.MAX_VALUE + }; + + // Test cases where scaling is always a no-op + for(int i=0; i < identityTestCases.length; i++) { + for(int j=0; j < manyScalingFactors.length; j++) { + failures += testScalbCase(identityTestCases[i], + manyScalingFactors[j], + identityTestCases[i]); + } + } + + // Test cases where result is 0.0 or infinity due to magnitude + // of the scaling factor + for(int i=0; i < someTestCases.length; i++) { + for(int j=0; j < manyScalingFactors.length; j++) { + int scaleFactor = manyScalingFactors[j]; + if (Math.abs(scaleFactor) >= MAX_SCALE) { + double value = someTestCases[i]; + failures+=testScalbCase(value, + scaleFactor, + FpUtils.copySign( (scaleFactor>0?infinityD:0.0), value) ); + } + } + } + + // Test cases that could be done with one floating-point + // multiply. + for(int i=0; i < someTestCases.length; i++) { + for(int j=0; j < oneMultiplyScalingFactors.length; j++) { + int scaleFactor = oneMultiplyScalingFactors[j]; + double value = someTestCases[i]; + + failures+=testScalbCase(value, + scaleFactor, + value*powerOfTwoD(scaleFactor)); + } + } + + // Create 2^MAX_EXPONENT + double twoToTheMaxExp = 1.0; // 2^0 + for(int i = 0; i < DoubleConsts.MAX_EXPONENT; i++) + twoToTheMaxExp *=2.0; + + // Scale-up subnormal values until they all overflow + for(int i=0; i < subnormalTestCases.length; i++) { + double scale = 1.0; // 2^j + double value = subnormalTestCases[i]; + + for(int j=DoubleConsts.MAX_EXPONENT*2; j < MAX_SCALE; j++) { // MAX_SCALE -1 should cause overflow + int scaleFactor = j; + + failures+=testScalbCase(value, + scaleFactor, + (FpUtils.ilogb(value) +j > DoubleConsts.MAX_EXPONENT ) ? + FpUtils.copySign(infinityD, value) : // overflow + // calculate right answer + twoToTheMaxExp*(twoToTheMaxExp*(scale*value)) ); + scale*=2.0; + } + } + + // Scale down a large number until it underflows. By scaling + // down MAX_NORMALmm, the first subnormal result will be exact + // but the next one will round -- all those results can be + // checked by halving a separate value in the loop. Actually, + // we can keep halving and checking until the product is zero + // since: + // + // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact + // it will round *up* + // + // 2. When rounding first occurs in the expected product, it + // too rounds up, to 2^-MAX_EXPONENT. + // + // Halving expected after rounding happends to give the same + // result as the scalb operation. + double expected = Double_MAX_VALUEmm *0.5f; + for(int i = -1; i > -MAX_SCALE; i--) { + failures+=testScalbCase(Double_MAX_VALUEmm, i, expected); + + expected *= 0.5; + } + + // Tricky rounding tests: + // Scale down a large number into subnormal range such that if + // scalb is being implemented with multiple floating-point + // multiplies, the value would round twice if the multiplies + // were done in the wrong order. + + double value = 0x1.000000000000bP-1; + expected = 0x0.2000000000001P-1022; + for(int i = 0; i < DoubleConsts.MAX_EXPONENT+2; i++) { + failures+=testScalbCase(value, + -1024-i, + expected); + value *=2.0; + } + + return failures; + } + + /* ************************* ulp tests ******************************* */ + + + /* + * Test Math.ulp and StrictMath.ulp with +d and -d. + */ + static int testUlpCase(float f, float expected) { + float minus_f = -f; + int failures=0; + + failures+=Tests.test("Math.ulp(float)", f, + Math.ulp(f), expected); + failures+=Tests.test("Math.ulp(float)", minus_f, + Math.ulp(minus_f), expected); + failures+=Tests.test("StrictMath.ulp(float)", f, + StrictMath.ulp(f), expected); + failures+=Tests.test("StrictMath.ulp(float)", minus_f, + StrictMath.ulp(minus_f), expected); + return failures; + } + + static int testUlpCase(double d, double expected) { + double minus_d = -d; + int failures=0; + + failures+=Tests.test("Math.ulp(double)", d, + Math.ulp(d), expected); + failures+=Tests.test("Math.ulp(double)", minus_d, + Math.ulp(minus_d), expected); + failures+=Tests.test("StrictMath.ulp(double)", d, + StrictMath.ulp(d), expected); + failures+=Tests.test("StrictMath.ulp(double)", minus_d, + StrictMath.ulp(minus_d), expected); + return failures; + } + + public static int testFloatUlp() { + int failures = 0; + float [] specialValues = {NaNf, + Float.POSITIVE_INFINITY, + +0.0f, + +1.0f, + +2.0f, + +16.0f, + +Float.MIN_VALUE, + +Float_MAX_SUBNORMAL, + +FloatConsts.MIN_NORMAL, + +Float.MAX_VALUE + }; + + float [] specialResults = {NaNf, + Float.POSITIVE_INFINITY, + Float.MIN_VALUE, + powerOfTwoF(-23), + powerOfTwoF(-22), + powerOfTwoF(-19), + Float.MIN_VALUE, + Float.MIN_VALUE, + Float.MIN_VALUE, + powerOfTwoF(104) + }; + + // Special value tests + for(int i = 0; i < specialValues.length; i++) { + failures += testUlpCase(specialValues[i], specialResults[i]); + } + + + // Normal exponent tests + for(int i = FloatConsts.MIN_EXPONENT; i <= FloatConsts.MAX_EXPONENT; i++) { + float expected; + + // Create power of two + float po2 = powerOfTwoF(i); + expected = FpUtils.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH-1)); + + failures += testUlpCase(po2, expected); + + // Generate some random bit patterns for the significand + for(int j = 0; j < 10; j++) { + int randSignif = rand.nextInt(); + float randFloat; + + randFloat = Float.intBitsToFloat( // Exponent + (Float.floatToIntBits(po2)& + (~FloatConsts.SIGNIF_BIT_MASK)) | + // Significand + (randSignif & + FloatConsts.SIGNIF_BIT_MASK) ); + + failures += testUlpCase(randFloat, expected); + } + + if (i > FloatConsts.MIN_EXPONENT) { + float po2minus = FpUtils.nextAfter(po2, + Float.NEGATIVE_INFINITY); + failures += testUlpCase(po2minus, expected/2.0f); + } + } + + // Subnormal tests + + /* + * Start with MIN_VALUE, left shift, test high value, low + * values, and random in between. + * + * Use nextAfter to calculate, high value of previous binade, + * loop count i will indicate how many random bits, if any are + * needed. + */ + + float top=Float.MIN_VALUE; + for( int i = 1; + i < FloatConsts.SIGNIFICAND_WIDTH; + i++, top *= 2.0f) { + + failures += testUlpCase(top, Float.MIN_VALUE); + + // Test largest value in next smaller binade + if (i >= 3) {// (i == 1) would test 0.0; + // (i == 2) would just retest MIN_VALUE + testUlpCase(FpUtils.nextAfter(top, 0.0f), + Float.MIN_VALUE); + + if( i >= 10) { + // create a bit mask with (i-1) 1's in the low order + // bits + int mask = ~((~0)<<(i-1)); + float randFloat = Float.intBitsToFloat( // Exponent + Float.floatToIntBits(top) | + // Significand + (rand.nextInt() & mask ) ) ; + + failures += testUlpCase(randFloat, Float.MIN_VALUE); + } + } + } + + return failures; + } + + public static int testDoubleUlp() { + int failures = 0; + double [] specialValues = {NaNd, + Double.POSITIVE_INFINITY, + +0.0d, + +1.0d, + +2.0d, + +16.0d, + +Double.MIN_VALUE, + +Double_MAX_SUBNORMAL, + +DoubleConsts.MIN_NORMAL, + +Double.MAX_VALUE + }; + + double [] specialResults = {NaNf, + Double.POSITIVE_INFINITY, + Double.MIN_VALUE, + powerOfTwoD(-52), + powerOfTwoD(-51), + powerOfTwoD(-48), + Double.MIN_VALUE, + Double.MIN_VALUE, + Double.MIN_VALUE, + powerOfTwoD(971) + }; + + // Special value tests + for(int i = 0; i < specialValues.length; i++) { + failures += testUlpCase(specialValues[i], specialResults[i]); + } + + + // Normal exponent tests + for(int i = DoubleConsts.MIN_EXPONENT; i <= DoubleConsts.MAX_EXPONENT; i++) { + double expected; + + // Create power of two + double po2 = powerOfTwoD(i); + expected = FpUtils.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH-1)); + + failures += testUlpCase(po2, expected); + + // Generate some random bit patterns for the significand + for(int j = 0; j < 10; j++) { + long randSignif = rand.nextLong(); + double randDouble; + + randDouble = Double.longBitsToDouble( // Exponent + (Double.doubleToLongBits(po2)& + (~DoubleConsts.SIGNIF_BIT_MASK)) | + // Significand + (randSignif & + DoubleConsts.SIGNIF_BIT_MASK) ); + + failures += testUlpCase(randDouble, expected); + } + + if (i > DoubleConsts.MIN_EXPONENT) { + double po2minus = FpUtils.nextAfter(po2, + Double.NEGATIVE_INFINITY); + failures += testUlpCase(po2minus, expected/2.0f); + } + } + + // Subnormal tests + + /* + * Start with MIN_VALUE, left shift, test high value, low + * values, and random in between. + * + * Use nextAfter to calculate, high value of previous binade, + * loop count i will indicate how many random bits, if any are + * needed. + */ + + double top=Double.MIN_VALUE; + for( int i = 1; + i < DoubleConsts.SIGNIFICAND_WIDTH; + i++, top *= 2.0f) { + + failures += testUlpCase(top, Double.MIN_VALUE); + + // Test largest value in next smaller binade + if (i >= 3) {// (i == 1) would test 0.0; + // (i == 2) would just retest MIN_VALUE + testUlpCase(FpUtils.nextAfter(top, 0.0f), + Double.MIN_VALUE); + + if( i >= 10) { + // create a bit mask with (i-1) 1's in the low order + // bits + int mask = ~((~0)<<(i-1)); + double randDouble = Double.longBitsToDouble( // Exponent + Double.doubleToLongBits(top) | + // Significand + (rand.nextLong() & mask ) ) ; + + failures += testUlpCase(randDouble, Double.MIN_VALUE); + } + } + } + + return failures; + } + + public static int testFloatSignum() { + int failures = 0; + float testCases [][] = { + {NaNf, NaNf}, + {-infinityF, -1.0f}, + {-Float.MAX_VALUE, -1.0f}, + {-FloatConsts.MIN_NORMAL, -1.0f}, + {-1.0f, -1.0f}, + {-2.0f, -1.0f}, + {-Float_MAX_SUBNORMAL, -1.0f}, + {-Float.MIN_VALUE, -1.0f}, + {-0.0f, -0.0f}, + {+0.0f, +0.0f}, + {Float.MIN_VALUE, 1.0f}, + {Float_MAX_SUBNORMALmm, 1.0f}, + {Float_MAX_SUBNORMAL, 1.0f}, + {FloatConsts.MIN_NORMAL, 1.0f}, + {1.0f, 1.0f}, + {2.0f, 1.0f}, + {Float_MAX_VALUEmm, 1.0f}, + {Float.MAX_VALUE, 1.0f}, + {infinityF, 1.0f} + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("Math.signum(float)", + testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]); + failures+=Tests.test("StrictMath.signum(float)", + testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + public static int testDoubleSignum() { + int failures = 0; + double testCases [][] = { + {NaNd, NaNd}, + {-infinityD, -1.0}, + {-Double.MAX_VALUE, -1.0}, + {-DoubleConsts.MIN_NORMAL, -1.0}, + {-1.0, -1.0}, + {-2.0, -1.0}, + {-Double_MAX_SUBNORMAL, -1.0}, + {-Double.MIN_VALUE, -1.0d}, + {-0.0d, -0.0d}, + {+0.0d, +0.0d}, + {Double.MIN_VALUE, 1.0}, + {Double_MAX_SUBNORMALmm, 1.0}, + {Double_MAX_SUBNORMAL, 1.0}, + {DoubleConsts.MIN_NORMAL, 1.0}, + {1.0, 1.0}, + {2.0, 1.0}, + {Double_MAX_VALUEmm, 1.0}, + {Double.MAX_VALUE, 1.0}, + {infinityD, 1.0} + }; + + for(int i = 0; i < testCases.length; i++) { + failures+=Tests.test("Math.signum(double)", + testCases[i][0], Math.signum(testCases[i][0]), testCases[i][1]); + failures+=Tests.test("StrictMath.signum(double)", + testCases[i][0], StrictMath.signum(testCases[i][0]), testCases[i][1]); + } + + return failures; + } + + + public static void main(String argv[]) { + int failures = 0; + + failures += testFloatGetExponent(); + failures += testDoubleGetExponent(); + + failures += testFloatNextAfter(); + failures += testDoubleNextAfter(); + + failures += testFloatNextUp(); + failures += testDoubleNextUp(); + + failures += testFloatNextDown(); + failures += testDoubleNextDown(); + + failures += testFloatBooleanMethods(); + failures += testDoubleBooleanMethods(); + + failures += testFloatCopySign(); + failures += testDoubleCopySign(); + + failures += testFloatScalb(); + failures += testDoubleScalb(); + + failures += testFloatUlp(); + failures += testDoubleUlp(); + + failures += testFloatSignum(); + failures += testDoubleSignum(); + + if (failures > 0) { + System.err.println("Testing the recommended functions incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/Math/Log10Tests.java b/jdk/test/java/lang/Math/Log10Tests.java new file mode 100644 index 00000000000..0f0c4799a43 --- /dev/null +++ b/jdk/test/java/lang/Math/Log10Tests.java @@ -0,0 +1,223 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4074599 4939441 + * @summary Tests for {Math, StrictMath}.log10 + * @author Joseph D. Darcy + */ + +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class Log10Tests { + private Log10Tests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + static final double NaNd = Double.NaN; + static final double LN_10 = StrictMath.log(10.0); + + // Initialize shared random number generator + static java.util.Random rand = new java.util.Random(0L); + + static int testLog10Case(double input, double expected) { + int failures=0; + + failures+=Tests.test("Math.log10(double)", input, + Math.log10(input), expected); + + failures+=Tests.test("StrictMath.log10(double)", input, + StrictMath.log10(input), expected); + + return failures; + } + + static int testLog10() { + int failures = 0; + + double [][] testCases = { + {Double.NaN, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.NEGATIVE_INFINITY, NaNd}, + {-8.0, NaNd}, + {-1.0, NaNd}, + {-DoubleConsts.MIN_NORMAL, NaNd}, + {-Double.MIN_VALUE, NaNd}, + {-0.0, -infinityD}, + {+0.0, -infinityD}, + {+1.0, 0.0}, + {Double.POSITIVE_INFINITY, infinityD}, + }; + + // Test special cases + for(int i = 0; i < testCases.length; i++) { + failures += testLog10Case(testCases[i][0], + testCases[i][1]); + } + + // Test log10(10^n) == n for integer n; 10^n, n < 0 is not + // exactly representable as a floating-point value -- up to + // 10^22 can be represented exactly + double testCase = 1.0; + for(int i = 0; i < 23; i++) { + failures += testLog10Case(testCase, i); + testCase *= 10.0; + } + + // Test for gross inaccuracy by comparing to log; should be + // within a few ulps of log(x)/log(10) + for(int i = 0; i < 10000; i++) { + double input = Double.longBitsToDouble(rand.nextLong()); + if(! FpUtils.isFinite(input)) + continue; // avoid testing NaN and infinite values + else { + input = Math.abs(input); + + double expected = StrictMath.log(input)/LN_10; + if( ! FpUtils.isFinite(expected)) + continue; // if log(input) overflowed, try again + else { + double result; + + if( Math.abs(((result=Math.log10(input)) - expected)/Math.ulp(expected)) > 3) { + failures++; + System.err.println("For input " + input + + ", Math.log10 was more than 3 ulps different from " + + "log(input)/log(10): log10(input) = " + result + + "\tlog(input)/log(10) = " + expected); + } + + if( Math.abs(((result=StrictMath.log10(input)) - expected)/Math.ulp(expected)) > 3) { + failures++; + System.err.println("For input " + input + + ", StrictMath.log10 was more than 3 ulps different from " + + "log(input)/log(10): log10(input) = " + result + + "\tlog(input)/log(10) = " + expected); + } + + + } + } + } + + // Test for accuracy and monotonicity near log10(1.0). From + // the Taylor expansion of log, + // log10(1+z) ~= (z -(z^2)/2)/LN_10; + { + double neighbors[] = new double[40]; + double neighborsStrict[] = new double[40]; + double z = Double.NaN; + + // Test inputs greater than 1.0. + neighbors[0] = Math.log10(1.0); + neighborsStrict[0] = StrictMath.log10(1.0); + + double input[] = new double[40]; + int half = input.length/2; + + + // Initialize input to the 40 consecutive double values + // "centered" at 1.0. + double up = Double.NaN; + double down = Double.NaN; + for(int i = 0; i < half; i++) { + if (i == 0) { + input[half] = 1.0; + up = FpUtils.nextUp(1.0); + down = FpUtils.nextDown(1.0); + } else { + input[half + i] = up; + input[half - i] = down; + up = FpUtils.nextUp(up); + down = FpUtils.nextDown(down); + } + } + input[0] = FpUtils.nextDown(input[1]); + + for(int i = 0; i < neighbors.length; i++) { + neighbors[i] = Math.log10(input[i]); + neighborsStrict[i] = StrictMath.log10(input[i]); + + // Test accuracy. + z = input[i] - 1.0; + double expected = (z - (z*z)*0.5)/LN_10; + if ( Math.abs(neighbors[i] - expected ) > 3*Math.ulp(expected) ) { + failures++; + System.err.println("For input near 1.0 " + input[i] + + ", Math.log10(1+z) was more than 3 ulps different from " + + "(z-(z^2)/2)/ln(10): log10(input) = " + neighbors[i] + + "\texpected about = " + expected); + } + + if ( Math.abs(neighborsStrict[i] - expected ) > 3*Math.ulp(expected) ) { + failures++; + System.err.println("For input near 1.0 " + input[i] + + ", StrictMath.log10(1+z) was more than 3 ulps different from " + + "(z-(z^2)/2)/ln(10): log10(input) = " + neighborsStrict[i] + + "\texpected about = " + expected); + } + + // Test monotonicity + if( i > 0) { + if( neighbors[i-1] > neighbors[i] ) { + failures++; + System.err.println("Monotonicity failure for Math.log10 at " + input[i] + + " and prior value."); + } + + if( neighborsStrict[i-1] > neighborsStrict[i] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.log10 at " + input[i] + + " and prior value."); + } + } + } + + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += testLog10(); + + if (failures > 0) { + System.err.println("Testing log10 incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/Log1pTests.java b/jdk/test/java/lang/Math/Log1pTests.java new file mode 100644 index 00000000000..8cfe6ed72e0 --- /dev/null +++ b/jdk/test/java/lang/Math/Log1pTests.java @@ -0,0 +1,206 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 4939441 + * @summary Tests for {Math, StrictMath}.log1p + * @author Joseph D. Darcy + */ + +import sun.misc.DoubleConsts; +import sun.misc.FpUtils; + +public class Log1pTests { + private Log1pTests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + static final double NaNd = Double.NaN; + + /** + * Formulation taken from HP-15C Advanced Functions Handbook, part + * number HP 0015-90011, p 181. This is accurate to a few ulps. + */ + static double hp15cLogp(double x) { + double u = 1.0 + x; + return (u==1.0? x : StrictMath.log(u)*x/(u-1) ); + } + + /* + * The Taylor expansion of ln(1 + x) for -1 < x <= 1 is: + * + * x - x^2/2 + x^3/3 - ... -(-x^j)/j + * + * Therefore, for small values of x, log1p(x) ~= x. For large + * values of x, log1p(x) ~= log(x). + * + * Also x/(x+1) < ln(1+x) < x + */ + + static int testLog1p() { + int failures = 0; + + double [][] testCases = { + {Double.NaN, NaNd}, + {Double.longBitsToDouble(0x7FF0000000000001L), NaNd}, + {Double.longBitsToDouble(0xFFF0000000000001L), NaNd}, + {Double.longBitsToDouble(0x7FF8555555555555L), NaNd}, + {Double.longBitsToDouble(0xFFF8555555555555L), NaNd}, + {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd}, + {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd}, + {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd}, + {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd}, + {Double.NEGATIVE_INFINITY, NaNd}, + {-8.0, NaNd}, + {-1.0, -infinityD}, + {-0.0, -0.0}, + {+0.0, +0.0}, + {infinityD, infinityD}, + }; + + // Test special cases + for(int i = 0; i < testCases.length; i++) { + failures += testLog1pCaseWithUlpDiff(testCases[i][0], + testCases[i][1], 0); + } + + // For |x| < 2^-54 log1p(x) ~= x + for(int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) { + double d = FpUtils.scalb(2, i); + failures += testLog1pCase(d, d); + failures += testLog1pCase(-d, -d); + } + + // For x > 2^53 log1p(x) ~= log(x) + for(int i = 53; i <= DoubleConsts.MAX_EXPONENT; i++) { + double d = FpUtils.scalb(2, i); + failures += testLog1pCaseWithUlpDiff(d, StrictMath.log(d), 2.001); + } + + // Construct random values with exponents ranging from -53 to + // 52 and compare against HP-15C formula. + java.util.Random rand = new java.util.Random(); + for(int i = 0; i < 1000; i++) { + double d = rand.nextDouble(); + + d = FpUtils.scalb(d, -53 - FpUtils.ilogb(d)); + + for(int j = -53; j <= 52; j++) { + failures += testLog1pCaseWithUlpDiff(d, hp15cLogp(d), 5); + + d *= 2.0; // increase exponent by 1 + } + } + + // Test for monotonicity failures near values y-1 where y ~= + // e^x. Test two numbers before and two numbers after each + // chosen value; i.e. + // + // pcNeighbors[] = + // {nextDown(nextDown(pc)), + // nextDown(pc), + // pc, + // nextUp(pc), + // nextUp(nextUp(pc))} + // + // and we test that log1p(pcNeighbors[i]) <= log1p(pcNeighbors[i+1]) + { + double pcNeighbors[] = new double[5]; + double pcNeighborsLog1p[] = new double[5]; + double pcNeighborsStrictLog1p[] = new double[5]; + + for(int i = -36; i <= 36; i++) { + double pc = StrictMath.pow(Math.E, i) - 1; + + pcNeighbors[2] = pc; + pcNeighbors[1] = FpUtils.nextDown(pc); + pcNeighbors[0] = FpUtils.nextDown(pcNeighbors[1]); + pcNeighbors[3] = FpUtils.nextUp(pc); + pcNeighbors[4] = FpUtils.nextUp(pcNeighbors[3]); + + for(int j = 0; j < pcNeighbors.length; j++) { + pcNeighborsLog1p[j] = Math.log1p(pcNeighbors[j]); + pcNeighborsStrictLog1p[j] = StrictMath.log1p(pcNeighbors[j]); + } + + for(int j = 0; j < pcNeighborsLog1p.length-1; j++) { + if(pcNeighborsLog1p[j] > pcNeighborsLog1p[j+1] ) { + failures++; + System.err.println("Monotonicity failure for Math.log1p on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsLog1p[j] + " and " + + pcNeighborsLog1p[j+1] ); + } + + if(pcNeighborsStrictLog1p[j] > pcNeighborsStrictLog1p[j+1] ) { + failures++; + System.err.println("Monotonicity failure for StrictMath.log1p on " + + pcNeighbors[j] + " and " + + pcNeighbors[j+1] + "\n\treturned " + + pcNeighborsStrictLog1p[j] + " and " + + pcNeighborsStrictLog1p[j+1] ); + } + + + } + + } + } + + return failures; + } + + public static int testLog1pCase(double input, + double expected) { + return testLog1pCaseWithUlpDiff(input, expected, 1); + } + + public static int testLog1pCaseWithUlpDiff(double input, + double expected, + double ulps) { + int failures = 0; + failures += Tests.testUlpDiff("Math.lop1p(double", + input, Math.log1p(input), + expected, ulps); + failures += Tests.testUlpDiff("StrictMath.log1p(double", + input, StrictMath.log1p(input), + expected, ulps); + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += testLog1p(); + + if (failures > 0) { + System.err.println("Testing log1p incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/MinMax.java b/jdk/test/java/lang/Math/MinMax.java new file mode 100644 index 00000000000..8ae8cf37ccf --- /dev/null +++ b/jdk/test/java/lang/Math/MinMax.java @@ -0,0 +1,124 @@ +/* + * Copyright 1997 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 4010528 4010529 + @summary Math.min and Math.max should treat negative zero as strictly + less than positive zero + */ + + +public class MinMax { + + + static void go(String what, float result, float correctResult) { + String v = what + ": got " + result + ", expected " + correctResult; + if (!(Float.toString(result).equals(Float.toString(correctResult)))) + throw new RuntimeException(v); + System.err.println(v); + } + + static void go(String what, double result, double correctResult) { + String v = what + ": got " + result + ", expected " + correctResult; + if (!(Double.toString(result).equals(Double.toString(correctResult)))) + throw new RuntimeException(v); + System.err.println(v); + } + + + public static void main(String[] args) { + + float fnz = -0.0f; + float fpz = +0.0f; + + go("Math.min(fnz, fnz)", Math.min(fnz, fnz), fnz); + go("Math.min(fnz, fpz)", Math.min(fnz, fpz), fnz); + go("Math.min(fpz, fnz)", Math.min(fpz, fnz), fnz); + go("Math.min(fpz, fpz)", Math.min(fpz, fpz), fpz); + + go("Math.min(-1.0f, fnz)", Math.min(-1.0f, fnz), -1.0f); + go("Math.min(-1.0f, fpz)", Math.min(-1.0f, fpz), -1.0f); + go("Math.min(+1.0f, fnz)", Math.min(+1.0f, fnz), fnz); + go("Math.min(+1.0f, fpz)", Math.min(+1.0f, fpz), fpz); + go("Math.min(-1.0f, +1.0f)", Math.min(-1.0f, +1.0f), -1.0f); + go("Math.min(fnz, -1.0f)", Math.min(fnz, -1.0f), -1.0f); + go("Math.min(fpz, -1.0f)", Math.min(fpz, -1.0f), -1.0f); + go("Math.min(fnz, +1.0f)", Math.min(fnz, +1.0f), fnz); + go("Math.min(fpz, +1.0f)", Math.min(fpz, +1.0f), fpz); + go("Math.min(+1.0f, -1.0f)", Math.min(+1.0f, -1.0f), -1.0f); + + go("Math.max(fnz, fnz)", Math.max(fnz, fnz), fnz); + go("Math.max(fnz, fpz)", Math.max(fnz, fpz), fpz); + go("Math.max(fpz, fnz)", Math.max(fpz, fnz), fpz); + go("Math.max(fpz, fpz)", Math.max(fpz, fpz), fpz); + + go("Math.max(-1.0f, fnz)", Math.max(-1.0f, fnz), fnz); + go("Math.max(-1.0f, fpz)", Math.max(-1.0f, fpz), fpz); + go("Math.max(+1.0f, fnz)", Math.max(+1.0f, fnz), +1.0f); + go("Math.max(+1.0f, fpz)", Math.max(+1.0f, fpz), +1.0f); + go("Math.max(-1.0f, +1.0f)", Math.max(-1.0f, +1.0f), +1.0f); + go("Math.max(fnz, -1.0f)", Math.max(fnz, -1.0f), fnz); + go("Math.max(fpz, -1.0f)", Math.max(fpz, -1.0f), fpz); + go("Math.max(fnz, +1.0f)", Math.max(fnz, +1.0f), +1.0f); + go("Math.max(fpz, +1.0f)", Math.max(fpz, +1.0f), +1.0f); + go("Math.max(+1.0f, -1.0f)", Math.max(+1.0f, -1.0f), +1.0f); + + + double dnz = -0.0d; + double dpz = +0.0d; + + go("Math.min(dnz, dnz)", Math.min(dnz, dnz), dnz); + go("Math.min(dnz, dpz)", Math.min(dnz, dpz), dnz); + go("Math.min(dpz, dnz)", Math.min(dpz, dnz), dnz); + go("Math.min(dpz, dpz)", Math.min(dpz, dpz), dpz); + + go("Math.min(-1.0d, dnz)", Math.min(-1.0d, dnz), -1.0d); + go("Math.min(-1.0d, dpz)", Math.min(-1.0d, dpz), -1.0d); + go("Math.min(+1.0d, dnz)", Math.min(+1.0d, dnz), dnz); + go("Math.min(+1.0d, dpz)", Math.min(+1.0d, dpz), dpz); + go("Math.min(-1.0d, +1.0d)", Math.min(-1.0d, +1.0d), -1.0d); + go("Math.min(dnz, -1.0d)", Math.min(dnz, -1.0d), -1.0d); + go("Math.min(dpz, -1.0d)", Math.min(dpz, -1.0d), -1.0d); + go("Math.min(dnz, +1.0d)", Math.min(dnz, +1.0d), dnz); + go("Math.min(dpz, +1.0d)", Math.min(dpz, +1.0d), dpz); + go("Math.min(+1.0d, -1.0d)", Math.min(+1.0d, -1.0d), -1.0d); + + go("Math.max(dnz, dnz)", Math.max(dnz, dnz), dnz); + go("Math.max(dnz, dpz)", Math.max(dnz, dpz), dpz); + go("Math.max(dpz, dnz)", Math.max(dpz, dnz), dpz); + go("Math.max(dpz, dpz)", Math.max(dpz, dpz), dpz); + + go("Math.max(-1.0d, dnz)", Math.max(-1.0d, dnz), dnz); + go("Math.max(-1.0d, dpz)", Math.max(-1.0d, dpz), dpz); + go("Math.max(+1.0d, dnz)", Math.max(+1.0d, dnz), +1.0d); + go("Math.max(+1.0d, dpz)", Math.max(+1.0d, dpz), +1.0d); + go("Math.max(-1.0d, +1.0d)", Math.max(-1.0d, +1.0d), +1.0d); + go("Math.max(dnz, -1.0d)", Math.max(dnz, -1.0d), dnz); + go("Math.max(dpz, -1.0d)", Math.max(dpz, -1.0d), dpz); + go("Math.max(dnz, +1.0d)", Math.max(dnz, +1.0d), +1.0d); + go("Math.max(dpz, +1.0d)", Math.max(dpz, +1.0d), +1.0d); + go("Math.max(+1.0d, -1.0d)", Math.max(+1.0d, -1.0d), +1.0d); + + } + +} diff --git a/jdk/test/java/lang/Math/PowTests.java b/jdk/test/java/lang/Math/PowTests.java new file mode 100644 index 00000000000..79764765e33 --- /dev/null +++ b/jdk/test/java/lang/Math/PowTests.java @@ -0,0 +1,301 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4984407 5033578 + * @summary Tests for {Math, StrictMath}.pow + * @compile -source 1.5 PowTests.java + * @run main PowTests + * @author Joseph D. Darcy + */ + +public class PowTests { + private PowTests(){} + + static final double infinityD = Double.POSITIVE_INFINITY; + + static int testPowCase(double input1, double input2, double expected) { + int failures = 0; + failures += Tests.test("StrictMath.pow(double, double)", input1, input2, + StrictMath.pow(input1, input2), expected); + failures += Tests.test("Math.pow(double, double)", input1, input2, + Math.pow(input1, input2), expected); + return failures; + } + + + static int testStrictPowCase(double input1, double input2, double expected) { + int failures = 0; + failures += Tests.test("StrictMath.pow(double, double)", input1, input2, + StrictMath.pow(input1, input2), expected); + return failures; + } + + static int testNonstrictPowCase(double input1, double input2, double expected) { + int failures = 0; + failures += Tests.test("Math.pow(double, double)", input1, input2, + Math.pow(input1, input2), expected); + return failures; + } + + /* + * Test for bad negation implementation. + */ + static int testPow() { + int failures = 0; + + double [][] testCases = { + {-0.0, 3.0, -0.0}, + {-0.0, 4.0, 0.0}, + {-infinityD, -3.0, -0.0}, + {-infinityD, -4.0, 0.0}, + }; + + for (double[] testCase : testCases) { + failures+=testPowCase(testCase[0], testCase[1], testCase[2]); + } + + return failures; + } + + /* + * Test cross-product of different kinds of arguments. + */ + static int testCrossProduct() { + int failures = 0; + + double testData[] = { + Double.NEGATIVE_INFINITY, +/* > -oo */ -Double.MAX_VALUE, +/**/ (double)Long.MIN_VALUE, +/**/ (double) -((1L<<53)+2L), +/**/ (double) -((1L<<53)), +/**/ (double) -((1L<<53)-1L), +/**/ -((double)Integer.MAX_VALUE + 4.0), +/**/ (double)Integer.MIN_VALUE - 1.0, +/**/ (double)Integer.MIN_VALUE, +/**/ (double)Integer.MIN_VALUE + 1.0, +/**/ -Math.PI, +/**/ -3.0, +/**/ -Math.E, +/**/ -2.0, +/**/ -1.0000000000000004, +/* < -1.0 */ -1.0000000000000002, // nextAfter(-1.0, -oo) + -1.0, +/* > -1.0 */ -0.9999999999999999, // nextAfter(-1.0, +oo) +/* > -1.0 */ -0.9999999999999998, +/**/ -0.5, +/**/ -1.0/3.0, +/* < 0.0 */ -Double.MIN_VALUE, + -0.0, + +0.0, +/* > 0.0 */ +Double.MIN_VALUE, +/**/ +1.0/3.0, +/**/ +0.5, +/**/ +0.9999999999999998, +/* < +1.0 */ +0.9999999999999999, // nextAfter(-1.0, +oo) + +1.0, +/* > 1.0 */ +1.0000000000000002, // nextAfter(+1.0, +oo) +/**/ +1.0000000000000004, +/**/ +2.0, +/**/ +Math.E, +/**/ +3.0, +/**/ +Math.PI, +/**/ -(double)Integer.MIN_VALUE - 1.0, +/**/ -(double)Integer.MIN_VALUE, +/**/ -(double)Integer.MIN_VALUE + 1.0, +/**/ (double)Integer.MAX_VALUE + 4.0, +/**/ (double) ((1L<<53)-1L), +/**/ (double) ((1L<<53)), +/**/ (double) ((1L<<53)+2L), +/**/ -(double)Long.MIN_VALUE, +/* < oo */ Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN + }; + + double NaN = Double.NaN; + for(double x: testData) { + for(double y: testData) { + boolean testPass = false; + double expected=NaN; + double actual; + + // First, switch on y + if( Double.isNaN(y)) { + expected = NaN; + } else if (y == 0.0) { + expected = 1.0; + } else if (Double.isInfinite(y) ) { + if(y > 0) { // x ^ (+oo) + if (Math.abs(x) > 1.0) { + expected = Double.POSITIVE_INFINITY; + } else if (Math.abs(x) == 1.0) { + expected = NaN; + } else if (Math.abs(x) < 1.0) { + expected = +0.0; + } else { // x is NaN + assert Double.isNaN(x); + expected = NaN; + } + } else { // x ^ (-oo) + if (Math.abs(x) > 1.0) { + expected = +0.0; + } else if (Math.abs(x) == 1.0) { + expected = NaN; + } else if (Math.abs(x) < 1.0) { + expected = Double.POSITIVE_INFINITY; + } else { // x is NaN + assert Double.isNaN(x); + expected = NaN; + } + } /* end Double.isInfinite(y) */ + } else if (y == 1.0) { + expected = x; + } else if (Double.isNaN(x)) { // Now start switching on x + assert y != 0.0; + expected = NaN; + } else if (x == Double.NEGATIVE_INFINITY) { + expected = (y < 0.0) ? f2(y) :f1(y); + } else if (x == Double.POSITIVE_INFINITY) { + expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY; + } else if (equivalent(x, +0.0)) { + assert y != 0.0; + expected = (y < 0.0) ? Double.POSITIVE_INFINITY: +0.0; + } else if (equivalent(x, -0.0)) { + assert y != 0.0; + expected = (y < 0.0) ? f1(y): f2(y); + } else if( x < 0.0) { + assert y != 0.0; + failures += testStrictPowCase(x, y, f3(x, y)); + failures += testNonstrictPowCase(x, y, f3ns(x, y)); + continue; + } else { + // go to next iteration + expected = NaN; + continue; + } + + failures += testPowCase(x, y, expected); + } // y + } // x + return failures; + } + + static boolean equivalent(double a, double b) { + return Double.compare(a, b) == 0; + } + + static double f1(double y) { + return (intClassify(y) == 1)? + Double.NEGATIVE_INFINITY: + Double.POSITIVE_INFINITY; + } + + + static double f2(double y) { + return (intClassify(y) == 1)?-0.0:0.0; + } + + static double f3(double x, double y) { + switch( intClassify(y) ) { + case 0: + return StrictMath.pow(Math.abs(x), y); + // break; + + case 1: + return -StrictMath.pow(Math.abs(x), y); + // break; + + case -1: + return Double.NaN; + // break; + + default: + throw new AssertionError("Bad classification."); + // break; + } + } + + static double f3ns(double x, double y) { + switch( intClassify(y) ) { + case 0: + return Math.pow(Math.abs(x), y); + // break; + + case 1: + return -Math.pow(Math.abs(x), y); + // break; + + case -1: + return Double.NaN; + // break; + + default: + throw new AssertionError("Bad classification."); + // break; + } + } + + static boolean isFinite(double a) { + return (0.0*a == 0); + } + + /** + * Return classification of argument: -1 for non-integers, 0 for + * even integers, 1 for odd integers. + */ + static int intClassify(double a) { + if(!isFinite(a) || // NaNs and infinities + (a != Math.floor(a) )) { // only integers are fixed-points of floor + return -1; + } + else { + // Determine if argument is an odd or even integer. + + a = StrictMath.abs(a); // absolute value doesn't affect odd/even + + if(a+1.0 == a) { // a > maximum odd floating-point integer + return 0; // Large integers are all even + } + else { // Convert double -> long and look at low-order bit + long ell = (long) a; + return ((ell & 0x1L) == (long)1)?1:0; + } + } + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testPow(); + failures += testCrossProduct(); + + if (failures > 0) { + System.err.println("Testing pow incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/Math/Rint.java b/jdk/test/java/lang/Math/Rint.java new file mode 100644 index 00000000000..d8e35cd1343 --- /dev/null +++ b/jdk/test/java/lang/Math/Rint.java @@ -0,0 +1,122 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4101566 4831589 + * @summary Check for correct implementation of Math.rint(double) + * + */ + +import sun.misc.FpUtils; +import sun.misc.DoubleConsts; + +public class Rint { + + static int testRintCase(double input, double expected) { + int failures = 0; + double result; + failures += Tests.test("Math.rint", input, Math.rint(input), expected); + failures += Tests.test("Math.rint", -input, Math.rint(-input), -expected); + failures += Tests.test("StrictMath.rint", + input, StrictMath.rint(input), expected); + failures += Tests.test("StrictMath.rint", -input, + StrictMath.rint(-input), -expected); + return failures; + } + + + public static void main(String args[]) { + int failures = 0; + double twoToThe52 = FpUtils.scalb(1.0, 52); // 2^52 + + double [][] testCases = { + {0.0, 0.0}, + {Double.MIN_VALUE, 0.0}, + {FpUtils.nextDown(DoubleConsts.MIN_NORMAL), 0.0}, + {DoubleConsts.MIN_NORMAL, 0.0}, + + {0.2, 0.0}, + + {FpUtils.nextDown(0.5), 0.0}, + { 0.5, 0.0}, + { FpUtils.nextUp(0.5), 1.0}, + + {0.7, 1.0}, + {FpUtils.nextDown(1.0), 1.0}, + { 1.0, 1.0}, + { FpUtils.nextUp(1.0), 1.0}, + + {FpUtils.nextDown(1.5), 1.0}, + { 1.5, 2.0}, + { FpUtils.nextUp(1.5), 2.0}, + + {4.2, 4.0}, + {4.5, 4.0}, + {4.7, 5.0}, + + {7.5, 8.0}, + {7.2, 7.0}, + {7.7, 8.0}, + + {150000.75, 150001.0}, + {300000.5, 300000.0}, + {FpUtils.nextUp(300000.5), 300001.0}, + {FpUtils.nextDown(300000.75), 300001.0}, + {300000.75, 300001.0}, + {FpUtils.nextUp(300000.75), 300001.0}, + {300000.99, 300001.0}, + {262144.75, 262145.0}, //(2^18 ) + 0.75 + {499998.75, 499999.0}, + {524287.75, 524288.0}, //(2^19 -1) + 0.75 + {524288.75, 524289.0}, + + {FpUtils.nextDown(twoToThe52), twoToThe52}, + {twoToThe52, twoToThe52}, + {FpUtils.nextUp(twoToThe52), FpUtils.nextUp(twoToThe52)}, + + {Double.MAX_VALUE, Double.MAX_VALUE}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.NaN, Double.NaN} + + }; + + + for(int i = 0; i < testCases.length; i++) { + failures += testRintCase(testCases[i][0], testCases[i][1]); + } + + // Test values throughout exponent range + for(double d = Double.MIN_VALUE; + d < Double.POSITIVE_INFINITY; d *= 2) { + failures += testRintCase(d, ((d<=0.5)?0.0:d)); + } + + if (failures > 0) { + System.err.println("Testing {Math, StrictMath}.rint incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/lang/Math/TanTests.java b/jdk/test/java/lang/Math/TanTests.java new file mode 100644 index 00000000000..f603fb872a0 --- /dev/null +++ b/jdk/test/java/lang/Math/TanTests.java @@ -0,0 +1,189 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5033578 + * @summary Tests for {Math, StrictMath}.tan + * @compile -source 1.5 TanTests.java + * @run main TanTests + * @author Joseph D. Darcy + */ + +public class TanTests { + private TanTests(){} + + static int testTanCase(double input, double expected, double ulps) { + int failures = 0; + failures += Tests.testUlpDiff("StrictMath.tan(double, double)", input, + StrictMath.tan(input), expected, ulps); + failures += Tests.testUlpDiff("Math.tan(double, double)", input, + Math.tan(input), expected, ulps); + return failures; + } + + static int testTan() { + int failures = 0; + + double [][] testCases = { + // 1.1 ulp case from Gonnet + {0x1.31b97c4000001p24, -0x1.d08538b656222p34, 1.9}, + // Remaining test cases adapted from work by Alex Liu + {0x1.be1b2d17ba207p6, -0x1.cf489c89f8066p49, 1.100000}, + {0x1.e0a9e6ab97de7p7, 0x1.d31ce95f57459p50, 1.100000}, + {0x1.23f8c5bcf003ep11, 0x1.f022585dbb50ap50, 1.100000}, + {0x1.44bdb557e1dc1p20, 0x1.b67eaf362701fp49, 1.100000}, + {0x1.604759040fb6fp68, 0x1.d574bc1f9e903p50, 1.100000}, + {0x1.3d33fa4e5ba47p70, 0x1.ce1dd6e33fef8p49, 1.100000}, + {0x1.f19e5d71b26bap85, 0x1.c2536a9119dd2p55, 1.100000}, + {0x1.43ed062d2d62cp88, -0x1.c94b0c5b7b05p49, 1.100000}, + {0x1.b7b895b030bep88, -0x1.cba9ebb0f20b9p51, 1.100000}, + {0x1.a86090fe7c144p95, 0x1.d5ad72ca48bbfp48, 1.100000}, + {0x1.d199df0700a61p95, -0x1.b8dd636f8dba7p49, 1.100000}, + {0x1.d713037d1d222p106, -0x1.d57f035fd0146p48, 1.100000}, + {0x1.ed1f6b066569bp115, 0x1.840af46cc9bep48, 1.100000}, + {0x1.16800a51eff75p118, 0x1.c9f91caf08a6ap49, 1.100000}, + {0x1.c1169c1040ecdp134, 0x1.e44a7eb56cb7p48, 1.100000}, + {0x1.19b0fb40dddd5p145, -0x1.f1b1c235774b2p48, 1.100000}, + {0x1.4d6b47f2480f8p162, 0x1.da1c2010795a5p51, 1.100000}, + {0x1.682ff8e5429ddp163, -0x1.95a7aee1e93bep55, 1.100000}, + {0x1.d0569fad9657dp204, -0x1.8f2ca17123aa5p49, 1.100000}, + {0x1.55505de5bbc14p206, -0x1.e8d28e39ddf9p50, 1.100000}, + {0x1.cf497083e6c77p206, -0x1.fd3fbaa40de18p49, 1.100000}, + {0x1.c5b30c8686203p214, 0x1.f4d14469638a9p48, 1.100000}, + {0x1.60d15b12ff0b7p217, 0x1.bc150932bd3d7p48, 1.100000}, + {0x1.07cc6858d980bp218, -0x1.f3f7355c983a5p51, 1.100000}, + {0x1.e06a67cd86969p218, 0x1.b0873124d98afp51, 1.100000}, + {0x1.49704174c38e3p229, 0x1.e0301142ccbc2p49, 1.100000}, + {0x1.ea19ceab3b06ap230, -0x1.fc22e687f0482p48, 1.100000}, + {0x1.0c905503fea72p236, -0x1.7d4e9a45014d5p49, 1.100000}, + {0x1.28eb1f8ddd7c3p257, -0x1.a951893680c71p49, 1.100000}, + {0x1.310b11af2bfbep260, 0x1.84d458039c2e6p48, 1.100000}, + {0x1.f3c172bb7afc2p265, -0x1.fb3139d3ba04fp49, 1.100000}, + {0x1.54a28326cfedep267, 0x1.f416de8fb60bap53, 1.100000}, + {0x1.5a5154d9d609dp269, -0x1.83d74cea8141p51, 1.100000}, + {0x1.3ee75fd803b21p275, 0x1.b9ab67b61bf65p50, 1.100000}, + {0x1.f4a4c781834d9p277, -0x1.d639ec63bf3b6p49, 1.100000}, + {0x1.2053d5c14cf78p279, 0x1.fc31413372cdcp50, 1.100000}, + {0x1.896d0a9acee4cp298, 0x1.f9136d6e27a5cp48, 1.100000}, + {0x1.f010da08a862p302, -0x1.fd812c5e13483p49, 1.100000}, + {0x1.65f2e272f729fp308, -0x1.f9f642ddaa32dp49, 1.100000}, + {0x1.a8afbc4edb07dp309, 0x1.fa0d458320902p52, 1.100000}, + {0x1.4d311a5447cdep329, -0x1.f7e98fe193e81p49, 1.100000}, + {0x1.808f66338b21bp345, -0x1.bceaf45f61155p49, 1.100000}, + {0x1.5a34aacf5ded1p350, 0x1.d41f0f13fadd4p49, 1.100000}, + {0x1.3e8b85532bad1p354, -0x1.f0b21179d663ep49, 1.100000}, + {0x1.1c2ecf01570acp394, -0x1.c215c9e2b7b24p49, 1.100000}, + {0x1.666eba99d2837p402, 0x1.fbd5c4b527506p48, 1.100000}, + {0x1.6cc39f07fafbbp460, -0x1.f087548a00e7cp49, 1.100000}, + {0x1.9481228fea3ffp463, -0x1.c585e64ff44c8p48, 1.100000}, + {0x1.79c3af0b4d0d4p466, 0x1.c9ed3716691f2p51, 1.100000}, + {0x1.993ea84c3e23bp468, 0x1.a6b3954fc37f3p49, 1.100000}, + {0x1.cfd6b13f64408p470, -0x1.f4db7cc2c09bp47, 1.100000}, + {0x1.b820ccdd52299p473, 0x1.77a1ff863b0f3p52, 1.100000}, + {0x1.157ef3a1528a5p475, -0x1.f4e14ddc45e49p51, 1.100000}, + {0x1.b492a8997bc36p478, -0x1.e0db26b7f03e8p48, 1.100000}, + {0x1.e0ea5674b831bp480, 0x1.e0ad6b3cdccdfp48, 1.100000}, + {0x1.c62ac8b32cb9ep497, 0x1.c95d00a36f677p48, 1.100000}, + {0x1.467f1daf12b43p498, 0x1.c6d3fdc096f0bp50, 1.100000}, + {0x1.336e5a83e390cp502, 0x1.fc873dae28572p48, 1.100000}, + {0x1.aaab1de0d6727p506, -0x1.e0482967d0354p49, 1.100000}, + {0x1.e5ce06a12139cp507, 0x1.cea42e29735bdp49, 1.100000}, + {0x1.87dad74d0dda8p516, -0x1.b2cde6c0a8b9fp48, 1.100000}, + {0x1.e4feb94ee0989p524, -0x1.b227d0d0ffaa8p49, 1.100000}, + {0x1.31c082b1361ebp525, 0x1.a7ed49158d736p49, 1.100000}, + {0x1.56913865b3e16p531, 0x1.eeb7a32591c3bp52, 1.100000}, + {0x1.36ade1fa883cap544, -0x1.fa087aadc0cbp48, 1.100000}, + {0x1.de57314df4af8p559, 0x1.c686aa5a41075p49, 1.100000}, + {0x1.0bb29bf7960ddp586, -0x1.d29ae1a3023cep50, 1.100000}, + {0x1.049a584685941p588, -0x1.eebfb159dba67p51, 1.100000}, + {0x1.33c1d4257b294p589, 0x1.ea1eedabea109p48, 1.100000}, + {0x1.3587e511bf47bp590, 0x1.c897858ce0ca9p48, 1.100000}, + {0x1.d12ee010c0facp590, 0x1.ab5b4b5065aa3p48, 1.100000}, + {0x1.87bbed5af48d9p605, 0x1.f512c3b2be7cap50, 1.100000}, + {0x1.a0b1131240cebp605, -0x1.fa373983fd571p48, 1.100000}, + {0x1.116fdda1a04c9p616, -0x1.d76fdbc8552f3p51, 1.100000}, + {0x1.67ebae833a034p620, 0x1.e1313af0a4075p50, 1.100000}, + {0x1.9a50fbc5b0fecp627, 0x1.d89150884fbf7p50, 1.100000}, + {0x1.6d625e0757e9cp631, -0x1.d0a5ecf002555p49, 1.100000}, + {0x1.e880344cc9913p636, -0x1.fafd04caaf58bp48, 1.100000}, + {0x1.e0a180b843cc5p650, 0x1.ea2aea3b8c953p49, 1.100000}, + {0x1.fa91ce15157b2p652, 0x1.e6f5f4d47d83fp48, 1.100000}, + {0x1.7696347caf8dfp654, 0x1.e0d36f2aef7dap51, 1.100000}, + {0x1.886484b536161p666, -0x1.e3c96481e335bp51, 1.100000}, + {0x1.0aa3ff2b41abdp675, -0x1.b3300ee04b4c8p50, 1.100000}, + {0x1.d695ac08fe897p675, -0x1.c27fd21ecb13p51, 1.100000}, + {0x1.4c1e532d7a99ap680, 0x1.e2ec695260c39p49, 1.100000}, + {0x1.44a9f3e395802p685, -0x1.e7273ab9ce8e2p52, 1.100000}, + {0x1.3a25ec2b43d45p697, -0x1.d23187ba6321ep49, 1.100000}, + {0x1.96f5c2420c3fdp716, -0x1.ea06ab71ad719p49, 1.100000}, + {0x1.926c063a9406bp741, 0x1.e3d3d9262fd66p48, 1.100000}, + {0x1.1a57713d6fd93p754, -0x1.c10074d49490dp48, 1.100000}, + {0x1.739387922e672p772, 0x1.bda527e215a3cp49, 1.100000}, + {0x1.d286eff17f4d4p793, 0x1.d01c678ebfa1p49, 1.100000}, + {0x1.f3d777206a062p794, -0x1.d8604b6d18385p49, 1.100000}, + {0x1.ae91e6574da91p826, -0x1.fd1b26ab656c2p49, 1.100000}, + {0x1.4422b3c871c9p836, 0x1.9d2cab1f3aebcp48, 1.100000}, + {0x1.7ff8537071e1p840, 0x1.badde451c6ed7p48, 1.100000}, + {0x1.c6fe9202e219dp845, -0x1.b2aa20745de3p51, 1.100000}, + {0x1.a95a0b4015d88p846, 0x1.cdf5dfd045657p50, 1.100000}, + {0x1.f823b9cff0daep867, 0x1.fd72fce3d5505p48, 1.100000}, + {0x1.a6bee2afcd2fp886, 0x1.fe06265cd3aebp49, 1.100000}, + {0x1.7b034b3412d17p892, 0x1.e48055812d391p50, 1.100000}, + {0x1.58588f8cda276p894, 0x1.f806fddf0dd05p53, 1.100000}, + {0x1.ce750a7963463p896, 0x1.e94f1f4018402p48, 1.100000}, + {0x1.3d50a91fe82cfp897, 0x1.cd518fda10e95p48, 1.100000}, + {0x1.f82dea1c0b809p897, -0x1.d6a0ef08179c5p48, 1.100000}, + {0x1.38673e8c6a4afp903, 0x1.f4113a036478p48, 1.100000}, + {0x1.dfb75e4a7432p911, 0x1.eb7bc6cb4d7f3p48, 1.100000}, + {0x1.1230b975a72b3p916, -0x1.e1042be0759f9p48, 1.100000}, + {0x1.302c2f5a4e6e5p916, 0x1.f66a9874cd60ap48, 1.100000}, + {0x1.04e07a1d67b93p921, 0x1.87735139f6a0bp53, 1.100000}, + {0x1.5a3eb79cd06fap931, -0x1.e00930c219ef3p51, 1.100000}, + {0x1.8fb45679936fp937, 0x1.9a427588645c4p50, 1.100000}, + {0x1.c4abb225260c6p964, -0x1.d1e64e91ac6ap50, 1.100000}, + {0x1.b43e449b25382p982, -0x1.f1848cc5ac4fep50, 1.100000}, + {0x1.504d9d7179b1ap983, 0x1.a4e51ea807786p48, 1.100000}, + {0x1.83a5af80fb39bp987, 0x1.a6dde6c2220ebp48, 1.100000}, + {0x1.5d978d9ad84c8p1011, 0x1.ec96900bfd1ddp51, 1.100000}, + }; + + for(double[] testCase: testCases) { + failures += testTanCase(testCase[0], testCase[1], testCase[2]); + } + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testTan(); + + if (failures > 0) { + System.err.println("Testing tan incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/Math/Tests.java b/jdk/test/java/lang/Math/Tests.java new file mode 100644 index 00000000000..f5f1edfbdd6 --- /dev/null +++ b/jdk/test/java/lang/Math/Tests.java @@ -0,0 +1,341 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * Shared static test methods for numerical tests. Sharing these + * helper test methods avoids repeated functions in the various test + * programs. The test methods return 1 for a test failure and 0 for + * success. The order of arguments to the test methods is generally + * the test name, followed by the test arguments, the computed result, + * and finally the expected result. + */ + +import sun.misc.FpUtils; + +public class Tests { + private Tests(){}; // do not instantiate + + private static String toHexString(float f) { + if (!Float.isNaN(f)) + return Float.toHexString(f); + else + return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")"; + } + + private static String toHexString(double d) { + if (!Double.isNaN(d)) + return Double.toHexString(d); + else + return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")"; + } + + public static int test(String testName, float input, + boolean result, boolean expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, double input, + boolean result, boolean expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, float input1, float input2, + boolean result, boolean expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\t(" + toHexString(input2) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + return 0; + } + + public static int test(String testName, double input1, double input2, + boolean result, boolean expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\t(" + toHexString(input2) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + return 0; + } + + public static int test(String testName, float input, + int result, int expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + return 0; + } + + public static int test(String testName, double input, + int result, int expected) { + if (expected != result) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\n" + + "\tgot " + result + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, float input, + float result, float expected) { + if (Float.compare(expected, result) != 0 ) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + + public static int test(String testName, double input, + double result, double expected) { + if (Double.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, + float input1, double input2, + float result, float expected) { + if (Float.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\t(" + toHexString(input2) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, + double input1, double input2, + double result, double expected) { + if (Double.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\t(" + toHexString(input2) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, + float input1, int input2, + float result, float expected) { + if (Float.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + public static int test(String testName, + double input1, int input2, + double result, double expected) { + if (Double.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + static int testUlpCore(double result, double expected, double ulps) { + // We assume we won't be unlucky and have an inexact expected + // be nextDown(2^i) when 2^i would be the correctly rounded + // answer. This would cause the ulp size to be half as large + // as it should be, doubling the measured error). + + if (Double.compare(expected, result) == 0) { + return 0; // result and expected are equivalent + } else { + if( ulps == 0.0) { + // Equivalent results required but not found + return 1; + } else { + double difference = expected - result; + if (FpUtils.isUnordered(expected, result) || + Double.isNaN(difference) || + // fail if greater than or unordered + !(Math.abs( difference/Math.ulp(expected) ) <= Math.abs(ulps)) ) { + return 1; + } + else + return 0; + } + } + } + + // One input argument. + public static int testUlpDiff(String testName, double input, + double result, double expected, double ulps) { + int code = testUlpCore(result, expected, ulps); + if (code == 1) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ");\n" + + "\tdifference greater than ulp tolerance " + ulps); + } + return code; + } + + // Two input arguments. + public static int testUlpDiff(String testName, double input1, double input2, + double result, double expected, double ulps) { + int code = testUlpCore(result, expected, ulps); + if (code == 1) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and " + + input2 + "\t(" + toHexString(input2) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ");\n" + + "\tdifference greater than ulp tolerance " + ulps); + } + return code; + } + + // For a successful test, the result must be within the ulp bound of + // expected AND the result must have absolute value less than or + // equal to absBound. + public static int testUlpDiffWithAbsBound(String testName, double input, + double result, double expected, + double ulps, double absBound) { + int code = 0; // return code value + + if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) && + !Double.isNaN(expected)) { + code = 1; + } else + code = testUlpCore(result, expected, ulps); + + if (code == 1) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ");\n" + + "\tdifference greater than ulp tolerance " + ulps + + " or the result has larger magnitude than " + absBound); + } + return code; + } + + // For a successful test, the result must be within the ulp bound of + // expected AND the result must have absolute value greater than + // or equal to the lowerBound. + public static int testUlpDiffWithLowerBound(String testName, double input, + double result, double expected, + double ulps, double lowerBound) { + int code = 0; // return code value + + if (!(result >= lowerBound) && !Double.isNaN(expected)) { + code = 1; + } else + code = testUlpCore(result, expected, ulps); + + if (code == 1) { + System.err.println("Failure for " + testName + + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")" + + "\n\texpected " + expected + "\t(" + toHexString(expected) + ")" + + "\n\tgot " + result + "\t(" + toHexString(result) + ");" + + "\ndifference greater than ulp tolerance " + ulps + + " or result not greater than or equal to the bound " + lowerBound); + } + return code; + } + + public static int testTolerance(String testName, double input, + double result, double expected, double tolerance) { + if (Double.compare(expected, result ) != 0) { + double difference = expected - result; + if (FpUtils.isUnordered(expected, result) || + Double.isNaN(difference) || + // fail if greater than or unordered + !(Math.abs((difference)/expected) <= StrictMath.pow(10, -tolerance)) ) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + toHexString(result) + ");\n" + + "\tdifference greater than tolerance 10^-" + tolerance); + return 1; + } + return 0; + } + else + return 0; + } +} diff --git a/jdk/test/java/lang/Short/ByteSwap.java b/jdk/test/java/lang/Short/ByteSwap.java new file mode 100644 index 00000000000..da249146159 --- /dev/null +++ b/jdk/test/java/lang/Short/ByteSwap.java @@ -0,0 +1,39 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4495754 + * @summary Basic test for int byte swap code on short and char + * @author Josh Bloch + */ + +public class ByteSwap { + public static void main(String args[]) { + if (Short.reverseBytes((short)0xaabb) != (short)0xbbaa) + throw new RuntimeException("short"); + + if (Character.reverseBytes((char)0xaabb) != (char)0xbbaa) + throw new RuntimeException("char"); + } +} diff --git a/jdk/test/java/lang/Short/Decode.java b/jdk/test/java/lang/Short/Decode.java new file mode 100644 index 00000000000..0a54036357d --- /dev/null +++ b/jdk/test/java/lang/Short/Decode.java @@ -0,0 +1,98 @@ +/* + * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4136371 5017980 6576055 + * @summary Test Short.decode method + * @author madbot + * @author Joseph D. Darcy + */ + +/** + * There are six methods in java.lang.Short which transform strings + * into a short or Short value: + * + * public Short(String s) + * public static Short decode(String nm) + * public static short parseShort(String s, int radix) + * public static short parseShort(String s) + * public static Short valueOf(String s, int radix) + * public static Short valueOf(String s) + * + * However, of these only decode has a nontrivial implementation + * in that class. + */ +public class Decode { + + private static void check(String ashort, short expected) { + short sh = (Short.decode(ashort)).shortValue(); + if (sh != expected) + throw new RuntimeException("Short.decode failed. String:" + + ashort + " Result:" + sh); + } + + private static void checkFailure(String val, String message) { + try { + short n = (Short.decode(val)).shortValue(); + throw new RuntimeException(message); + } catch (NumberFormatException e) { /* Okay */} + } + + public static void main(String[] args) throws Exception { + check(new String(""+Short.MIN_VALUE), Short.MIN_VALUE); + check(new String(""+Short.MAX_VALUE), Short.MAX_VALUE); + + check("10", (short)10); + check("0x10", (short)16); + check("0X10", (short)16); + check("010", (short)8); + check("#10", (short)16); + + check("+10", (short)10); + check("+0x10", (short)16); + check("+0X10", (short)16); + check("+010", (short)8); + check("+#10", (short)16); + + check("-10", (short)-10); + check("-0x10", (short)-16); + check("-0X10", (short)-16); + check("-010", (short)-8); + check("-#10", (short)-16); + + check(Integer.toString((int)Short.MIN_VALUE), Short.MIN_VALUE); + check(Integer.toString((int)Short.MAX_VALUE), Short.MAX_VALUE); + + checkFailure("0x-10", "Short.decode allows negative sign in wrong position."); + checkFailure("0x+10", "Short.decode allows positive sign in wrong position."); + + checkFailure("+", "Raw plus sign allowed."); + checkFailure("-", "Raw minus sign allowed."); + + checkFailure(Integer.toString((int)Short.MIN_VALUE - 1), "Out of range"); + checkFailure(Integer.toString((int)Short.MAX_VALUE + 1), "Out of range"); + + checkFailure("", "Empty String"); + } +} diff --git a/jdk/test/java/lang/StrictMath/CubeRootTests.java b/jdk/test/java/lang/StrictMath/CubeRootTests.java new file mode 100644 index 00000000000..a7eef55c5e3 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/CubeRootTests.java @@ -0,0 +1,473 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4347132 + * @summary Tests specifically for StrictMath.cbrt + * @author Joseph D. Darcy + */ + +/** + * The tests in ../Math/CubeRootTests.java test properties that should + * hold for any cube root implementation, including the FDLIBM-based + * one required for StrictMath.cbrt. Therefore, the test cases in + * ../Math/CubeRootTests.java are run against both the Math and + * StrictMath versions of cube root. The role of this test is to + * verify that the FDLIBM cbrt algorithm is being used by running + * golden file tests on values that may vary from one conforming cube + * root implementation to another. + */ + +public class CubeRootTests { + private CubeRootTests(){} + + static int testCubeRootCase(double input, double expected) { + int failures=0; + + double minus_input = -input; + double minus_expected = -expected; + + failures+=Tests.test("StrictMath.cbrt(double)", input, + StrictMath.cbrt(input), expected); + failures+=Tests.test("StrictMath.cbrt(double)", minus_input, + StrictMath.cbrt(minus_input), minus_expected); + return failures; + } + + static int testCubeRoot() { + int failures = 0; + double [][] testCases = { + {0x1.ffffffffffffep-766, 0x1.fffffffffffffp-256}, + {0x1.ffffffffffffep-763, 0x1.fffffffffffffp-255}, + {0x1.ffffffffffffep-760, 0x1.fffffffffffffp-254}, + {0x1.ffffffffffffep-757, 0x1.fffffffffffffp-253}, + {0x1.ffffffffffffep-754, 0x1.fffffffffffffp-252}, + {0x1.ffffffffffffep-751, 0x1.fffffffffffffp-251}, + {0x1.ffffffffffffep-748, 0x1.fffffffffffffp-250}, + {0x1.ffffffffffffep-745, 0x1.fffffffffffffp-249}, + {0x1.ffffffffffffep-742, 0x1.fffffffffffffp-248}, + {0x1.ffffffffffffep-739, 0x1.fffffffffffffp-247}, + {0x1.ffffffffffffep-1006, 0x1.fffffffffffffp-336}, + {0x1.ffffffffffffep-736, 0x1.fffffffffffffp-246}, + {0x1.ffffffffffffep-733, 0x1.fffffffffffffp-245}, + {0x1.ffffffffffffep-730, 0x1.fffffffffffffp-244}, + {0x1.ffffffffffffep-727, 0x1.fffffffffffffp-243}, + {0x1.ffffffffffffep-724, 0x1.fffffffffffffp-242}, + {0x1.ffffffffffffep-721, 0x1.fffffffffffffp-241}, + {0x1.ffffffffffffep-718, 0x1.fffffffffffffp-240}, + {0x1.ffffffffffffep-715, 0x1.fffffffffffffp-239}, + {0x1.ffffffffffffep-712, 0x1.fffffffffffffp-238}, + {0x1.ffffffffffffep-709, 0x1.fffffffffffffp-237}, + {0x1.ffffffffffffep-706, 0x1.fffffffffffffp-236}, + {0x1.ffffffffffffep-703, 0x1.fffffffffffffp-235}, + {0x1.ffffffffffffep-700, 0x1.fffffffffffffp-234}, + {0x1.ffffffffffffep-697, 0x1.fffffffffffffp-233}, + {0x1.ffffffffffffep-694, 0x1.fffffffffffffp-232}, + {0x1.ffffffffffffep-691, 0x1.fffffffffffffp-231}, + {0x1.ffffffffffffep-1003, 0x1.fffffffffffffp-335}, + {0x1.ffffffffffffep-688, 0x1.fffffffffffffp-230}, + {0x1.ffffffffffffep-685, 0x1.fffffffffffffp-229}, + {0x1.ffffffffffffep-682, 0x1.fffffffffffffp-228}, + {0x1.ffffffffffffep-679, 0x1.fffffffffffffp-227}, + {0x1.ffffffffffffep-676, 0x1.fffffffffffffp-226}, + {0x1.ffffffffffffep-673, 0x1.fffffffffffffp-225}, + {0x1.ffffffffffffep-670, 0x1.fffffffffffffp-224}, + {0x1.ffffffffffffep-667, 0x1.fffffffffffffp-223}, + {0x1.ffffffffffffep-664, 0x1.fffffffffffffp-222}, + {0x1.ffffffffffffep-661, 0x1.fffffffffffffp-221}, + {0x1.ffffffffffffep-658, 0x1.fffffffffffffp-220}, + {0x1.ffffffffffffep-655, 0x1.fffffffffffffp-219}, + {0x1.ffffffffffffep-652, 0x1.fffffffffffffp-218}, + {0x1.ffffffffffffep-649, 0x1.fffffffffffffp-217}, + {0x1.ffffffffffffep-646, 0x1.fffffffffffffp-216}, + {0x1.ffffffffffffep-643, 0x1.fffffffffffffp-215}, + {0x1.ffffffffffffep-1000, 0x1.fffffffffffffp-334}, + {0x1.ffffffffffffep-640, 0x1.fffffffffffffp-214}, + {0x1.ffffffffffffep-637, 0x1.fffffffffffffp-213}, + {0x1.ffffffffffffep-634, 0x1.fffffffffffffp-212}, + {0x1.ffffffffffffep-631, 0x1.fffffffffffffp-211}, + {0x1.ffffffffffffep-628, 0x1.fffffffffffffp-210}, + {0x1.ffffffffffffep-625, 0x1.fffffffffffffp-209}, + {0x1.ffffffffffffep-622, 0x1.fffffffffffffp-208}, + {0x1.ffffffffffffep-619, 0x1.fffffffffffffp-207}, + {0x1.ffffffffffffep-616, 0x1.fffffffffffffp-206}, + {0x1.ffffffffffffep-613, 0x1.fffffffffffffp-205}, + {0x1.ffffffffffffep-610, 0x1.fffffffffffffp-204}, + {0x1.ffffffffffffep-607, 0x1.fffffffffffffp-203}, + {0x1.ffffffffffffep-604, 0x1.fffffffffffffp-202}, + {0x1.ffffffffffffep-601, 0x1.fffffffffffffp-201}, + {0x1.ffffffffffffep-598, 0x1.fffffffffffffp-200}, + {0x1.ffffffffffffep-595, 0x1.fffffffffffffp-199}, + {0x1.ffffffffffffep-997, 0x1.fffffffffffffp-333}, + {0x1.ffffffffffffep-592, 0x1.fffffffffffffp-198}, + {0x1.ffffffffffffep-589, 0x1.fffffffffffffp-197}, + {0x1.ffffffffffffep-586, 0x1.fffffffffffffp-196}, + {0x1.ffffffffffffep-583, 0x1.fffffffffffffp-195}, + {0x1.ffffffffffffep-580, 0x1.fffffffffffffp-194}, + {0x1.ffffffffffffep-577, 0x1.fffffffffffffp-193}, + {0x1.ffffffffffffep-574, 0x1.fffffffffffffp-192}, + {0x1.ffffffffffffep-571, 0x1.fffffffffffffp-191}, + {0x1.ffffffffffffep-568, 0x1.fffffffffffffp-190}, + {0x1.ffffffffffffep-565, 0x1.fffffffffffffp-189}, + {0x1.ffffffffffffep-562, 0x1.fffffffffffffp-188}, + {0x1.ffffffffffffep-559, 0x1.fffffffffffffp-187}, + {0x1.ffffffffffffep-556, 0x1.fffffffffffffp-186}, + {0x1.ffffffffffffep-553, 0x1.fffffffffffffp-185}, + {0x1.ffffffffffffep-550, 0x1.fffffffffffffp-184}, + {0x1.ffffffffffffep-547, 0x1.fffffffffffffp-183}, + {0x1.ffffffffffffep-994, 0x1.fffffffffffffp-332}, + {0x1.ffffffffffffep-544, 0x1.fffffffffffffp-182}, + {0x1.ffffffffffffep-541, 0x1.fffffffffffffp-181}, + {0x1.ffffffffffffep-538, 0x1.fffffffffffffp-180}, + {0x1.ffffffffffffep-535, 0x1.fffffffffffffp-179}, + {0x1.ffffffffffffep-532, 0x1.fffffffffffffp-178}, + {0x1.ffffffffffffep-529, 0x1.fffffffffffffp-177}, + {0x0.00000000001fp-1022, 0x1.fa9c313858568p-356}, + {0x1.ffffffffffffep-526, 0x1.fffffffffffffp-176}, + {0x1.ffffffffffffep-523, 0x1.fffffffffffffp-175}, + {0x1.ffffffffffffep-520, 0x1.fffffffffffffp-174}, + {0x1.ffffffffffffep-517, 0x1.fffffffffffffp-173}, + {0x0.00000000001fdp-1022, 0x1.feff7f94ea34dp-356}, + {0x1.ffffffffffffep-514, 0x1.fffffffffffffp-172}, + {0x0.00000001fffe7p-1022, 0x1.ffff7aaa87f1bp-352}, + {0x0.00000001fffffp-1022, 0x1.fffffaaaaa9c7p-352}, + {0x0.00001ffffff4p-1022, 0x1.ffffffcp-348}, + {0x0.00001ffffffffp-1022, 0x1.ffffffffaaaabp-348}, + {0x0.01ffffffffffcp-1022, 0x1.ffffffffffeabp-344}, + {0x1.ffffffffffffep-511, 0x1.fffffffffffffp-171}, + {0x1.ffffffffffffep-508, 0x1.fffffffffffffp-170}, + {0x1.ffffffffffffep-505, 0x1.fffffffffffffp-169}, + {0x1.ffffffffffffep-502, 0x1.fffffffffffffp-168}, + {0x1.ffffffffffffep-499, 0x1.fffffffffffffp-167}, + {0x1.ffffffffffffep-991, 0x1.fffffffffffffp-331}, + {0x1.ffffffffffffep-496, 0x1.fffffffffffffp-166}, + {0x1.ffffffffffffep-493, 0x1.fffffffffffffp-165}, + {0x1.ffffffffffffep-490, 0x1.fffffffffffffp-164}, + {0x1.ffffffffffffep-487, 0x1.fffffffffffffp-163}, + {0x1.ffffffffffffep-484, 0x1.fffffffffffffp-162}, + {0x1.ffffffffffffep-481, 0x1.fffffffffffffp-161}, + {0x1.ffffffffffffep-478, 0x1.fffffffffffffp-160}, + {0x1.ffffffffffffep-475, 0x1.fffffffffffffp-159}, + {0x1.ffffffffffffep-472, 0x1.fffffffffffffp-158}, + {0x1.ffffffffffffep-469, 0x1.fffffffffffffp-157}, + {0x1.ffffffffffffep-466, 0x1.fffffffffffffp-156}, + {0x1.ffffffffffffep-463, 0x1.fffffffffffffp-155}, + {0x1.ffffffffffffep-460, 0x1.fffffffffffffp-154}, + {0x1.ffffffffffffep-457, 0x1.fffffffffffffp-153}, + {0x1.ffffffffffffep-454, 0x1.fffffffffffffp-152}, + {0x1.ffffffffffffep-451, 0x1.fffffffffffffp-151}, + {0x1.ffffffffffffep-988, 0x1.fffffffffffffp-330}, + {0x1.ffffffffffffep-448, 0x1.fffffffffffffp-150}, + {0x1.ffffffffffffep-445, 0x1.fffffffffffffp-149}, + {0x1.ffffffffffffep-442, 0x1.fffffffffffffp-148}, + {0x1.ffffffffffffep-439, 0x1.fffffffffffffp-147}, + {0x1.ffffffffffffep-436, 0x1.fffffffffffffp-146}, + {0x1.ffffffffffffep-433, 0x1.fffffffffffffp-145}, + {0x1.ffffffffffffep-430, 0x1.fffffffffffffp-144}, + {0x1.ffffffffffffep-427, 0x1.fffffffffffffp-143}, + {0x1.ffffffffffffep-424, 0x1.fffffffffffffp-142}, + {0x1.ffffffffffffep-421, 0x1.fffffffffffffp-141}, + {0x1.ffffffffffffep-418, 0x1.fffffffffffffp-140}, + {0x1.ffffffffffffep-415, 0x1.fffffffffffffp-139}, + {0x1.ffffffffffffep-412, 0x1.fffffffffffffp-138}, + {0x1.ffffffffffffep-409, 0x1.fffffffffffffp-137}, + {0x1.ffffffffffffep-406, 0x1.fffffffffffffp-136}, + {0x1.ffffffffffffep-403, 0x1.fffffffffffffp-135}, + {0x1.ffffffffffffep-985, 0x1.fffffffffffffp-329}, + {0x1.ffffffffffffep-400, 0x1.fffffffffffffp-134}, + {0x1.ffffffffffffep-397, 0x1.fffffffffffffp-133}, + {0x1.ffffffffffffep-394, 0x1.fffffffffffffp-132}, + {0x1.ffffffffffffep-391, 0x1.fffffffffffffp-131}, + {0x1.ffffffffffffep-388, 0x1.fffffffffffffp-130}, + {0x1.ffffffffffffep-385, 0x1.fffffffffffffp-129}, + {0x1.ffffffffffffep-382, 0x1.fffffffffffffp-128}, + {0x1.ffffffffffffep-379, 0x1.fffffffffffffp-127}, + {0x1.ffffffffffffep-376, 0x1.fffffffffffffp-126}, + {0x1.ffffffffffffep-373, 0x1.fffffffffffffp-125}, + {0x1.ffffffffffffep-370, 0x1.fffffffffffffp-124}, + {0x1.ffffffffffffep-367, 0x1.fffffffffffffp-123}, + {0x1.ffffffffffffep-364, 0x1.fffffffffffffp-122}, + {0x1.ffffffffffffep-361, 0x1.fffffffffffffp-121}, + {0x1.ffffffffffffep-358, 0x1.fffffffffffffp-120}, + {0x1.ffffffffffffep-355, 0x1.fffffffffffffp-119}, + {0x1.ffffffffffffep-982, 0x1.fffffffffffffp-328}, + {0x1.ffffffffffffep-352, 0x1.fffffffffffffp-118}, + {0x1.ffffffffffffep-349, 0x1.fffffffffffffp-117}, + {0x1.ffffffffffffep-346, 0x1.fffffffffffffp-116}, + {0x1.ffffffffffffep-343, 0x1.fffffffffffffp-115}, + {0x1.ffffffffffffep-340, 0x1.fffffffffffffp-114}, + {0x1.ffffffffffffep-337, 0x1.fffffffffffffp-113}, + {0x1.ffffffffffffep-334, 0x1.fffffffffffffp-112}, + {0x1.ffffffffffffep-331, 0x1.fffffffffffffp-111}, + {0x1.ffffffffffffep-328, 0x1.fffffffffffffp-110}, + {0x1.ffffffffffffep-325, 0x1.fffffffffffffp-109}, + {0x1.ffffffffffffep-322, 0x1.fffffffffffffp-108}, + {0x1.ffffffffffffep-319, 0x1.fffffffffffffp-107}, + {0x1.ffffffffffffep-316, 0x1.fffffffffffffp-106}, + {0x1.ffffffffffffep-313, 0x1.fffffffffffffp-105}, + {0x1.ffffffffffffep-310, 0x1.fffffffffffffp-104}, + {0x1.ffffffffffffep-307, 0x1.fffffffffffffp-103}, + {0x1.ffffffffffffep-979, 0x1.fffffffffffffp-327}, + {0x1.ffffffffffffep-304, 0x1.fffffffffffffp-102}, + {0x1.ffffffffffffep-301, 0x1.fffffffffffffp-101}, + {0x1.ffffffffffffep-298, 0x1.fffffffffffffp-100}, + {0x1.ffffffffffffep-295, 0x1.fffffffffffffp-99}, + {0x1.ffffffffffffep-292, 0x1.fffffffffffffp-98}, + {0x1.ffffffffffffep-289, 0x1.fffffffffffffp-97}, + {0x1.ffffffffffffep-286, 0x1.fffffffffffffp-96}, + {0x1.ffffffffffffep-283, 0x1.fffffffffffffp-95}, + {0x1.ffffffffffffep-280, 0x1.fffffffffffffp-94}, + {0x1.ffffffffffffep-277, 0x1.fffffffffffffp-93}, + {0x1.ffffffffffffep-274, 0x1.fffffffffffffp-92}, + {0x1.ffffffffffffep-271, 0x1.fffffffffffffp-91}, + {0x1.ffffffffffffep-268, 0x1.fffffffffffffp-90}, + {0x1.ffffffffffffep-265, 0x1.fffffffffffffp-89}, + {0x1.ffffffffffffep-262, 0x1.fffffffffffffp-88}, + {0x1.ffffffffffffep-259, 0x1.fffffffffffffp-87}, + {0x1.ffffffffffffep-1021, 0x1.fffffffffffffp-341}, + {0x1.ffffffffffffep-976, 0x1.fffffffffffffp-326}, + {0x1.ffffffffffffep-256, 0x1.fffffffffffffp-86}, + {0x1.ffffffffffffep-253, 0x1.fffffffffffffp-85}, + {0x1.ffffffffffffep-250, 0x1.fffffffffffffp-84}, + {0x1.ffffffffffffep-247, 0x1.fffffffffffffp-83}, + {0x1.ffffffffffffep-244, 0x1.fffffffffffffp-82}, + {0x1.ffffffffffffep-241, 0x1.fffffffffffffp-81}, + {0x1.ffffffffffffep-238, 0x1.fffffffffffffp-80}, + {0x1.ffffffffffffep-235, 0x1.fffffffffffffp-79}, + {0x1.ffffffffffffep-232, 0x1.fffffffffffffp-78}, + {0x1.ffffffffffffep-229, 0x1.fffffffffffffp-77}, + {0x1.ffffffffffffep-226, 0x1.fffffffffffffp-76}, + {0x1.ffffffffffffep-223, 0x1.fffffffffffffp-75}, + {0x1.ffffffffffffep-220, 0x1.fffffffffffffp-74}, + {0x1.ffffffffffffep-217, 0x1.fffffffffffffp-73}, + {0x1.ffffffffffffep-214, 0x1.fffffffffffffp-72}, + {0x1.ffffffffffffep-211, 0x1.fffffffffffffp-71}, + {0x1.ffffffffffffep-973, 0x1.fffffffffffffp-325}, + {0x1.ffffffffffffep-208, 0x1.fffffffffffffp-70}, + {0x1.ffffffffffffep-205, 0x1.fffffffffffffp-69}, + {0x1.ffffffffffffep-202, 0x1.fffffffffffffp-68}, + {0x1.ffffffffffffep-199, 0x1.fffffffffffffp-67}, + {0x1.ffffffffffffep-196, 0x1.fffffffffffffp-66}, + {0x1.ffffffffffffep-193, 0x1.fffffffffffffp-65}, + {0x1.ffffffffffffep-190, 0x1.fffffffffffffp-64}, + {0x1.ffffffffffffep-187, 0x1.fffffffffffffp-63}, + {0x1.ffffffffffffep-184, 0x1.fffffffffffffp-62}, + {0x1.ffffffffffffep-181, 0x1.fffffffffffffp-61}, + {0x1.ffffffffffffep-178, 0x1.fffffffffffffp-60}, + {0x1.ffffffffffffep-175, 0x1.fffffffffffffp-59}, + {0x1.ffffffffffffep-172, 0x1.fffffffffffffp-58}, + {0x1.ffffffffffffep-169, 0x1.fffffffffffffp-57}, + {0x1.ffffffffffffep-166, 0x1.fffffffffffffp-56}, + {0x1.ffffffffffffep-163, 0x1.fffffffffffffp-55}, + {0x1.ffffffffffffep-970, 0x1.fffffffffffffp-324}, + {0x1.ffffffffffffep-160, 0x1.fffffffffffffp-54}, + {0x1.ffffffffffffep-157, 0x1.fffffffffffffp-53}, + {0x1.ffffffffffffep-154, 0x1.fffffffffffffp-52}, + {0x1.ffffffffffffep-151, 0x1.fffffffffffffp-51}, + {0x1.ffffffffffffep-148, 0x1.fffffffffffffp-50}, + {0x1.ffffffffffffep-145, 0x1.fffffffffffffp-49}, + {0x1.ffffffffffffep-142, 0x1.fffffffffffffp-48}, + {0x1.ffffffffffffep-139, 0x1.fffffffffffffp-47}, + {0x1.ffffffffffffep-136, 0x1.fffffffffffffp-46}, + {0x1.ffffffffffffep-133, 0x1.fffffffffffffp-45}, + {0x1.ffffffffffffep-130, 0x1.fffffffffffffp-44}, + {0x1.ffffffffffffep-127, 0x1.fffffffffffffp-43}, + {0x1.ffffffffffffep-124, 0x1.fffffffffffffp-42}, + {0x1.ffffffffffffep-121, 0x1.fffffffffffffp-41}, + {0x1.ffffffffffffep-118, 0x1.fffffffffffffp-40}, + {0x1.ffffffffffffep-115, 0x1.fffffffffffffp-39}, + {0x1.ffffffffffffep-967, 0x1.fffffffffffffp-323}, + {0x1.ffffffffffffep-112, 0x1.fffffffffffffp-38}, + {0x1.ffffffffffffep-109, 0x1.fffffffffffffp-37}, + {0x1.ffffffffffffep-106, 0x1.fffffffffffffp-36}, + {0x1.ffffffffffffep-103, 0x1.fffffffffffffp-35}, + {0x1.ffffffffffffep-100, 0x1.fffffffffffffp-34}, + {0x1.ffffffffffffep-97, 0x1.fffffffffffffp-33}, + {0x1.ffffffffffffep-94, 0x1.fffffffffffffp-32}, + {0x1.ffffffffffffep-91, 0x1.fffffffffffffp-31}, + {0x1.ffffffffffffep-88, 0x1.fffffffffffffp-30}, + {0x1.ffffffffffffep-85, 0x1.fffffffffffffp-29}, + {0x1.ffffffffffffep-82, 0x1.fffffffffffffp-28}, + {0x1.ffffffffffffep-79, 0x1.fffffffffffffp-27}, + {0x1.ffffffffffffep-76, 0x1.fffffffffffffp-26}, + {0x1.ffffffffffffep-73, 0x1.fffffffffffffp-25}, + {0x1.ffffffffffffep-70, 0x1.fffffffffffffp-24}, + {0x1.ffffffffffffep-67, 0x1.fffffffffffffp-23}, + {0x1.ffffffffffffep-964, 0x1.fffffffffffffp-322}, + {0x1.ffffffffffffep-64, 0x1.fffffffffffffp-22}, + {0x1.ffffffffffffep-61, 0x1.fffffffffffffp-21}, + {0x1.ffffffffffffep-58, 0x1.fffffffffffffp-20}, + {0x1.ffffffffffffep-55, 0x1.fffffffffffffp-19}, + {0x1.ffffffffffffep-52, 0x1.fffffffffffffp-18}, + {0x1.ffffffffffffep-49, 0x1.fffffffffffffp-17}, + {0x1.ffffffffffffep-46, 0x1.fffffffffffffp-16}, + {0x1.ffffffffffffep-43, 0x1.fffffffffffffp-15}, + {0x1.ffffffffffffep-40, 0x1.fffffffffffffp-14}, + {0x1.ffffffffffffep-37, 0x1.fffffffffffffp-13}, + {0x1.ffffffffffffep-34, 0x1.fffffffffffffp-12}, + {0x1.ffffffffffffep-31, 0x1.fffffffffffffp-11}, + {0x1.ffffffffffffep-28, 0x1.fffffffffffffp-10}, + {0x1.ffffffffffffep-25, 0x1.fffffffffffffp-9}, + {0x1.ffffffffffffep-22, 0x1.fffffffffffffp-8}, + {0x0.000000000003ep-1022, 0x1.fa9c313858568p-357}, + {0x1.ffffffffffffep-19, 0x1.fffffffffffffp-7}, + {0x1.ffffffffffffep-961, 0x1.fffffffffffffp-321}, + {0x1.ffffffffffffep-16, 0x1.fffffffffffffp-6}, + {0x1.ffffffffffffep-13, 0x1.fffffffffffffp-5}, + {0x1.ffffffffffffep-10, 0x1.fffffffffffffp-4}, + {0x1.ffffffffffffep-7, 0x1.fffffffffffffp-3}, + {0x0.000000000003fp-1022, 0x1.fd51bf2069fe6p-357}, + {0x1.ffffffffffffep-4, 0x1.fffffffffffffp-2}, + {0x1.ffffffffffffep-1, 0x1.fffffffffffffp-1}, + {0x0.000000003fffcp-1022, 0x1.ffff55551c71bp-353}, + {0x0.000003fffffe8p-1022, 0x1.ffffffcp-349}, + {0x0.000003ffffffcp-1022, 0x1.fffffff555555p-349}, + {0x0.003fffffffff9p-1022, 0x1.fffffffffed55p-345}, + {0x1.ffffffffffffep2, 0x1.fffffffffffffp0}, + {0x1.bp4, 0x1.8p1}, + {0x1.ffffffffffffep5, 0x1.fffffffffffffp1}, + {0x1.f3ffffffffff4p6, 0x1.3fffffffffffep2}, + {0x1.f3ffffffffffcp6, 0x1.3ffffffffffffp2}, + {0x1.bp7, 0x1.8p2}, + {0x1.56ffffffffffep8, 0x1.bffffffffffffp2}, + {0x1.ffffffffffffep8, 0x1.fffffffffffffp2}, + {0x1.6c8p9, 0x1.2p3}, + {0x1.f3ffffffffff4p9, 0x1.3fffffffffffep3}, + {0x1.f3ffffffffffcp9, 0x1.3ffffffffffffp3}, + {0x1.4cbfffffffffcp10, 0x1.5fffffffffffep3}, + {0x1.4cbfffffffffep10, 0x1.5ffffffffffffp3}, + {0x1.bp10, 0x1.8p3}, + {0x1.129ffffffffa4p11, 0x1.9ffffffffffd1p3}, + {0x1.129fffffffffep11, 0x1.9ffffffffffffp3}, + {0x1.56ffffffffffep11, 0x1.bffffffffffffp3}, + {0x1.a5ep11, 0x1.ep3}, + {0x1.ffffffffffffep11, 0x1.fffffffffffffp3}, + {0x1.330fffffffc1ep12, 0x1.0fffffffffedbp4}, + {0x1.331p12, 0x1.1p4}, + {0x1.6c8p12, 0x1.2p4}, + {0x1.acafffffffffap12, 0x1.2ffffffffffffp4}, + {0x1.acafffffffffep12, 0x1.2ffffffffffffp4}, + {0x1.ffffffffffffep-958, 0x1.fffffffffffffp-320}, + {0x1.ffffffffffffep-955, 0x1.fffffffffffffp-319}, + {0x1.ffffffffffffep-952, 0x1.fffffffffffffp-318}, + {0x1.ffffffffffffep-949, 0x1.fffffffffffffp-317}, + {0x1.ffffffffffffep-946, 0x1.fffffffffffffp-316}, + {0x1.ffffffffffffep-943, 0x1.fffffffffffffp-315}, + {0x1.ffffffffffffep-940, 0x1.fffffffffffffp-314}, + {0x1.ffffffffffffep-937, 0x1.fffffffffffffp-313}, + {0x1.ffffffffffffep-934, 0x1.fffffffffffffp-312}, + {0x1.ffffffffffffep-931, 0x1.fffffffffffffp-311}, + {0x1.ffffffffffffep-1018, 0x1.fffffffffffffp-340}, + {0x1.ffffffffffffep-928, 0x1.fffffffffffffp-310}, + {0x1.ffffffffffffep-925, 0x1.fffffffffffffp-309}, + {0x1.ffffffffffffep-922, 0x1.fffffffffffffp-308}, + {0x1.ffffffffffffep-919, 0x1.fffffffffffffp-307}, + {0x1.ffffffffffffep-916, 0x1.fffffffffffffp-306}, + {0x1.ffffffffffffep-913, 0x1.fffffffffffffp-305}, + {0x1.ffffffffffffep-910, 0x1.fffffffffffffp-304}, + {0x1.ffffffffffffep-907, 0x1.fffffffffffffp-303}, + {0x1.ffffffffffffep-904, 0x1.fffffffffffffp-302}, + {0x0.0000000000007p-1022, 0x1.e9b5dba58189ep-358}, + {0x1.ffffffffffffep-901, 0x1.fffffffffffffp-301}, + {0x1.ffffffffffffep-898, 0x1.fffffffffffffp-300}, + {0x0.0000000007ffp-1022, 0x1.ffeaa9c70ca31p-354}, + {0x0.0000000007ffep-1022, 0x1.fffd5551c7149p-354}, + {0x0.0000007fffffdp-1022, 0x1.ffffffcp-350}, + {0x0.0000007fffffep-1022, 0x1.ffffffd555555p-350}, + {0x0.0007ffffffffap-1022, 0x1.fffffffff8p-346}, + {0x0.7ffffffffffffp-1022, 0x1.fffffffffffffp-342}, + {0x1.ffffffffffffep-895, 0x1.fffffffffffffp-299}, + {0x1.ffffffffffffep-892, 0x1.fffffffffffffp-298}, + {0x1.ffffffffffffep-889, 0x1.fffffffffffffp-297}, + {0x1.ffffffffffffep-886, 0x1.fffffffffffffp-296}, + {0x1.ffffffffffffep-883, 0x1.fffffffffffffp-295}, + {0x1.ffffffffffffep-1015, 0x1.fffffffffffffp-339}, + {0x1.ffffffffffffep-880, 0x1.fffffffffffffp-294}, + {0x1.ffffffffffffep-877, 0x1.fffffffffffffp-293}, + {0x1.ffffffffffffep-874, 0x1.fffffffffffffp-292}, + {0x1.ffffffffffffep-871, 0x1.fffffffffffffp-291}, + {0x1.ffffffffffffep-868, 0x1.fffffffffffffp-290}, + {0x1.ffffffffffffep-865, 0x1.fffffffffffffp-289}, + {0x1.ffffffffffffep-862, 0x1.fffffffffffffp-288}, + {0x1.ffffffffffffep-859, 0x1.fffffffffffffp-287}, + {0x1.ffffffffffffep-856, 0x1.fffffffffffffp-286}, + {0x1.ffffffffffffep-853, 0x1.fffffffffffffp-285}, + {0x1.ffffffffffffep-850, 0x1.fffffffffffffp-284}, + {0x1.ffffffffffffep-847, 0x1.fffffffffffffp-283}, + {0x1.ffffffffffffep-844, 0x1.fffffffffffffp-282}, + {0x1.ffffffffffffep-841, 0x1.fffffffffffffp-281}, + {0x1.ffffffffffffep-838, 0x1.fffffffffffffp-280}, + {0x1.ffffffffffffep-835, 0x1.fffffffffffffp-279}, + {0x1.ffffffffffffep-1012, 0x1.fffffffffffffp-338}, + {0x1.ffffffffffffep-832, 0x1.fffffffffffffp-278}, + {0x1.ffffffffffffep-829, 0x1.fffffffffffffp-277}, + {0x1.ffffffffffffep-826, 0x1.fffffffffffffp-276}, + {0x1.ffffffffffffep-823, 0x1.fffffffffffffp-275}, + {0x1.ffffffffffffep-820, 0x1.fffffffffffffp-274}, + {0x1.ffffffffffffep-817, 0x1.fffffffffffffp-273}, + {0x1.ffffffffffffep-814, 0x1.fffffffffffffp-272}, + {0x1.ffffffffffffep-811, 0x1.fffffffffffffp-271}, + {0x1.ffffffffffffep-808, 0x1.fffffffffffffp-270}, + {0x1.ffffffffffffep-805, 0x1.fffffffffffffp-269}, + {0x1.ffffffffffffep-802, 0x1.fffffffffffffp-268}, + {0x1.ffffffffffffep-799, 0x1.fffffffffffffp-267}, + {0x1.ffffffffffffep-796, 0x1.fffffffffffffp-266}, + {0x1.ffffffffffffep-793, 0x1.fffffffffffffp-265}, + {0x1.ffffffffffffep-790, 0x1.fffffffffffffp-264}, + {0x1.ffffffffffffep-787, 0x1.fffffffffffffp-263}, + {0x1.ffffffffffffep-1009, 0x1.fffffffffffffp-337}, + {0x1.ffffffffffffep-784, 0x1.fffffffffffffp-262}, + {0x1.ffffffffffffep-781, 0x1.fffffffffffffp-261}, + {0x1.ffffffffffffep-778, 0x1.fffffffffffffp-260}, + {0x1.ffffffffffffep-775, 0x1.fffffffffffffp-259}, + {0x1.ffffffffffffep-772, 0x1.fffffffffffffp-258}, + {0x1.ffffffffffffep-769, 0x1.fffffffffffffp-257}, + {0x0.0000000000ffep-1022, 0x1.ffeaa9c70ca31p-355}, + {0x0.0000000000fffp-1022, 0x1.fff5551c6fcd6p-355}, + {0x0.0000000ffff86p-1022, 0x1.ffffaeaa9dbf1p-351}, + {0x0.0000000ffffffp-1022, 0x1.ffffff5555552p-351}, + {0x0.0000ffffffap-1022, 0x1.ffffffcp-347}, + {0x0.0000ffffffff8p-1022, 0x1.ffffffffaaaabp-347}, + {0x0.0fffffffffffbp-1022, 0x1.fffffffffffcbp-343} + }; + + for(double[] testCase: testCases) + failures+=testCubeRootCase(testCase[0], testCase[1]); + + return failures; + } + + + public static void main(String [] argv) { + int failures = 0; + + failures += testCubeRoot(); + + if (failures > 0) { + System.err.println("Testing the cube root incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/Expm1Tests.java b/jdk/test/java/lang/StrictMath/Expm1Tests.java new file mode 100644 index 00000000000..667fa480cf0 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/Expm1Tests.java @@ -0,0 +1,795 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 + * @summary Tests for StrictMath.expm1 + * @author Joseph D. Darcy + */ + +/** + * The tests in ../Math/Expm1Tests.java test properties that should + * hold for any expm1 implementation, including the FDLIBM-based one + * required for StrictMath.expm1. Therefore, the test cases in + * ../Math/Expm1Tests.java are run against both the Math and + * StrictMath versions of expm1. The role of this test is to verify + * that the FDLIBM expm1 algorithm is being used by running golden + * file tests on values that may vary from one conforming expm1 + * implementation to another. + */ + +public class Expm1Tests { + private Expm1Tests(){} + + static int testExpm1Case(double input, double expected) { + return Tests.test("StrictMath.expm1(double)", input, + StrictMath.expm1(input), expected); + } + + static int testExpm1() { + int failures = 0; + + // Test cases in the range [-36.75, 710] + double [][] testCases = { + {-0x1.580000008c619p3, -0x1.fffd3069586f6p-1}, + {-0x1.380000008c721p3, -0x1.fff85bf4a6e98p-1}, + {-0x1.180000008c9fap3, -0x1.ffeb3aeb95524p-1}, + {-0x1.f0000001197ccp2, -0x1.ffc78aadc116ap-1}, + {-0x1.b0000001197e7p2, -0x1.ff6687cca710bp-1}, + {-0x1.70000001197f6p2, -0x1.fe5ed3992a519p-1}, + {-0x1.30000001198p2, -0x1.fb9201482bdfap-1}, + {-0x1.e000000233006p1, -0x1.f3f57b658d6fbp-1}, + {-0x1.6000000233012p1, -0x1.df44d8ee30b76p-1}, + {-0x1.c000000466028p0, -0x1.a7071a097ed5ep-1}, + {-0x1.80000008cc052p-1, -0x1.0e25f8a4a95b7p-1}, + {0x1.ffffffdccfeb7p-3, 0x1.22d78ef909144p-2}, + {0x1.3ffffffb99fd7p0, 0x1.3ec38ed3629a6p1}, + {0x1.1ffffffdccfebp1, 0x1.0f9b882a107edp3}, + {0x1.9ffffffdccfebp1, 0x1.8ca53b70fa11bp4}, + {0x1.0ffffffee67f6p2, 0x1.146bf132050c5p6}, + {0x1.4ffffffee67f5p2, 0x1.7b21ede9f0bdap7}, + {0x1.8ffffffee67f5p2, 0x1.0281a438aa523p9}, + {0x1.cffffffee67f5p2, 0x1.5fc6b5cf322c4p10}, + {0x1.07ffffff733fap3, 0x1.de5406b276b92p11}, + {0x1.27ffffff733fap3, 0x1.451c8690d1567p13}, + {0x1.47ffffff733fap3, 0x1.b9e62ae5924dfp14}, + {0x1.67ffffff733fap3, 0x1.2c4eeb7089cp16}, + {0x1.87ffffff733fap3, 0x1.982a24f2ab78ap17}, + {0x1.a7ffffff733fap3, 0x1.1560a14319349p19}, + {0x1.c7ffffff733fap3, 0x1.78fed772b40f2p20}, + {0x1.e7ffffff733fap3, 0x1.0031f18ee602fp22}, + {0x1.03ffffffb99fdp4, 0x1.5c348d8118f26p23}, + {0x1.13ffffffb99fdp4, 0x1.d942943e22d74p24}, + {0x1.23ffffffb99fcp4, 0x1.419d1309466ep26}, + {0x1.33ffffffb99fcp4, 0x1.b51e403430afep27}, + {0x1.43ffffffb99fcp4, 0x1.290d76c47bd4cp29}, + {0x1.53ffffffb99fcp4, 0x1.93bc8061146dp30}, + {0x1.63ffffffb99fbp4, 0x1.125e0665544a5p32}, + {0x1.73ffffffb99fbp4, 0x1.74e75f9de5d7cp33}, + {0x1.83ffffffb99fbp4, 0x1.fad42d3f28732p34}, + {0x1.93ffffffb99fbp4, 0x1.586d071cb8f87p36}, + {0x1.a3ffffffb99fbp4, 0x1.d41f91d0b4e6ep37}, + {0x1.b3ffffffb99fbp4, 0x1.3e1f6e5bc0242p39}, + {0x1.c3ffffffb99fbp4, 0x1.b05fa9aebfa64p40}, + {0x1.d3ffffffb99fbp4, 0x1.25d410cc90a38p42}, + {0x1.e3ffffffb99fbp4, 0x1.8f5aab33aa6c6p43}, + {0x1.f3ffffffb99fbp4, 0x1.0f63a91bc9797p45}, + {0x1.01ffffffdccfep5, 0x1.70db367c88b28p46}, + {0x1.09ffffffdccfep5, 0x1.f553e36d2975fp47}, + {0x1.11ffffffdccfep5, 0x1.54afff2230e99p49}, + {0x1.19ffffffdccfep5, 0x1.cf0ad451f1e9fp50}, + {0x1.21ffffffdccfep5, 0x1.3aab7c88ef991p52}, + {0x1.29ffffffdccfep5, 0x1.abae41ecccd22p53}, + {0x1.31ffffffdccfep5, 0x1.22a3a0462535fp55}, + {0x1.39ffffffdccfdp5, 0x1.8b050329f95c8p56}, + {0x1.41ffffffdccfdp5, 0x1.0c719224d80a2p58}, + {0x1.49ffffffdccfdp5, 0x1.6cda4c755ea56p59}, + {0x1.51ffffffdccfdp5, 0x1.efe2e2b6ad6ebp60}, + {0x1.59ffffffdccfdp5, 0x1.50fd5a6337c61p62}, + {0x1.61ffffffdccfdp5, 0x1.ca043518d78acp63}, + {0x1.69ffffffdccfdp5, 0x1.374122dd2fbdbp65}, + {0x1.71ffffffdccfdp5, 0x1.a709e46cc671ep66}, + {0x1.79ffffffdccfdp5, 0x1.1f7c0c5482bf3p68}, + {0x1.81ffffffdccfdp5, 0x1.86bb667297515p69}, + {0x1.89ffffffdccfcp5, 0x1.0987aa8375abcp71}, + {0x1.91ffffffdccfcp5, 0x1.68e48248f27ddp72}, + {0x1.99ffffffdccfcp5, 0x1.ea8100a2e27e9p73}, + {0x1.a1ffffffdccfcp5, 0x1.4d54fc02d9352p75}, + {0x1.a9ffffffdccfcp5, 0x1.c50b8ceab6ad1p76}, + {0x1.b1ffffffdccfcp5, 0x1.33e046afc7062p78}, + {0x1.b9ffffffdccfcp5, 0x1.a2726cf2e78e3p79}, + {0x1.c1ffffffdccfcp5, 0x1.1c5d3c581edf2p81}, + {0x1.c9ffffffdccfcp5, 0x1.827db3961daecp82}, + {0x1.d1ffffffdccfbp5, 0x1.06a5db797b4b2p84}, + {0x1.d9ffffffdccfbp5, 0x1.64f9b90e23fb4p85}, + {0x1.e1ffffffdccfbp5, 0x1.e52e132ebafe2p86}, + {0x1.e9ffffffdccfbp5, 0x1.49b6c774442efp88}, + {0x1.f1ffffffdccfbp5, 0x1.c020b4f9d926cp89}, + {0x1.f9ffffffdccfbp5, 0x1.3088cda20d465p91}, + {0x1.00ffffffee67ep6, 0x1.9de7b7a818186p92}, + {0x1.04ffffffee67ep6, 0x1.194717f5da259p94}, + {0x1.08ffffffee67ep6, 0x1.7e4bc97a2360dp95}, + {0x1.0cffffffee67ep6, 0x1.03cc0e87f367bp97}, + {0x1.10ffffffee67ep6, 0x1.6119d231b67f5p98}, + {0x1.14ffffffee67ep6, 0x1.dfe9f0cbe5942p99}, + {0x1.18ffffffee67ep6, 0x1.4622a079fc2a6p101}, + {0x1.1cffffffee67ep6, 0x1.bb4386e45ae94p102}, + {0x1.20ffffffee67ep6, 0x1.2d3a9d9e9fe6p104}, + {0x1.24ffffffee67ep6, 0x1.9969a118d6261p105}, + {0x1.28ffffffee67ep6, 0x1.1639871642331p107}, + {0x1.2cffffffee67ep6, 0x1.7a2587603a84bp108}, + {0x1.30ffffffee67ep6, 0x1.00fa2d6e6a76ep110}, + {0x1.34ffffffee67ep6, 0x1.5d44af7562574p111}, + {0x1.38ffffffee67ep6, 0x1.dab4705f88c02p112}, + {0x1.3cffffffee67ep6, 0x1.42986b24fc9dcp114}, + {0x1.40ffffffee67ep6, 0x1.b673dcb2fe519p115}, + {0x1.44ffffffee67ep6, 0x1.29f59cd896383p117}, + {0x1.48ffffffee67ep6, 0x1.94f806342143cp118}, + {0x1.4cffffffee67ep6, 0x1.133471e4d5b38p120}, + {0x1.50ffffffee67ep6, 0x1.760acce4f0e03p121}, + {0x1.54ffffffee67ep6, 0x1.fc604454828ddp122}, + {0x1.58ffffffee67ep6, 0x1.597a32eee8c46p124}, + {0x1.5cffffffee67ep6, 0x1.d58d694102246p125}, + {0x1.60ffffffee67ep6, 0x1.3f180bd3df0d2p127}, + {0x1.64ffffffee67ep6, 0x1.b1b190d803f07p128}, + {0x1.68ffffffee67ep6, 0x1.26b9b1cab82dap130}, + {0x1.6cffffffee67ep6, 0x1.9092c44a68bc1p131}, + {0x1.70ffffffee67ep6, 0x1.1037c0cf4a5a6p133}, + {0x1.74ffffffee67ep6, 0x1.71fb79fed30fbp134}, + {0x1.78ffffffee67ep6, 0x1.f6dbadec024eep135}, + {0x1.7cffffffee67ep6, 0x1.55ba3f072a6dbp137}, + {0x1.80ffffffee67ep6, 0x1.d074b338a9163p138}, + {0x1.84ffffffee67ep6, 0x1.3ba167320351ap140}, + {0x1.88ffffffee67ep6, 0x1.acfc7e2e0558bp141}, + {0x1.8cffffffee67ep6, 0x1.2386c336b7163p143}, + {0x1.90ffffffee67ep6, 0x1.8c39b90c7cdap144}, + {0x1.94ffffffee67ep6, 0x1.0d435c84d4e66p146}, + {0x1.98ffffffee67ep6, 0x1.6df76efd7275ep147}, + {0x1.9cffffffee67ep6, 0x1.f1666c9163f86p148}, + {0x1.a0ffffffee67ep6, 0x1.5204b679406b7p150}, + {0x1.a4ffffffee67ep6, 0x1.cb6a267e94b7ap151}, + {0x1.a8ffffffee67ep6, 0x1.38346236ba483p153}, + {0x1.acffffffee67ep6, 0x1.a8547ff6d3311p154}, + {0x1.b0ffffffee67ep6, 0x1.205cb8246899ap156}, + {0x1.b4ffffffee67ep6, 0x1.87ecc28a831c1p157}, + {0x1.b8ffffffee67ep6, 0x1.0a572df57323ep159}, + {0x1.bcffffffee67ep6, 0x1.69fe8c886de24p160}, + {0x1.c0ffffffee67ep6, 0x1.ec0055aa644acp161}, + {0x1.c4ffffffee67ep6, 0x1.4e597c5197d13p163}, + {0x1.c8ffffffee67ep6, 0x1.c66d9bb965746p164}, + {0x1.ccffffffee67ep6, 0x1.34d0e22472ce2p166}, + {0x1.d0ffffffee67ep6, 0x1.a3b971da5668ap167}, + {0x1.d4ffffffee67ep6, 0x1.1d3b77e103d1ap169}, + {0x1.d8ffffffee67ep6, 0x1.83abbf32ed4f6p170}, + {0x1.dcffffffee67ep6, 0x1.07731e5137e95p172}, + {0x1.e0ffffffee67ep6, 0x1.6610b39e7ce7p173}, + {0x1.e4ffffffee67ep6, 0x1.e6a93f132076cp174}, + {0x1.e8ffffffee67ep6, 0x1.4ab873ed0fb2cp176}, + {0x1.ecffffffee67ep6, 0x1.c17eebfd11debp177}, + {0x1.f0ffffffee67ep6, 0x1.3176cc87e9082p179}, + {0x1.f4ffffffee67ep6, 0x1.9f2b2fe57487ap180}, + {0x1.f8ffffffee67ep6, 0x1.1a22e9fe60816p182}, + {0x1.fcffffffee67ep6, 0x1.7f768dd1738aap183}, + {0x1.007ffffff733fp7, 0x1.049717079907bp185}, + {0x1.027ffffff733fp7, 0x1.622dc5947dd63p186}, + {0x1.047ffffff733fp7, 0x1.e160ff1ccd30cp187}, + {0x1.067ffffff733fp7, 0x1.472180f8199d7p189}, + {0x1.087ffffff733fp7, 0x1.bc9df0c9b6e0fp190}, + {0x1.0a7ffffff733fp7, 0x1.2e26073757ed6p192}, + {0x1.0c7ffffff733fp7, 0x1.9aa99688f714bp193}, + {0x1.0e7ffffff733fp7, 0x1.1712f6523864dp195}, + {0x1.107ffffff733fp7, 0x1.7b4d0d8e11012p196}, + {0x1.127ffffff733fp7, 0x1.01c301c6bf29cp198}, + {0x1.147ffffff733fp7, 0x1.5e55a41486608p199}, + {0x1.167ffffff733fp7, 0x1.dc276c8c7156p200}, + {0x1.187ffffff733fp7, 0x1.4394876ddc7dap202}, + {0x1.1a7ffffff733fp7, 0x1.b7ca840a6b3bap203}, + {0x1.1c7ffffff733fp7, 0x1.2ade7851ad0fep205}, + {0x1.1e7ffffff733fp7, 0x1.963482987606p206}, + {0x1.207ffffff733fp7, 0x1.140b84f56a91bp208}, + {0x1.227ffffff733fp7, 0x1.772f1dec03a66p209}, + {0x1.247ffffff733fp7, 0x1.fded90f5af3ap210}, + {0x1.267ffffff733fp7, 0x1.5a88311cf6cbdp212}, + {0x1.287ffffff733fp7, 0x1.d6fc5e99a419dp213}, + {0x1.2a7ffffff733fp7, 0x1.40116b9759ebap215}, + {0x1.2c7ffffff733fp7, 0x1.b304801416466p216}, + {0x1.2e7ffffff733fp7, 0x1.27a0063dbe9cep218}, + {0x1.307ffffff733fp7, 0x1.91cbd14945353p219}, + {0x1.327ffffff733fp7, 0x1.110c7e4340e4fp221}, + {0x1.347ffffff733fp7, 0x1.731c9ec8ce996p222}, + {0x1.367ffffff733fp7, 0x1.f864aa9acffbdp223}, + {0x1.387ffffff733fp7, 0x1.56c54eff8fbcdp225}, + {0x1.3a7ffffff733fp7, 0x1.d1dfaced4eb1p226}, + {0x1.3c7ffffff733fp7, 0x1.3c98120a95d78p228}, + {0x1.3e7ffffff733fp7, 0x1.ae4bbfa449eaap229}, + {0x1.407ffffff733fp7, 0x1.246a97a9838dcp231}, + {0x1.427ffffff733fp7, 0x1.8d6f603164cebp232}, + {0x1.447ffffff733fp7, 0x1.0e15cad8b775ep234}, + {0x1.467ffffff733fp7, 0x1.6f15705b3f514p235}, + {0x1.487ffffff733fp7, 0x1.f2eb25494787dp236}, + {0x1.4a7ffffff733fp7, 0x1.530ce0608a8acp238}, + {0x1.4c7ffffff733fp7, 0x1.ccd12fa07172p239}, + {0x1.4e7ffffff733fp7, 0x1.39285fa9c08e7p241}, + {0x1.507ffffff733fp7, 0x1.a9a01de01fd02p242}, + {0x1.527ffffff733fp7, 0x1.213e13894e05p244}, + {0x1.547ffffff733fp7, 0x1.891f0d4674b33p245}, + {0x1.567ffffff733fp7, 0x1.0b275393c60b2p247}, + {0x1.587ffffff733fp7, 0x1.6b1973327581dp248}, + {0x1.5a7ffffff733fp7, 0x1.ed80d645874cfp249}, + {0x1.5c7ffffff733fp7, 0x1.4f5ec835b4172p251}, + {0x1.5e7ffffff733fp7, 0x1.c7d0bf3aec5fcp252}, + {0x1.607ffffff733fp7, 0x1.35c239a263125p254}, + {0x1.627ffffff733fp7, 0x1.a501765319bp255}, + {0x1.647ffffff733fp7, 0x1.1e1a611707cfbp257}, + {0x1.667ffffff733fp7, 0x1.84dab6dcaac3cp258}, + {0x1.687ffffff733fp7, 0x1.08410192ab89ep260}, + {0x1.6a7ffffff733fp7, 0x1.67288834edb2fp261}, + {0x1.6c7ffffff733fp7, 0x1.e825934abdad9p262}, + {0x1.6e7ffffff733fp7, 0x1.4bbae9c58a222p264}, + {0x1.707ffffff733fp7, 0x1.c2de34b24b161p265}, + {0x1.727ffffff733fp7, 0x1.3265856c8dbdcp267}, + {0x1.747ffffff733fp7, 0x1.a06fa4ee04c8ep268}, + {0x1.767ffffff733fp7, 0x1.1aff67d171068p270}, + {0x1.787ffffff733fp7, 0x1.80a23ba5cc0fep271}, + {0x1.7a7ffffff733fp7, 0x1.0562be333b5b6p273}, + {0x1.7c7ffffff733fp7, 0x1.6342909f8e806p274}, + {0x1.7e7ffffff733fp7, 0x1.e2d932898c11cp275}, + {0x1.807ffffff733ep7, 0x1.482128a65b0aap277}, + {0x1.827ffffff733ep7, 0x1.bdf9696894p278}, + {0x1.847ffffff733ep7, 0x1.2f1228ca0924p280}, + {0x1.867ffffff733ep7, 0x1.9bea8605e05b8p281}, + {0x1.887ffffff733ep7, 0x1.17ed0f7b60befp283}, + {0x1.8a7ffffff733ep7, 0x1.7c757ab028d2cp284}, + {0x1.8c7ffffff733ep7, 0x1.028c73122cbaap286}, + {0x1.8e7ffffff733ep7, 0x1.5f676e04b872p287}, + {0x1.907ffffff733ep7, 0x1.dd9b8aa6c07f4p288}, + {0x1.927ffffff733ep7, 0x1.449168bd6830bp290}, + {0x1.947ffffff733ep7, 0x1.b922372b1b22fp291}, + {0x1.967ffffff733ep7, 0x1.2bc809c589606p293}, + {0x1.987ffffff733ep7, 0x1.9771f652c776ap294}, + {0x1.9a7ffffff733ep7, 0x1.14e3401b07fc7p296}, + {0x1.9c7ffffff733ep7, 0x1.785453659b7d4p297}, + {0x1.9e7ffffff733ep7, 0x1.ff7c1414d829fp298}, + {0x1.a07ffffff733ep7, 0x1.5b97024b58a63p300}, + {0x1.a27ffffff733ep7, 0x1.d86c72ba13072p301}, + {0x1.a47ffffff733ep7, 0x1.410b8e3e0a59p303}, + {0x1.a67ffffff733ep7, 0x1.b458783157a34p304}, + {0x1.a87ffffff733ep7, 0x1.28870eb1e33efp306}, + {0x1.aa7ffffff733ep7, 0x1.9305d2eedd47p307}, + {0x1.ac7ffffff733ep7, 0x1.11e1e1f93656cp309}, + {0x1.ae7ffffff733ep7, 0x1.743ea58a8a142p310}, + {0x1.b07ffffff733ep7, 0x1.f9eeda68dbff6p311}, + {0x1.b27ffffff733ep7, 0x1.57d12fadfda18p313}, + {0x1.b47ffffff733ep7, 0x1.d34bc24ce61e7p314}, + {0x1.b67ffffff733ep7, 0x1.3d8f7da8d8d95p316}, + {0x1.b87ffffff733ep7, 0x1.af9c071bbd116p317}, + {0x1.ba7ffffff733ep7, 0x1.254f1e2943f7fp319}, + {0x1.bc7ffffff733ep7, 0x1.8ea5f9553ce5ep320}, + {0x1.be7ffffff733ep7, 0x1.0ee8dda0a100cp322}, + {0x1.c07ffffff733ep7, 0x1.7034513ceac7dp323}, + {0x1.c27ffffff733ep7, 0x1.f4710dcb08bdcp324}, + {0x1.c47ffffff733ep7, 0x1.5415d8b9ef19cp326}, + {0x1.c67ffffff733ep7, 0x1.ce3951590b045p327}, + {0x1.c87ffffff733ep7, 0x1.3a1d1bcad2ec4p329}, + {0x1.ca7ffffff733ep7, 0x1.aaecbef297a4ap330}, + {0x1.cc7ffffff733ep7, 0x1.22201f0c6ae88p332}, + {0x1.ce7ffffff733ep7, 0x1.8a524760ebdc1p333}, + {0x1.d07ffffff733ep7, 0x1.0bf81bdd2ba52p335}, + {0x1.d27ffffff733ep7, 0x1.6c3536f34b0c2p336}, + {0x1.d47ffffff733ep7, 0x1.ef02835e6a7d8p337}, + {0x1.d67ffffff733ep7, 0x1.5064e04e480fep339}, + {0x1.d87ffffff733ep7, 0x1.c934f847894a8p340}, + {0x1.da7ffffff733ep7, 0x1.36b44dbc8b633p342}, + {0x1.dc7ffffff733ep7, 0x1.a64a7b24ebae2p343}, + {0x1.de7ffffff733ep7, 0x1.1ef9f881e57b8p345}, + {0x1.e07ffffff733ep7, 0x1.860a9b4bcf9dfp346}, + {0x1.e27ffffff733ep7, 0x1.090f85bb33493p348}, + {0x1.e47ffffff733ep7, 0x1.6841377bd96e9p349}, + {0x1.e67ffffff733ep7, 0x1.e9a310bd2715dp350}, + {0x1.e87ffffff733ep7, 0x1.4cbe299b1372dp352}, + {0x1.ea7ffffff733ep7, 0x1.c43e8fef69d0dp353}, + {0x1.ec7ffffff733ep7, 0x1.3354f8e156a72p355}, + {0x1.ee7ffffff733ep7, 0x1.a1b51787582dfp356}, + {0x1.f07ffffff733ep7, 0x1.1bdc91f54d333p358}, + {0x1.f27ffffff733ep7, 0x1.81ced3ada5ec9p359}, + {0x1.f47ffffff733ep7, 0x1.062f0486db268p361}, + {0x1.f67ffffff733ep7, 0x1.645833fb72196p362}, + {0x1.f87ffffff733ep7, 0x1.e4528bf7332d2p363}, + {0x1.fa7ffffff733ep7, 0x1.492198206b3aep365}, + {0x1.fc7ffffff733ep7, 0x1.bf55f194851b5p366}, + {0x1.fe7ffffff733ep7, 0x1.2fff02e67affep368}, + {0x1.003ffffffb99fp8, 0x1.9d2c7052fc80ep369}, + {0x1.013ffffffb99fp8, 0x1.18c7d31687cep371}, + {0x1.023ffffffb99fp8, 0x1.7d9ecf7b00132p372}, + {0x1.033ffffffb99fp8, 0x1.035681cb5b766p374}, + {0x1.043ffffffb99fp8, 0x1.607a0decadfaep375}, + {0x1.053ffffffb99fp8, 0x1.df10cb910ae14p376}, + {0x1.063ffffffb99fp8, 0x1.458f0fad99f57p378}, + {0x1.073ffffffb99fp8, 0x1.ba7af6e654fa2p379}, + {0x1.083ffffffb99fp8, 0x1.2cb251c2631d6p381}, + {0x1.093ffffffb99fp8, 0x1.98b06224611f2p382}, + {0x1.0a3ffffffb99fp8, 0x1.15bba3d909807p384}, + {0x1.0b3ffffffb99fp8, 0x1.797a6e0440f8fp385}, + {0x1.0c3ffffffb99fp8, 0x1.0085e752522ap387}, + {0x1.0d3ffffffb99fp8, 0x1.5ca6a71ef489ep388}, + {0x1.0e3ffffffb99fp8, 0x1.d9dda6826dfc7p389}, + {0x1.0f3ffffffb99fp8, 0x1.420674603ebb2p391}, + {0x1.103ffffffb99fp8, 0x1.b5ad79fec979p392}, + {0x1.113ffffffb99fp8, 0x1.296ecbb3d2db7p394}, + {0x1.123ffffffb99fp8, 0x1.9440c9fa6362ap395}, + {0x1.133ffffffb99fp8, 0x1.12b7ec73193e4p397}, + {0x1.143ffffffb99fp8, 0x1.75618ef49dffep398}, + {0x1.153ffffffb99fp8, 0x1.fb7a3e462b12ap399}, + {0x1.163ffffffb99fp8, 0x1.58dde1b590206p401}, + {0x1.173ffffffb99fp8, 0x1.d4b8f4351faecp402}, + {0x1.183ffffffb99fp8, 0x1.3e87aaa373892p404}, + {0x1.193ffffffb99fp8, 0x1.b0ed5561210d9p405}, + {0x1.1a3ffffffb99fp8, 0x1.263457411e3a5p407}, + {0x1.1b3ffffffb99fp8, 0x1.8fdd8535244cdp408}, + {0x1.1c3ffffffb99fp8, 0x1.0fbc955d170d1p410}, + {0x1.1d3ffffffb99fp8, 0x1.7154125122a86p411}, + {0x1.1e3ffffffb99fp8, 0x1.f5f8270411675p412}, + {0x1.1f3ffffffb99fp8, 0x1.551fa026c4e4cp414}, + {0x1.203ffffffb99fp8, 0x1.cfa28c83a9c15p415}, + {0x1.213ffffffb99fp8, 0x1.3b12972ef5f7ap417}, + {0x1.223ffffffb99fp8, 0x1.ac3a63f8c3fc9p418}, + {0x1.233ffffffb99fp8, 0x1.2302db376285dp420}, + {0x1.243ffffffb99fp8, 0x1.8b867194fa443p421}, + {0x1.253ffffffb99fp8, 0x1.0cc98750c45aep423}, + {0x1.263ffffffb99fp8, 0x1.6d51d877b6f1bp424}, + {0x1.273ffffffb99fp8, 0x1.f0855ddfe3faap425}, + {0x1.283ffffffb99fp8, 0x1.516bc53aea3aap427}, + {0x1.293ffffffb99fp8, 0x1.ca9a47b823396p428}, + {0x1.2a3ffffffb99fp8, 0x1.37a71f0652462p430}, + {0x1.2b3ffffffb99fp8, 0x1.a794811822eb3p431}, + {0x1.2c3ffffffb99fp8, 0x1.1fda3ea9c1a4fp433}, + {0x1.2d3ffffffb99fp8, 0x1.873b6d3965cp434}, + {0x1.2e3ffffffb99fp8, 0x1.09deab488e539p436}, + {0x1.2f3ffffffb99fp8, 0x1.695ac21e2870ep437}, + {0x1.303ffffffb99fp8, 0x1.eb21b852a647cp438}, + {0x1.313ffffffb99fp8, 0x1.4dc2340b86b4cp440}, + {0x1.323ffffffb99fp8, 0x1.c59ffe8afa62cp441}, + {0x1.333ffffffb99fp8, 0x1.3445277810b78p443}, + {0x1.343ffffffb99fp8, 0x1.a2fb88779894fp444}, + {0x1.353ffffffb99fp8, 0x1.1cba68f09f8c5p446}, + {0x1.363ffffffb99fp8, 0x1.82fc56a008db6p447}, + {0x1.373ffffffb99fp8, 0x1.06fbea7eda2dfp449}, + {0x1.383ffffffb99fp8, 0x1.656eb0513614ep450}, + {0x1.393ffffffb99fp8, 0x1.e5cd0c4b86aaap451}, + {0x1.3a3ffffffb99fp8, 0x1.4a22d0026e7ffp453}, + {0x1.3b3ffffffb99fp8, 0x1.c0b38a21c236cp454}, + {0x1.3c3ffffffb99fp8, 0x1.30ec961ce5379p456}, + {0x1.3d3ffffffb99fp8, 0x1.9e6f56344e9dp457}, + {0x1.3e3ffffffb99fp8, 0x1.19a341a8e1ccbp459}, + {0x1.3f3ffffffb99fp8, 0x1.7ec90ca3a1c6dp460}, + {0x1.403ffffffb99fp8, 0x1.04212e6d536d6p462}, + {0x1.413ffffffb99fp8, 0x1.618d84739e91cp463}, + {0x1.423ffffffb99fp8, 0x1.e087302e9607ap464}, + {0x1.433ffffffb99fp8, 0x1.468d7cd8e4417p466}, + {0x1.443ffffffb99fp8, 0x1.bbd4c40e0317cp467}, + {0x1.453ffffffb99fp8, 0x1.2d9d50d6e1436p469}, + {0x1.463ffffffb99fp8, 0x1.99efc6cf25729p470}, + {0x1.473ffffffb99fp8, 0x1.1694b0b33138ap472}, + {0x1.483ffffffb99fp8, 0x1.7aa16e7b0810dp473}, + {0x1.493ffffffb99fp8, 0x1.014e60cc3c10bp475}, + {0x1.4a3ffffffb99fp8, 0x1.5db7203d316b3p476}, + {0x1.4b3ffffffb99fp8, 0x1.db4ffad383047p477}, + {0x1.4c3ffffffb99fp8, 0x1.43021e96bc60ep479}, + {0x1.4d3ffffffb99fp8, 0x1.b703864c0ed74p480}, + {0x1.4e3ffffffb99fp8, 0x1.2a573dd0a80e6p482}, + {0x1.4f3ffffffb99fp8, 0x1.957cb72b9f3f6p483}, + {0x1.503ffffffb99fp8, 0x1.138e9e333d9afp485}, + {0x1.513ffffffb99fp8, 0x1.76855bb82cbcep486}, + {0x1.523ffffffb99fp8, 0x1.fd06d7237d52bp487}, + {0x1.533ffffffb99fp8, 0x1.59eb65b9e296ap489}, + {0x1.543ffffffb99fp8, 0x1.d627438458c6ap490}, + {0x1.553ffffffb99fp8, 0x1.3f80999182b7ap492}, + {0x1.563ffffffb99fp8, 0x1.b23fab41d7fcdp493}, + {0x1.573ffffffb99fp8, 0x1.271a437ca4dd9p495}, + {0x1.583ffffffb99fp8, 0x1.9116048ecdd82p496}, + {0x1.593ffffffb99fp8, 0x1.1090f28f03784p498}, + {0x1.5a3ffffffb99fp8, 0x1.7274b4471d222p499}, + {0x1.5b3ffffffb99fp8, 0x1.f78071e284acfp500}, + {0x1.5c3ffffffb99fp8, 0x1.562a3748e0ae8p502}, + {0x1.5d3ffffffb99fp8, 0x1.d10ce1fc412f2p503}, + {0x1.5e3ffffffb99fp8, 0x1.3c08d26ba29edp505}, + {0x1.5f3ffffffb99fp8, 0x1.ad890dbdcc46ap506}, + {0x1.603ffffffb99fp8, 0x1.23e648944393ap508}, + {0x1.613ffffffb99fp8, 0x1.8cbb8c9e43a63p509}, + {0x1.623ffffffb99fp8, 0x1.0d9b966e13d61p511}, + {0x1.633ffffffb99fp8, 0x1.6e6f586d0888dp512}, + {0x1.643ffffffb99fp8, 0x1.f20966b5813aep513}, + {0x1.653ffffffb99fp8, 0x1.5273779badaf2p515}, + {0x1.663ffffffb99fp8, 0x1.cc00ae664a89p516}, + {0x1.673ffffffb99fp8, 0x1.389aae1391554p518}, + {0x1.683ffffffb99fp8, 0x1.a8df88f5b2588p519}, + {0x1.693ffffffb99fp8, 0x1.20bb34172b66ap521}, + {0x1.6a3ffffffb99fp8, 0x1.886d2d5f07833p522}, + {0x1.6b3ffffffb99fp8, 0x1.0aae72b8de01ep524}, + {0x1.6c3ffffffb99fp8, 0x1.6a7528c7487fep525}, + {0x1.6d3ffffffb99fp8, 0x1.eca18af43a36cp526}, + {0x1.6e3ffffffb99fp8, 0x1.4ec709b53a35fp528}, + {0x1.6f3ffffffb99fp8, 0x1.c702815c30a11p529}, + {0x1.703ffffffb99fp8, 0x1.353611c2fab72p531}, + {0x1.713ffffffb99fp8, 0x1.a442f8858a925p532}, + {0x1.723ffffffb99fp8, 0x1.1d98ed4a7bba3p534}, + {0x1.733ffffffb99fp8, 0x1.842ac5348b7cep535}, + {0x1.743ffffffb99fp8, 0x1.07c97097fb529p537}, + {0x1.753ffffffb99fp8, 0x1.6686064a6be2ap538}, + {0x1.763ffffffb99fp8, 0x1.e748b46cfe14cp539}, + {0x1.773ffffffb99fp8, 0x1.4b24d0e9033c7p541}, + {0x1.783ffffffb99fp8, 0x1.c21233e5293dap542}, + {0x1.793ffffffb99fp8, 0x1.31dae2fdf0407p544}, + {0x1.7a3ffffffb99fp8, 0x1.9fb3386e7303dp545}, + {0x1.7b3ffffffb99fp8, 0x1.1a7f5bb80b183p547}, + {0x1.7c3ffffffb99fp8, 0x1.7ff432dfa67a9p548}, + {0x1.7d3ffffffb99fp8, 0x1.04ec79737cde7p550}, + {0x1.7e3ffffffb99fp8, 0x1.62a1d2414486ep551}, + {0x1.7f3ffffffb99fp8, 0x1.e1feb963592a3p552}, + {0x1.803ffffffb99fp8, 0x1.478cb0da3248p554}, + {0x1.813ffffffb99fp8, 0x1.bd2f9f74b3ecep555}, + {0x1.823ffffffb99fp8, 0x1.2e8907921a545p557}, + {0x1.833ffffffb99fp8, 0x1.9b3025158e763p558}, + {0x1.843ffffffb99fp8, 0x1.176e672da841p560}, + {0x1.853ffffffb99fp8, 0x1.7bc9557d90bb5p561}, + {0x1.863ffffffb99fp8, 0x1.021776f23b20ap563}, + {0x1.873ffffffb99fp8, 0x1.5ec86e4bf78ccp564}, + {0x1.883ffffffb99fp8, 0x1.dcc3708ecfe88p565}, + {0x1.893ffffffb99fp8, 0x1.43fe8d7ac0079p567}, + {0x1.8a3ffffffb99fp8, 0x1.b85a9de96d206p568}, + {0x1.8b3ffffffb99fp8, 0x1.2b406595ebc2fp570}, + {0x1.8c3ffffffb99fp8, 0x1.96b99b42ee81ep571}, + {0x1.8d3ffffffb99fp8, 0x1.1465f7bc5d4f3p573}, + {0x1.8e3ffffffb99fp8, 0x1.77aa0c86e3254p574}, + {0x1.8f3ffffffb99fp8, 0x1.fe94a5f24f127p575}, + {0x1.903ffffffb99fp8, 0x1.5af9bc5f10484p577}, + {0x1.913ffffffb99fp8, 0x1.d796b1199ca0dp578}, + {0x1.923ffffffb99fp8, 0x1.407a4b0a99581p580}, + {0x1.933ffffffb99fp8, 0x1.b393098be48c6p581}, + {0x1.943ffffffb99fp8, 0x1.2800e367d7873p583}, + {0x1.953ffffffb99fp8, 0x1.924f782080a9p584}, + {0x1.963ffffffb99fp8, 0x1.1165f5b7b4e77p586}, + {0x1.973ffffffb99fp8, 0x1.739637ce995dep587}, + {0x1.983ffffffb99fp8, 0x1.f909ef553fe1dp588}, + {0x1.993ffffffb99fp8, 0x1.57359ec295bd8p590}, + {0x1.9a3ffffffb99fp8, 0x1.d278529f70c72p591}, + {0x1.9b3ffffffb99fp8, 0x1.3cffce16c6a9fp593}, + {0x1.9c3ffffffb99fp8, 0x1.aed8bd0d76c2ep594}, + {0x1.9d3ffffffb99fp8, 0x1.24ca67ad88b68p596}, + {0x1.9e3ffffffb99fp8, 0x1.8df19938fe6d4p597}, + {0x1.9f3ffffffb99fp8, 0x1.0e6e49b5016fbp599}, + {0x1.a03ffffffb99fp8, 0x1.6f8db78116a48p600}, + {0x1.a13ffffffb99fp8, 0x1.f38e9ecb87da4p601}, + {0x1.a23ffffffb99fp8, 0x1.537bf81122a93p603}, + {0x1.a33ffffffb99fp8, 0x1.cd682d2c39ab4p604}, + {0x1.a43ffffffb99fp8, 0x1.398efb7895c02p606}, + {0x1.a53ffffffb99fp8, 0x1.aa2b938729ffap607}, + {0x1.a63ffffffb99fp8, 0x1.219cd9531c9cep609}, + {0x1.a73ffffffb99fp8, 0x1.899fdc76e059bp610}, + {0x1.a83ffffffb99fp8, 0x1.0b7edc8aa647ep612}, + {0x1.a93ffffffb99fp8, 0x1.6b906c232d65ep613}, + {0x1.aa3ffffffb99fp8, 0x1.ee22898b97fbep614}, + {0x1.ab3ffffffb99fp8, 0x1.4fccab37000cep616}, + {0x1.ac3ffffffb99fp8, 0x1.c866193ae89dbp617}, + {0x1.ad3ffffffb99fp8, 0x1.3627b854c5c27p619}, + {0x1.ae3ffffffb99fp8, 0x1.a58b68788e1e6p620}, + {0x1.af3ffffffb99fp8, 0x1.1e781f8a5efe5p622}, + {0x1.b03ffffffb99fp8, 0x1.855a202353f77p623}, + {0x1.b13ffffffb99fp8, 0x1.0897974f62fe1p625}, + {0x1.b23ffffffb99fp8, 0x1.679e369129826p626}, + {0x1.b33ffffffb99fp8, 0x1.e8c58542c521dp627}, + {0x1.b43ffffffb99fp8, 0x1.4c279b7142392p629}, + {0x1.b53ffffffb99fp8, 0x1.c371efb43e76ep630}, + {0x1.b63ffffffb99fp8, 0x1.32c9ea1ab59ccp632}, + {0x1.b73ffffffb99fp8, 0x1.a0f817c69fb0ap633}, + {0x1.b83ffffffb99fp8, 0x1.1b5c21ca08788p635}, + {0x1.b93ffffffb99fp8, 0x1.812042e534a64p636}, + {0x1.ba3ffffffb99fp8, 0x1.05b86359a079cp638}, + {0x1.bb3ffffffb99fp8, 0x1.63b6f7fddd3efp639}, + {0x1.bc3ffffffb99fp8, 0x1.e3776813fda8ep640}, + {0x1.bd3ffffffb99fp8, 0x1.488cac4ce84e7p642}, + {0x1.be3ffffffb99fp8, 0x1.be8b89ed9a77dp643}, + {0x1.bf3ffffffb99fp8, 0x1.2f75768394a5p645}, + {0x1.c03ffffffb99fp8, 0x1.9c717dbaae2b8p646}, + {0x1.c13ffffffb99fp8, 0x1.1848c7ccfefe3p648}, + {0x1.c23ffffffb99fp8, 0x1.7cf223c0074fbp649}, + {0x1.c33ffffffb99fp8, 0x1.02e12a3ec0173p651}, + {0x1.c43ffffffb99fp8, 0x1.5fda91f1b0d98p652}, + {0x1.c53ffffffb99fp8, 0x1.de38089682abp653}, + {0x1.c63ffffffb99fp8, 0x1.44fbc1a5fe2ddp655}, + {0x1.c73ffffffb99fp8, 0x1.b9b2c1a7cc7aap656}, + {0x1.c83ffffffb99fp8, 0x1.2c2a43919580dp658}, + {0x1.c93ffffffb99fp8, 0x1.97f7770145248p659}, + {0x1.ca3ffffffb99fp8, 0x1.153df9919867p661}, + {0x1.cb3ffffffb99fp8, 0x1.78cfa212f8edcp662}, + {0x1.cc3ffffffb99fp8, 0x1.0011d5d26caedp664}, + {0x1.cd3ffffffb99fp8, 0x1.5c08e649b4b94p665}, + {0x1.ce3ffffffb99fp8, 0x1.d9073dd4a4c7bp666}, + {0x1.cf3ffffffb99fp8, 0x1.4174bfa6c0d24p668}, + {0x1.d03ffffffb99fp8, 0x1.b4e7710dea691p669}, + {0x1.d13ffffffb99fp8, 0x1.28e8378f2345ap671}, + {0x1.d23ffffffb99fp8, 0x1.9389e0a91894fp672}, + {0x1.d33ffffffb99fp8, 0x1.123b9f58df0dap674}, + {0x1.d43ffffffb99fp8, 0x1.74b89d97dfdd3p675}, + {0x1.d53ffffffb99fp8, 0x1.fa94a04bdb05cp676}, + {0x1.d63ffffffb99fp8, 0x1.5841d736b633cp678}, + {0x1.d73ffffffb99fp8, 0x1.d3e4df4a846ddp679}, + {0x1.d83ffffffb99fp8, 0x1.3df78ac6c50cep681}, + {0x1.d93ffffffb99fp8, 0x1.b02972b428f19p682}, + {0x1.da3ffffffb99fp8, 0x1.25af390e18cbep684}, + {0x1.db3ffffffb99fp8, 0x1.8f289821f41b9p685}, + {0x1.dc3ffffffb99fp8, 0x1.0f41a1a5d8764p687}, + {0x1.dd3ffffffb99fp8, 0x1.70acf6623ff32p688}, + {0x1.de3ffffffb99fp8, 0x1.f515070ef61acp689}, + {0x1.df3ffffffb99fp8, 0x1.5485473c56dfcp691}, + {0x1.e03ffffffb99fp8, 0x1.ced0c4e4d59e4p692}, + {0x1.e13ffffffb99fp8, 0x1.3a8407ca209c6p694}, + {0x1.e23ffffffb99fp8, 0x1.ab78a196b76fdp695}, + {0x1.e33ffffffb99fp8, 0x1.227f2ee6fa305p697}, + {0x1.e43ffffffb99fp8, 0x1.8ad37b3bad33ep698}, + {0x1.e53ffffffb99fp8, 0x1.0c4fe93ccdf88p700}, + {0x1.e63ffffffb99fp8, 0x1.6cac8cde514efp701}, + {0x1.e73ffffffb99fp8, 0x1.efa4b5032b54fp702}, + {0x1.e83ffffffb99fp8, 0x1.50d31930266e8p704}, + {0x1.e93ffffffb99fp8, 0x1.c9cac6ffa71cbp705}, + {0x1.ea3ffffffb99fp8, 0x1.371a1bc09599dp707}, + {0x1.eb3ffffffb99fp8, 0x1.a6d4d9189f018p708}, + {0x1.ec3ffffffb99fp8, 0x1.1f580038307ccp710}, + {0x1.ed3ffffffb99fp8, 0x1.868a6825185b7p711}, + {0x1.ee3ffffffb99fp8, 0x1.09665f229766bp713}, + {0x1.ef3ffffffb99fp8, 0x1.68b741d009e02p714}, + {0x1.f03ffffffb99fp8, 0x1.ea437fb4bc319p715}, + {0x1.f13ffffffb99fp8, 0x1.4d2b3038bf046p717}, + {0x1.f23ffffffb99ep8, 0x1.c4d2be652cea4p718}, + {0x1.f33ffffffb99ep8, 0x1.33b9ac04c0212p720}, + {0x1.f43ffffffb99ep8, 0x1.a23df502a4a3ap721}, + {0x1.f53ffffffb99ep8, 0x1.1c39946547606p723}, + {0x1.f63ffffffb99ep8, 0x1.824d3d6b0103dp724}, + {0x1.f73ffffffb99ep8, 0x1.0684ec9be79c4p726}, + {0x1.f83ffffffb99ep8, 0x1.64ccf65229834p727}, + {0x1.f93ffffffb99ep8, 0x1.e4f13d25df78ap728}, + {0x1.fa3ffffffb99ep8, 0x1.498d6fcce3f5ep730}, + {0x1.fb3ffffffb99ep8, 0x1.bfe8844c8ea89p731}, + {0x1.fc3ffffffb99ep8, 0x1.30629e3b46a18p733}, + {0x1.fd3ffffffb99ep8, 0x1.9db3d1822eed1p734}, + {0x1.fe3ffffffb99ep8, 0x1.1923d3162d5cep736}, + {0x1.ff3ffffffb99ep8, 0x1.7e1bd9f724dbcp737}, + {0x1.001ffffffdccfp9, 0x1.03ab7b2c9b517p739}, + {0x1.009ffffffdccfp9, 0x1.60ed8bd54933ep740}, + {0x1.011ffffffdccfp9, 0x1.dfadc3cd79f32p741}, + {0x1.019ffffffdccfp9, 0x1.45f9bbb2a35d1p743}, + {0x1.021ffffffdccfp9, 0x1.bb0bf258b833ap744}, + {0x1.029ffffffdccfp9, 0x1.2d14d8520baf7p746}, + {0x1.031ffffffdccfp9, 0x1.99364b282dd34p747}, + {0x1.039ffffffdccfp9, 0x1.1616a4367556fp749}, + {0x1.041ffffffdccfp9, 0x1.79f61d0f30fbp750}, + {0x1.049ffffffdccfp9, 0x1.00d9f49709365p752}, + {0x1.051ffffffdccfp9, 0x1.5d18e41eebfc4p753}, + {0x1.059ffffffdccfp9, 0x1.da78ea95d97f9p754}, + {0x1.061ffffffdccfp9, 0x1.426ff7fe794b6p756}, + {0x1.069ffffffdccfp9, 0x1.b63ce2972ea1ep757}, + {0x1.071ffffffdccfp9, 0x1.29d0407f62d33p759}, + {0x1.079ffffffdccfp9, 0x1.94c53ee806803p760}, + {0x1.081ffffffdccfp9, 0x1.1311eff49ae9ap762}, + {0x1.089ffffffdccfp9, 0x1.75dbe653c2ceap763}, + {0x1.091ffffffdccfp9, 0x1.fc2085b6a9375p764}, + {0x1.099ffffffdccfp9, 0x1.594ee148935c8p766}, + {0x1.0a1ffffffdccfp9, 0x1.d55288db74dc3p767}, + {0x1.0a9ffffffdccfp9, 0x1.3ef00912762eap769}, + {0x1.0b1ffffffdccfp9, 0x1.b17b2f7ee7f4ep770}, + {0x1.0b9ffffffdccfp9, 0x1.2694bd41472c4p772}, + {0x1.0c1ffffffdccfp9, 0x1.90608a1681a3ep773}, + {0x1.0c9ffffffdccfp9, 0x1.10159ec1486a4p775}, + {0x1.0d1ffffffdccfp9, 0x1.71cd15bf6b516p776}, + {0x1.0d9ffffffdccfp9, 0x1.f69ca06d83551p777}, + {0x1.0e1ffffffdccfp9, 0x1.558f65bed5d1ap779}, + {0x1.0e9ffffffdccfp9, 0x1.d03a766bae541p780}, + {0x1.0f1ffffffdccfp9, 0x1.3b79d39d672c6p782}, + {0x1.0f9ffffffdccfp9, 0x1.acc6b3ef261e7p783}, + {0x1.101ffffffdccfp9, 0x1.2362355c94574p785}, + {0x1.109ffffffdccfp9, 0x1.8c080a68bcd97p786}, + {0x1.111ffffffdccfp9, 0x1.0d21994e9f02ap788}, + {0x1.119ffffffdccfp9, 0x1.6dc98ba5b51bp789}, + {0x1.121ffffffdccfp9, 0x1.f1280e4617147p790}, + {0x1.129ffffffdccfp9, 0x1.51da544077fa2p792}, + {0x1.131ffffffdccfp9, 0x1.cb308b8399fb7p793}, + {0x1.139ffffffdccfp9, 0x1.380d3c9a00e7ep795}, + {0x1.141ffffffdccfp9, 0x1.a81f4b2e55334p796}, + {0x1.149ffffffdccfp9, 0x1.20388fdc417d5p798}, + {0x1.151ffffffdccfp9, 0x1.87bb9df31efbp799}, + {0x1.159ffffffdccfp9, 0x1.0a35c88f80cbp801}, + {0x1.161ffffffdccfp9, 0x1.69d128b22d25ap802}, + {0x1.169ffffffdccfp9, 0x1.ebc2a4ab78bb5p803}, + {0x1.171ffffffdccfp9, 0x1.4e2f8fdd883d6p805}, + {0x1.179ffffffdccfp9, 0x1.c634a0cec7546p806}, + {0x1.181ffffffdccfp9, 0x1.34aa294e0c99ep808}, + {0x1.189ffffffdccfp9, 0x1.a384d0e8ecc3p809}, + {0x1.191ffffffdccfp9, 0x1.1d17b4109e865p811}, + {0x1.199ffffffdccfp9, 0x1.837b23284f5e9p812}, + {0x1.1a1ffffffdccfp9, 0x1.075215b6dcdc8p814}, + {0x1.1a9ffffffdccfp9, 0x1.65e3cde76e421p815}, + {0x1.1b1ffffffdccfp9, 0x1.e66c397f0e285p816}, + {0x1.1b9ffffffdccfp9, 0x1.4a8efbf67ceccp818}, + {0x1.1c1ffffffdccfp9, 0x1.c1468f660e51bp819}, + {0x1.1c9ffffffdccfp9, 0x1.31507f4997713p821}, + {0x1.1d1ffffffdccfp9, 0x1.9ef72130544cep822}, + {0x1.1d9ffffffdccfp9, 0x1.19ff898e9368dp824}, + {0x1.1e1ffffffdccfp9, 0x1.7f4678d82ff18p825}, + {0x1.1e9ffffffdccfp9, 0x1.04766a36fd582p827}, + {0x1.1f1ffffffdccfp9, 0x1.62015c9e2f34p828}, + {0x1.1f9ffffffdccfp9, 0x1.e124a317460fp829}, + {0x1.201ffffffdccfp9, 0x1.46f87c3b54d8ep831}, + {0x1.209ffffffdccfp9, 0x1.bc6630ce5faecp832}, + {0x1.211ffffffdccfp9, 0x1.2e00246624382p834}, + {0x1.219ffffffdccfp9, 0x1.9a761879cac82p835}, + {0x1.221ffffffdccfp9, 0x1.16eff82ee1911p837}, + {0x1.229ffffffdccfp9, 0x1.7b1d7e2eda2c6p838}, + {0x1.231ffffffdccfp9, 0x1.01a2afc0d75c2p840}, + {0x1.239ffffffdccfp9, 0x1.5e29b684536ep841}, + {0x1.241ffffffdccfp9, 0x1.dbebb83e52c5dp842}, + {0x1.249ffffffdccfp9, 0x1.436bf4aaba53p844}, + {0x1.251ffffffdccfp9, 0x1.b7935ef798935p845}, + {0x1.259ffffffdccfp9, 0x1.2ab8fec5df362p847}, + {0x1.261ffffffdccfp9, 0x1.9601939d5137dp848}, + {0x1.269ffffffdccfp9, 0x1.13e8e80d6759dp850}, + {0x1.271ffffffdccfp9, 0x1.770012b39ed67p851}, + {0x1.279ffffffdccfp9, 0x1.fdada086b9c52p852}, + {0x1.281ffffffdccfp9, 0x1.5a5cbd9bfe665p854}, + {0x1.289ffffffdccfp9, 0x1.d6c15030e89c1p855}, + {0x1.291ffffffdccfp9, 0x1.3fe9499128953p857}, + {0x1.299ffffffdccfp9, 0x1.b2cdf43b59797p858}, + {0x1.2a1ffffffdccfp9, 0x1.277af4d2d449ap860}, + {0x1.2a9ffffffdccfp9, 0x1.91996fd498417p861}, + {0x1.2b1ffffffdccfp9, 0x1.10ea41886590dp863}, + {0x1.2b9ffffffdccfp9, 0x1.72ee16480890ep864}, + {0x1.2c1ffffffdccfp9, 0x1.f8256bd5a1072p865}, + {0x1.2c9ffffffdccfp9, 0x1.569a543aa97d8p867}, + {0x1.2d1ffffffdccfp9, 0x1.d1a5429cffadp868}, + {0x1.2d9ffffffdccfp9, 0x1.3c705f8813894p870}, + {0x1.2e1ffffffdccfp9, 0x1.ae15cb5be04dap871}, + {0x1.2e9ffffffdccfp9, 0x1.2445ed3e27324p873}, + {0x1.2f1ffffffdccfp9, 0x1.8d3d8ab9f0bdep874}, + {0x1.2f9ffffffdccfp9, 0x1.0df3ed3fc701dp876}, + {0x1.301ffffffdccfp9, 0x1.6ee76926e122bp877}, + {0x1.309ffffffdccfp9, 0x1.f2ac9640362cap878}, + {0x1.311ffffffdccfp9, 0x1.52e25d083c6f6p880}, + {0x1.319ffffffdccfp9, 0x1.cc9767a099276p881}, + {0x1.321ffffffdccfp9, 0x1.39011b7511e91p883}, + {0x1.329ffffffdccfp9, 0x1.a96abf82e5bedp884}, + {0x1.331ffffffdccfp9, 0x1.2119ceff4e062p886}, + {0x1.339ffffffdccfp9, 0x1.88edc2473f3cfp887}, + {0x1.341ffffffdccfp9, 0x1.0b05d4146a019p889}, + {0x1.349ffffffdccfp9, 0x1.6aebebe3397ccp890}, + {0x1.351ffffffdccfp9, 0x1.ed42f5104656ep891}, + {0x1.359ffffffdccfp9, 0x1.4f34bafe2847bp893}, + {0x1.361ffffffdccfp9, 0x1.c79797c887ff8p894}, + {0x1.369ffffffdccfp9, 0x1.359b628909b0ap896}, + {0x1.371ffffffdccfp9, 0x1.a4ccac407db6ep897}, + {0x1.379ffffffdccfp9, 0x1.1df681534dcc2p899}, + {0x1.381ffffffdccfp9, 0x1.84a9f4d4f272ap900}, + {0x1.389ffffffdccfp9, 0x1.081fdf276bf44p902}, + {0x1.391ffffffdccfp9, 0x1.66fb7f67746f6p903}, + {0x1.399ffffffdccfp9, 0x1.e7e85e064cb73p904}, + {0x1.3a1ffffffdccfp9, 0x1.4b91516684d28p906}, + {0x1.3a9ffffffdccfp9, 0x1.c2a5ac0f3d022p907}, + {0x1.3b1ffffffdccfp9, 0x1.323f1a3f5edc4p909}, + {0x1.3b9ffffffdccfp9, 0x1.a03b6d89faf11p910}, + {0x1.3c1ffffffdccfp9, 0x1.1adbebbbf9351p912}, + {0x1.3c9ffffffdccfp9, 0x1.80720118fc863p913}, + {0x1.3d1ffffffdccfp9, 0x1.0541f7d976c95p915}, + {0x1.3d9ffffffdccfp9, 0x1.631604f454091p916}, + {0x1.3e1ffffffdccfp9, 0x1.e29ca75828ca4p917}, + {0x1.3e9ffffffdccfp9, 0x1.47f803db3082ep919}, + {0x1.3f1ffffffdccfp9, 0x1.bdc17ddb963f2p920}, + {0x1.3f9ffffffdccfp9, 0x1.2eec285d246c2p922}, + {0x1.401ffffffdccfp9, 0x1.9bb6dfb8d5a7bp923}, + {0x1.409ffffffdccfp9, 0x1.17c9f5ff316ddp925}, + {0x1.411ffffffdccfp9, 0x1.7c45c625cf3bcp926}, + {0x1.419ffffffdccfp9, 0x1.026c07ca1067p928}, + {0x1.421ffffffdccfp9, 0x1.5f3b5e200997dp929}, + {0x1.429ffffffdccfp9, 0x1.dd5fa7afd8289p930}, + {0x1.431ffffffdccfp9, 0x1.4468b644f2c7fp932}, + {0x1.439ffffffdccfp9, 0x1.b8eae6ffb1c26p933}, + {0x1.441ffffffdccfp9, 0x1.2ba272f04fa72p935}, + {0x1.449ffffffdccfp9, 0x1.973edf89954efp936}, + {0x1.451ffffffdccfp9, 0x1.14c088262904bp938}, + {0x1.459ffffffdccfp9, 0x1.782523695aef2p939}, + {0x1.461ffffffdccfp9, 0x1.ff3bf1add8023p940}, + {0x1.469ffffffdccfp9, 0x1.5b6b6cd54844dp942}, + {0x1.471ffffffdccfp9, 0x1.d831362a33e02p943}, + {0x1.479ffffffdccfp9, 0x1.40e34cdaa0c9dp945}, + {0x1.481ffffffdccfp9, 0x1.b421c1b7c391cp946}, + {0x1.489ffffffdccfp9, 0x1.2861e04eed965p948}, + {0x1.491ffffffdccfp9, 0x1.92d34a1abd55p949}, + {0x1.499ffffffdccfp9, 0x1.11bf8a7ca8dc9p951}, + {0x1.4a1ffffffdccfp9, 0x1.740ff8ac10594p952}, + {0x1.4a9ffffffdccfp9, 0x1.f9af6a367aa8cp953}, + {0x1.4b1ffffffdccfp9, 0x1.57a613525a444p955}, + {0x1.4b9ffffffdccfp9, 0x1.d3112a55b14f7p956}, + {0x1.4c1ffffffdccfp9, 0x1.3d67ac204487bp958}, + {0x1.4c9ffffffdccfp9, 0x1.af65e8a8eee76p959}, + {0x1.4d1ffffffdccfp9, 0x1.252a57165ab35p961}, + {0x1.4d9ffffffdccfp9, 0x1.8e73fcebbcdf2p962}, + {0x1.4e1ffffffdccfp9, 0x1.0ec6e5905727p964}, + {0x1.4e9ffffffdccfp9, 0x1.7006260fe518p965}, + {0x1.4f1ffffffdccfp9, 0x1.f4324dde1b853p966}, + {0x1.4f9ffffffdccfp9, 0x1.53eb342838912p968}, + {0x1.501ffffffdccfp9, 0x1.cdff5c312677p969}, + {0x1.509ffffffdccfp9, 0x1.39f5b8e646512p971}, + {0x1.511ffffffdccfp9, 0x1.aab736e0229e8p972}, + {0x1.519ffffffdccfp9, 0x1.21fbbe2a7cc33p974}, + {0x1.521ffffffdccfp9, 0x1.8a20d5dbe17b1p975}, + {0x1.529ffffffdccfp9, 0x1.0bd6823000616p977}, + {0x1.531ffffffdccfp9, 0x1.6c078c0f5af0cp978}, + {0x1.539ffffffdccfp9, 0x1.eec471cd26923p979}, + {0x1.541ffffffdccfp9, 0x1.503ab239a52eep981}, + {0x1.549ffffffdccfp9, 0x1.c8fba42a91b8p982}, + {0x1.551ffffffdccfp9, 0x1.368d584898928p984}, + {0x1.559ffffffdccfp9, 0x1.a61587d0f8cb4p985}, + {0x1.561ffffffdccfp9, 0x1.1ed5fcb4fed8p987}, + {0x1.569ffffffdccfp9, 0x1.85d9b3294cbccp988}, + {0x1.571ffffffdccfp9, 0x1.08ee496ae24e1p990}, + {0x1.579ffffffdccfp9, 0x1.68140b7c89c5cp991}, + {0x1.581ffffffdccfp9, 0x1.e965aba3129a2p992}, + {0x1.589ffffffdccfp9, 0x1.4c9470ba47e91p994}, + {0x1.591ffffffdccfp9, 0x1.c405db1de4f69p995}, + {0x1.599ffffffdccfp9, 0x1.332e6fade5fp997}, + {0x1.5a1ffffffdccfp9, 0x1.a180b7549973p998}, + {0x1.5a9ffffffdccfp9, 0x1.1bb8fa248f731p1000}, + {0x1.5b1ffffffdccfp9, 0x1.819e736fecc0ap1001}, + {0x1.5b9ffffffdccfp9, 0x1.060e248ff8e45p1003}, + {0x1.5c1ffffffdccfp9, 0x1.642b85802c37dp1004}, + {0x1.5c9ffffffdccfp9, 0x1.e415d17516714p1005}, + {0x1.5d1ffffffdccfp9, 0x1.48f8532dcd8aap1007}, + {0x1.5d9ffffffdccfp9, 0x1.bf1dda53d4168p1008}, + {0x1.5e1ffffffdccfp9, 0x1.2fd8e4c6c1a74p1010}, + {0x1.5e9ffffffdccfp9, 0x1.9cf8a1a8a05e1p1011}, + {0x1.5f1ffffffdccfp9, 0x1.18a49e2c20c14p1013}, + {0x1.5f9ffffffdccfp9, 0x1.7d6ef5a877896p1014}, + {0x1.601ffffffdccfp9, 0x1.0335fd2d4d32ap1016}, + {0x1.609ffffffdccfp9, 0x1.604ddb98aeeb6p1017}, + {0x1.611ffffffdccfp9, 0x1.ded4b9cce1c65p1018}, + {0x1.619ffffffdccep9, 0x1.45663d67095d1p1020}, + {0x1.621ffffffdccep9, 0x1.ba437b80a6915p1021}, + {0x1.629ffffffdccep9, 0x1.2c8c9d8cda0c8p1023}, + }; + + for (double[] testCase: testCases) + failures+=testExpm1Case(testCase[0], testCase[1]); + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testExpm1(); + + if (failures > 0) { + System.err.println("Testing expm1 incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/HyperbolicTests.java b/jdk/test/java/lang/StrictMath/HyperbolicTests.java new file mode 100644 index 00000000000..7cb135abf86 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/HyperbolicTests.java @@ -0,0 +1,280 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851625 + * @summary Tests for StrictMath.{sinh, cosh, tanh} + * @author Joseph D. Darcy + */ + +/** + * The tests in ../Math/HyperbolicTests.java test properties that + * should hold for any implementation of the hyperbolic functions + * sinh, cos, and tanh, including the FDLIBM-based ones required by + * the StrictMath class. Therefore, the test cases in + * ../Math/HyperbolicTests.java are run against both the Math and + * StrictMath versions of the hyperbolic methods. The role of this + * test is to verify that the FDLIBM algorithms are being used by + * running golden file tests on values that may vary from one + * conforming implementation of the hyperbolics to another. + */ + +public class HyperbolicTests { + private HyperbolicTests(){} + + static int testSinhCase(double input, double expected) { + return Tests.test("StrictMath.sinh(double)", input, + StrictMath.sinh(input), expected); + } + + static int testCoshCase(double input, double expected) { + return Tests.test("StrictMath.cosh(double)", input, + StrictMath.cosh(input), expected); + } + + static int testTanhCase(double input, double expected) { + return Tests.test("StrictMath.tanh(double)", input, + StrictMath.tanh(input), expected); + } + + static int testSinh() { + int failures = 0; + double [][] testCases = { + {0x1.5798ee2308c3ap-27, 0x1.5798ee2308c3bp-27}, + {0x1.ffffffffffff8p-26, 0x1.ffffffffffffap-26}, + {0x1.ffffffffffffep-26, 0x1.0p-25}, + {0x1.ffffffffffff8p-25, 0x1.ffffffffffffep-25}, + {0x1.ffffffffffffap-25, 0x1.0p-24}, + {0x1.ad7f29abcaf47p-24, 0x1.ad7f29abcaf53p-24}, + {0x1.ad7f29abcaf48p-24, 0x1.ad7f29abcaf54p-24}, + {0x1.fffffffffffeap-24, 0x1.0p-23}, + {0x1.ffffffffffff8p-24, 0x1.0000000000007p-23}, + {0x1.fffffffffffaap-23, 0x1.0p-22}, + {0x1.ffffffffffff8p-23, 0x1.0000000000027p-22}, + {0x1.ffffffffffeaap-22, 0x1.0p-21}, + {0x1.ffffffffffff8p-22, 0x1.00000000000a7p-21}, + {0x1.ffffffffffaaap-21, 0x1.0p-20}, + {0x1.ffffffffffff8p-21, 0x1.00000000002a7p-20}, + {0x1.0c6f7a0b5ed8cp-20, 0x1.0c6f7a0b5f09fp-20}, + {0x1.0c6f7a0b5ed8dp-20, 0x1.0c6f7a0b5f0ap-20}, + {0x1.fffffffffeaaap-20, 0x1.0p-19}, + {0x1.ffffffffffff8p-20, 0x1.0000000000aa7p-19}, + {0x1.ffffffffffff8p-19, 0x1.0000000002aa7p-18}, + {0x1.ffffffffffff7p-18, 0x1.000000000aaa6p-17}, + {0x1.4f8b588e368d9p-17, 0x1.4f8b588e4e928p-17}, + {0x1.ffffffffffffep-17, 0x1.000000002aaa9p-16}, + {0x1.0p-16, 0x1.000000002aaaap-16}, + {0x1.fffffffffffffp-16, 0x1.00000000aaaabp-15}, + {0x1.fffffffffeaaap-15, 0x1.00000002aap-14}, + {0x1.ffffffffffffep-15, 0x1.00000002aaaa9p-14}, + {0x1.0p-14, 0x1.00000002aaaaap-14}, + {0x1.a36e2eb1c3dd4p-14, 0x1.a36e2ebd7e43ap-14}, + {0x1.a36e2eb1c3f8cp-14, 0x1.a36e2ebd7e5f1p-14}, + {0x1.a36e2eb1c432cp-14, 0x1.a36e2ebd7e991p-14}, + {0x1.fffffffffffffp-14, 0x1.0000000aaaaabp-13}, + {0x1.ffffffffffffep-13, 0x1.0000002aaaaa9p-12}, + {0x1.0p-12, 0x1.0000002aaaaaap-12}, + {0x1.ffffffffff7f9p-12, 0x1.000000aaaa6a9p-11}, + {0x1.fffffffffffffp-12, 0x1.000000aaaaaadp-11}, + {0x1.ffffffffffffep-11, 0x1.000002aaaaacbp-10}, + {0x1.0p-10, 0x1.000002aaaaaccp-10}, + {0x1.0624dd2f1a79p-10, 0x1.0624e00c1c776p-10}, + {0x1.0624dd2f1a8c9p-10, 0x1.0624e00c1c8bp-10}, + {0x1.0624dd2f1a9fcp-10, 0x1.0624e00c1c9e3p-10}, + {0x1.ffffffffffffep-10, 0x1.00000aaaaaccbp-9}, + {0x1.0p-9, 0x1.00000aaaaacccp-9}, + {0x1.ffffffffffe4ap-9, 0x1.00002aaaacbf2p-8}, + {0x1.fffffffffffffp-9, 0x1.00002aaaacccdp-8}, + {0x1.fffffffffff9dp-8, 0x1.0000aaaaccc9bp-7}, + {0x1.ffffffffffffep-8, 0x1.0000aaaacccccp-7}, + {0x1.0p-7, 0x1.0000aaaaccccdp-7}, + {0x1.47ae147ae146fp-7, 0x1.47af7a654e9e2p-7}, + {0x1.47ae147ae147ap-7, 0x1.47af7a654e9eep-7}, + {0x1.47ae147ae147bp-7, 0x1.47af7a654e9efp-7}, + {0x1.fffffffffffb6p-7, 0x1.0002aaaccccb4p-6}, + {0x1.fffffffffffcap-7, 0x1.0002aaaccccbep-6}, + {0x1.ffffffffffff7p-7, 0x1.0002aaaccccd5p-6}, + {0x1.fffffffffffe9p-6, 0x1.000aaacccd001p-5}, + {0x1.ffffffffffff7p-6, 0x1.000aaacccd008p-5}, + {0x1.fffffffffffffp-6, 0x1.000aaacccd00dp-5}, + {0x1.ffffffffffff6p-5, 0x1.002aacccd9cd7p-4}, + {0x1.ffffffffffff8p-5, 0x1.002aacccd9cd9p-4}, + {0x1.0p-4, 0x1.002aacccd9cddp-4}, + {0x1.9999999999995p-4, 0x1.9a487337b59afp-4}, + {0x1.9999999999996p-4, 0x1.9a487337b59afp-4}, + {0x1.9999999999998p-4, 0x1.9a487337b59b1p-4}, + {0x1.ffffffffffffap-4, 0x1.00aaccd00d2edp-3}, + {0x1.ffffffffffffcp-4, 0x1.00aaccd00d2efp-3}, + {0x1.ffffffffffff3p-3, 0x1.02accd9d080fbp-2}, + {0x1.ffffffffffffdp-3, 0x1.02accd9d08101p-2}, + {0x1.fffffffffffffp-3, 0x1.02accd9d08101p-2}, + {0x1.fffffffffffecp-2, 0x1.0acd00fe63b8cp-1}, + {0x1.ffffffffffffcp-2, 0x1.0acd00fe63b94p-1}, + {0x1.0p-1, 0x1.0acd00fe63b97p-1}, + {0x1.ffffffffffff6p-1, 0x1.2cd9fc44eb97ap0}, + {0x1.ffffffffffffep-1, 0x1.2cd9fc44eb981p0}, + {0x1.fffffffffffffp0, 0x1.d03cf63b6e19ep1}, + {0x1.0p1, 0x1.d03cf63b6e1ap1}, + {0x1.fffffffffffffp1, 0x1.b4a380370362dp4}, + {0x1.0p2, 0x1.b4a380370363p4}, + {0x1.ffffffffffffcp2, 0x1.749ea514eca4ep10}, + {0x1.0p3, 0x1.749ea514eca66p10}, + {0x1.fffffffffffffp3, 0x1.0f2ebd0a7ffdcp22}, + {0x1.0p4, 0x1.0f2ebd0a7ffe4p22}, + {0x1.fffffffffff68p4, 0x1.1f43fcc4b5b83p45}, + {0x1.fffffffffffd4p4, 0x1.1f43fcc4b6316p45}, + {0x1.0p5, 0x1.1f43fcc4b662cp45}, + }; + + for (double[] testCase: testCases) + failures+=testSinhCase(testCase[0], testCase[1]); + + return failures; + } + + static int testCosh() { + int failures = 0; + double [][] testCases = { + {0x1.fffffffffb49fp-8, 0x1.00020000aaaabp0}, + {0x1.47ae147ae0e45p-7, 0x1.000346de27853p0}, + {0x1.fffffffffd9f3p-7, 0x1.0008000aaab05p0}, + {0x1.ffffffffff9f1p-7, 0x1.0008000aaab05p0}, + {0x1.fffffffffe27dp-6, 0x1.002000aaac169p0}, + {0x1.ffffffffff27bp-6, 0x1.002000aaac16bp0}, + {0x1.ffffffffffb9cp-5, 0x1.00800aab05b1ep0}, + {0x1.ffffffffffd9dp-5, 0x1.00800aab05b1fp0}, + {0x1.9999999999368p-4, 0x1.0147f40224b2ep0}, + {0x1.9999999999727p-4, 0x1.0147f40224b35p0}, + {0x1.ffffffffffed1p-4, 0x1.0200aac16db6cp0}, + {0x1.fffffffffffd1p-4, 0x1.0200aac16db6ep0}, + {0x1.ffffffffffeb4p-3, 0x1.080ab05ca613bp0}, + {0x1.ffffffffffff2p-3, 0x1.080ab05ca6146p0}, + {0x1.ffffffffffff3p-2, 0x1.20ac1862ae8cep0}, + {0x1.ffffffffffff9p-2, 0x1.20ac1862ae8dp0}, + {0x1.0p0, 0x1.8b07551d9f551p0}, + {0x1.ffffffffffffbp0, 0x1.e18fa0df2d9b3p1}, + {0x1.ffffffffffffep0, 0x1.e18fa0df2d9b8p1}, + {0x1.fffffffffffffp0, 0x1.e18fa0df2d9bap1}, + {0x1.ffffffffffff9p1, 0x1.b4ee858de3e68p4}, + {0x1.ffffffffffffep1, 0x1.b4ee858de3e7ap4}, + {0x1.fffffffffffffp1, 0x1.b4ee858de3e7dp4}, + {0x1.ffffffffffffcp2, 0x1.749eaa93f4e5ep10}, + {0x1.ffffffffffffdp2, 0x1.749eaa93f4e64p10}, + {0x1.0p3, 0x1.749eaa93f4e76p10}, + {0x1.fffffffffff6fp3, 0x1.0f2ebd0a7fb9p22}, + {0x1.0p4, 0x1.0f2ebd0a8005cp22}, + {0x1.fffffffffffd4p4, 0x1.1f43fcc4b6316p45}, + {0x1.0p5, 0x1.1f43fcc4b662cp45}, + }; + + for (double[] testCase: testCases) + failures+=testCoshCase(testCase[0], testCase[1]); + + return failures; + } + + static int testTanh() { + int failures = 0; + double [][] testCases = { + {0x1.5798ee2308c36p-27, 0x1.5798ee2308c36p-27}, + {0x1.ffffffffffffep-26, 0x1.ffffffffffffbp-26}, + {0x1.ffffffffffffep-25, 0x1.ffffffffffff3p-25}, + {0x1.ad7f29abcaf47p-24, 0x1.ad7f29abcaf2dp-24}, + {0x1.ad7f29abcaf48p-24, 0x1.ad7f29abcaf2ep-24}, + {0x1.ffffffffffffep-24, 0x1.fffffffffffd3p-24}, + {0x1.ffffffffffffep-23, 0x1.fffffffffff53p-23}, + {0x1.ffffffffffffep-22, 0x1.ffffffffffd53p-22}, + {0x1.ffffffffffffep-21, 0x1.ffffffffff553p-21}, + {0x1.0c6f7a0b5ed8dp-20, 0x1.0c6f7a0b5e767p-20}, + {0x1.ffffffffffffep-20, 0x1.fffffffffd553p-20}, + {0x1.ffffffffffffep-19, 0x1.fffffffff5553p-19}, + {0x1.fffffffffffffp-18, 0x1.ffffffffd5555p-18}, + {0x1.0p-17, 0x1.ffffffffd5556p-18}, + {0x1.4f8b588e368edp-17, 0x1.4f8b588e0685p-17}, + {0x1.fffffffffffffp-17, 0x1.ffffffff55554p-17}, + {0x1.fffffffffffffp-16, 0x1.fffffffd55555p-16}, + {0x1.0p-15, 0x1.fffffffd55556p-16}, + {0x1.fffffffffe5ddp-15, 0x1.fffffff553b33p-15}, + {0x1.fffffffffffffp-15, 0x1.fffffff555554p-15}, + {0x1.a36e2eb1c432dp-14, 0x1.a36e2e9a4f663p-14}, + {0x1.ffffffffffffep-14, 0x1.ffffffd555553p-14}, + {0x1.0p-13, 0x1.ffffffd555555p-14}, + {0x1.ffffffffffd51p-13, 0x1.ffffff55552aap-13}, + {0x1.fffffffffffffp-13, 0x1.ffffff5555559p-13}, + {0x1.ffffffffffffep-12, 0x1.fffffd5555597p-12}, + {0x1.0p-11, 0x1.fffffd5555599p-12}, + {0x1.fffffffffff1p-11, 0x1.fffff555558a9p-11}, + {0x1.0p-10, 0x1.fffff5555599ap-11}, + {0x1.0624dd2f1a9c6p-10, 0x1.0624d77516cabp-10}, + {0x1.0624dd2f1a9f8p-10, 0x1.0624d77516cdep-10}, + {0x1.fffffffffffddp-10, 0x1.ffffd55559976p-10}, + {0x1.fffffffffffffp-10, 0x1.ffffd55559999p-10}, + {0x1.ffffffffffffcp-9, 0x1.ffff555599993p-9}, + {0x1.ffffffffffffep-9, 0x1.ffff555599996p-9}, + {0x1.ffffffffffff8p-8, 0x1.fffd555999924p-8}, + {0x1.ffffffffffffep-8, 0x1.fffd555999929p-8}, + {0x1.47ae147ae1458p-7, 0x1.47ab48ae4593cp-7}, + {0x1.47ae147ae1464p-7, 0x1.47ab48ae45947p-7}, + {0x1.ffffffffffffep-7, 0x1.fff5559997df6p-7}, + {0x1.fffffffffffffp-7, 0x1.fff5559997df8p-7}, + {0x1.ffffffffffff9p-6, 0x1.ffd559992b1d8p-6}, + {0x1.ffffffffffffep-6, 0x1.ffd559992b1dcp-6}, + {0x1.ffffffffffff9p-5, 0x1.ff55997e030d1p-5}, + {0x1.fffffffffffffp-5, 0x1.ff55997e030d6p-5}, + {0x1.9999999999996p-4, 0x1.983d7795f4137p-4}, + {0x1.9999999999997p-4, 0x1.983d7795f4137p-4}, + {0x1.fffffffffffffp-4, 0x1.fd5992bc4b834p-4}, + {0x1.0p-3, 0x1.fd5992bc4b834p-4}, + {0x1.fffffffffffffp-3, 0x1.f597ea69a1c86p-3}, + {0x1.ffffffffffffcp-2, 0x1.d9353d7568aefp-2}, + {0x1.ffffffffffffep-2, 0x1.d9353d7568af3p-2}, + {0x1.ffffffffffffbp-1, 0x1.85efab514f393p-1}, + {0x1.ffffffffffffep-1, 0x1.85efab514f393p-1}, + {0x1.fffffffffffd3p0, 0x1.ed9505e1bc3cep-1}, + {0x1.fffffffffffe1p0, 0x1.ed9505e1bc3cfp-1}, + {0x1.ffffffffffed8p1, 0x1.ffa81708a0b4p-1}, + {0x1.fffffffffff92p1, 0x1.ffa81708a0b41p-1}, + }; + + for (double[] testCase: testCases) + failures+=testTanhCase(testCase[0], testCase[1]); + + return failures; + } + + + public static void main(String [] argv) { + int failures = 0; + + failures += testSinh(); + failures += testCosh(); + failures += testTanh(); + + if (failures > 0) { + System.err.println("Testing the hyperbolics incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/HypotTests.java b/jdk/test/java/lang/StrictMath/HypotTests.java new file mode 100644 index 00000000000..09c601a5185 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/HypotTests.java @@ -0,0 +1,633 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 + * @summary Tests for StrictMath.hypot + * @author Joseph D. Darcy + */ + +/** + * The tests in ../Math/HypotTests.java test properties that should + * hold for any hypot implementation, including the FDLIBM-based one + * required for StrictMath.hypot. Therefore, the test cases in + * ../Math/HypotTests.java are run against both the Math and + * StrictMath versions of hypot. The role of this test is to verify + * that the FDLIBM hypot algorithm is being used by running golden + * file tests on values that may vary from one conforming hypot + * implementation to another. + */ + +public class HypotTests { + private HypotTests(){} + + static int testHypotCase(double input1, double input2, double expected) { + return Tests.test("StrictMath.hypot(double)", input1, input2, + StrictMath.hypot(input1, input2), expected); + } + + static int testHypot() { + int failures = 0; + + double [][] testCases = { + {0x1.0p0, 0x1.ffffffffffab5p-1, 0x1.6a09e667f39edp0}, + {0x1.0p0, 0x1.ffffffffffffbp0, 0x1.1e3779b97f4a6p1}, + {0x1.0p0, 0x1.7ffffffffffffp1, 0x1.94c583ada5b51p1}, + {0x1.0p0, 0x1.ffffffffffffdp1, 0x1.07e0f66afed06p2}, + {0x1.0p0, 0x1.3fffffffffffdp2, 0x1.465655f122ff3p2}, + {0x1.0p0, 0x1.4p2, 0x1.465655f122ff6p2}, + {0x1.0p0, 0x1.7ffffffffffffp2, 0x1.854bfb363dc38p2}, + {0x1.0p0, 0x1.8p2, 0x1.854bfb363dc39p2}, + {0x1.0p0, 0x1.bfffffffffffep2, 0x1.c48c6001f0abdp2}, + {0x1.0p0, 0x1.fffffffffffffp2, 0x1.01fe03f61badp3}, + {0x1.0p0, 0x1.1fffffffffffap3, 0x1.21c5b70d9f81dp3}, + {0x1.0p0, 0x1.3ffffffffffe5p3, 0x1.419894c2329d5p3}, + {0x1.0p0, 0x1.3ffffffffffe7p3, 0x1.419894c2329d8p3}, + {0x1.0p0, 0x1.5ffffffffff7ep3, 0x1.617398f2aa9c6p3}, + {0x1.0p0, 0x1.5ffffffffff8dp3, 0x1.617398f2aa9d5p3}, + {0x1.0p0, 0x1.7ffffffffff9bp3, 0x1.8154be27734c1p3}, + {0x1.0p0, 0x1.8p3, 0x1.8154be2773526p3}, + {0x1.0p0, 0x1.9fffffffffff4p3, 0x1.a13a9cb996644p3}, + {0x1.0p0, 0x1.9ffffffffffffp3, 0x1.a13a9cb99664fp3}, + {0x1.0p0, 0x1.bfffffffffffep3, 0x1.c12432fec0327p3}, + {0x1.0p0, 0x1.cp3, 0x1.c12432fec0329p3}, + {0x1.0p0, 0x1.dffffffffffbcp3, 0x1.e110c39105f6bp3}, + {0x1.0p0, 0x1.ep3, 0x1.e110c39105fafp3}, + {0x1.0p0, 0x1.ffffffffffeafp3, 0x1.007fe00ff5fc8p4}, + {0x1.0p0, 0x1.0fffffffffff4p4, 0x1.10785dd689a1cp4}, + {0x1.0p0, 0x1.0fffffffffffbp4, 0x1.10785dd689a23p4}, + {0x1.0p0, 0x1.1ffffffffff92p4, 0x1.2071b0abcd7cap4}, + {0x1.0p0, 0x1.1ffffffffff99p4, 0x1.2071b0abcd7d1p4}, + {0x1.0p0, 0x1.2fffffffffffcp4, 0x1.306bb705ae7bfp4}, + {0x1.0p0, 0x1.2ffffffffffffp4, 0x1.306bb705ae7c3p4}, + {0x1.0p0, 0x1.3fffffffffffdp4, 0x1.4066560954a8bp4}, + {0x1.0p0, 0x1.4fffffffffe14p4, 0x1.506177f548fcfp4}, + {0x1.0p0, 0x1.5p4, 0x1.506177f5491bbp4}, + {0x1.0p0, 0x1.5fffffffffffdp4, 0x1.605d0af9d3a42p4}, + {0x1.0p0, 0x1.5fffffffffffep4, 0x1.605d0af9d3a42p4}, + {0x1.0p0, 0x1.6fffffffffff8p4, 0x1.7059005e2c015p4}, + {0x1.0p0, 0x1.6ffffffffffffp4, 0x1.7059005e2c01dp4}, + {0x1.0p0, 0x1.7fffffffffffdp4, 0x1.80554bdc2dc4dp4}, + {0x1.0p0, 0x1.7ffffffffffffp4, 0x1.80554bdc2dc4ep4}, + {0x1.0p0, 0x1.8fffffffffe68p4, 0x1.9051e3235a2cp4}, + {0x1.0p0, 0x1.9p4, 0x1.9051e3235a458p4}, + {0x1.0p0, 0x1.9fffffffffff4p4, 0x1.a04ebd789d00cp4}, + {0x1.0p0, 0x1.ap4, 0x1.a04ebd789d019p4}, + {0x1.0p0, 0x1.afffffffffed8p4, 0x1.b04bd36b639fbp4}, + {0x1.0p0, 0x1.affffffffff43p4, 0x1.b04bd36b63a66p4}, + {0x1.0p0, 0x1.bfffffffffe3ep4, 0x1.c0491e9ab90fdp4}, + {0x1.0p0, 0x1.cp4, 0x1.c0491e9ab92bfp4}, + {0x1.0p0, 0x1.cfffffffffed8p4, 0x1.d0469986884d6p4}, + {0x1.0p0, 0x1.cfffffffffee8p4, 0x1.d0469986884e5p4}, + {0x1.0p0, 0x1.dfffffffffe5cp4, 0x1.e0443f6a33104p4}, + {0x1.0p0, 0x1.dffffffffffffp4, 0x1.e0443f6a332a7p4}, + {0x1.0p0, 0x1.efffffffffff8p4, 0x1.f0420c1e63084p4}, + {0x1.0p0, 0x1.fp4, 0x1.f0420c1e6308dp4}, + {0x1.0p0, 0x1.ffffffffffffdp4, 0x1.001ffe003ff5fp5}, + {0x1.0p0, 0x1.07ffffffffed8p5, 0x1.081f05ef4d755p5}, + {0x1.0p0, 0x1.07ffffffffee8p5, 0x1.081f05ef4d764p5}, + {0x1.0p0, 0x1.0fffffffffff4p5, 0x1.101e1c7371c6bp5}, + {0x1.0p0, 0x1.0fffffffffffbp5, 0x1.101e1c7371c72p5}, + {0x1.0p0, 0x1.17ffffffffff8p5, 0x1.181d404cf7f51p5}, + {0x1.0p0, 0x1.17ffffffffffdp5, 0x1.181d404cf7f56p5}, + {0x1.0p0, 0x1.1fffffffffbf2p5, 0x1.201c705fa7a27p5}, + {0x1.0p0, 0x1.1fffffffffc65p5, 0x1.201c705fa7a9ap5}, + {0x1.0p0, 0x1.27ffffffffe08p5, 0x1.281babadfba01p5}, + {0x1.0p0, 0x1.28p5, 0x1.281babadfbbf9p5}, + {0x1.0p0, 0x1.2ffffffffff64p5, 0x1.301af15517357p5}, + {0x1.0p0, 0x1.2ffffffffff6cp5, 0x1.301af1551735ep5}, + {0x1.0p0, 0x1.37ffffffffc78p5, 0x1.381a40895d3f5p5}, + {0x1.0p0, 0x1.37ffffffffc88p5, 0x1.381a40895d406p5}, + {0x1.0p0, 0x1.3fffffffffffdp5, 0x1.4019989389b2dp5}, + {0x1.0p0, 0x1.4p5, 0x1.4019989389b3p5}, + {0x1.0p0, 0x1.47fffffffffe8p5, 0x1.4818f8ce34e19p5}, + {0x1.0p0, 0x1.47ffffffffffap5, 0x1.4818f8ce34e2cp5}, + {0x1.0p0, 0x1.4fffffffffa64p5, 0x1.501860a3b54bep5}, + {0x1.0p0, 0x1.4fffffffffe47p5, 0x1.501860a3b58a1p5}, + {0x1.0p0, 0x1.57ffffffffff8p5, 0x1.5817cf8c4c199p5}, + {0x1.0p0, 0x1.57fffffffffffp5, 0x1.5817cf8c4c1ap5}, + {0x1.0p0, 0x1.5fffffffffbeep5, 0x1.6017450c8d3e7p5}, + {0x1.0p0, 0x1.6p5, 0x1.6017450c8d7f9p5}, + {0x1.0p0, 0x1.67fffffffffe8p5, 0x1.6816c0b405afp5}, + {0x1.0p0, 0x1.68p5, 0x1.6816c0b405b09p5}, + {0x1.0p0, 0x1.6fffffffffb78p5, 0x1.7016421c06043p5}, + {0x1.0p0, 0x1.7p5, 0x1.7016421c064cbp5}, + {0x1.0p0, 0x1.77ffffffffffp5, 0x1.7815c8e69cc37p5}, + {0x1.0p0, 0x1.77ffffffffffcp5, 0x1.7815c8e69cc43p5}, + {0x1.0p0, 0x1.7ffffffffffffp5, 0x1.801554bda99c5p5}, + {0x1.0p0, 0x1.87fffffffffdp5, 0x1.8814e55214271p5}, + {0x1.0p0, 0x1.87ffffffffffcp5, 0x1.8814e5521429ep5}, + {0x1.0p0, 0x1.8ffffffffffe8p5, 0x1.90147a5b16ce5p5}, + {0x1.0p0, 0x1.8fffffffffffcp5, 0x1.90147a5b16cfap5}, + {0x1.0p0, 0x1.97ffffffffffp5, 0x1.98141395a0592p5}, + {0x1.0p0, 0x1.97fffffffffffp5, 0x1.98141395a05a1p5}, + {0x1.0p0, 0x1.9fffffffff8f4p5, 0x1.a013b0c3c7377p5}, + {0x1.0p0, 0x1.9fffffffffb18p5, 0x1.a013b0c3c759bp5}, + {0x1.0p0, 0x1.a7fffffffffdp5, 0x1.a81351ac4f317p5}, + {0x1.0p0, 0x1.a7ffffffffffp5, 0x1.a81351ac4f338p5}, + {0x1.0p0, 0x1.afffffffff698p5, 0x1.b012f61a35d98p5}, + {0x1.0p0, 0x1.bp5, 0x1.b012f61a367p5}, + {0x1.0p0, 0x1.b7ffffffff85p5, 0x1.b8129ddc56b26p5}, + {0x1.0p0, 0x1.b7ffffffff87p5, 0x1.b8129ddc56b45p5}, + {0x1.0p0, 0x1.bfffffffffffdp5, 0x1.c01248c50d99cp5}, + {0x1.0p0, 0x1.bfffffffffffep5, 0x1.c01248c50d99cp5}, + {0x1.0p0, 0x1.c7ffffffffedp5, 0x1.c811f6a9e9676p5}, + {0x1.0p0, 0x1.c8p5, 0x1.c811f6a9e97a6p5}, + {0x1.0p0, 0x1.cffffffffffe8p5, 0x1.d011a7636789ep5}, + {0x1.0p0, 0x1.d7ffffffffffp5, 0x1.d8115accb20f3p5}, + {0x1.0p0, 0x1.d8p5, 0x1.d8115accb2103p5}, + {0x1.0p0, 0x1.dfffffffffebcp5, 0x1.e01110c367a41p5}, + {0x1.0p0, 0x1.ep5, 0x1.e01110c367b85p5}, + {0x1.0p0, 0x1.e7fffffffffdp5, 0x1.e810c927681fap5}, + {0x1.0p0, 0x1.e8p5, 0x1.e810c9276822ap5}, + {0x1.0p0, 0x1.efffffffff7f8p5, 0x1.f01083daa4dadp5}, + {0x1.0p0, 0x1.fp5, 0x1.f01083daa55b5p5}, + {0x1.0p0, 0x1.f7ffffffffffp5, 0x1.f81040c0f9c6p5}, + {0x1.0p0, 0x1.f8p5, 0x1.f81040c0f9c71p5}, + {0x1.0p0, 0x1.fffffffffffffp5, 0x1.0007ffe000fffp6}, + {0x1.0p0, 0x1.03fffffffffdp6, 0x1.0407e05f7d188p6}, + {0x1.0p0, 0x1.03ffffffffffbp6, 0x1.0407e05f7d1b4p6}, + {0x1.0p0, 0x1.07ffffffff7f8p6, 0x1.0807c1d34edd5p6}, + {0x1.0p0, 0x1.07ffffffff808p6, 0x1.0807c1d34ede4p6}, + {0x1.0p0, 0x1.0bffffffff65p6, 0x1.0c07a430870e5p6}, + {0x1.0p0, 0x1.0bffffffff67p6, 0x1.0c07a43087104p6}, + {0x1.0p0, 0x1.0fffffffffc54p6, 0x1.1007876cda509p6}, + {0x1.0p0, 0x1.0fffffffffe0dp6, 0x1.1007876cda6c2p6}, + {0x1.0p0, 0x1.13fffffffffdp6, 0x1.14076b7e954b4p6}, + {0x1.0p0, 0x1.13ffffffffffep6, 0x1.14076b7e954e3p6}, + {0x1.0p0, 0x1.17ffffffffff8p6, 0x1.1807505c9310dp6}, + {0x1.0p0, 0x1.18p6, 0x1.1807505c93116p6}, + {0x1.0p0, 0x1.1bfffffffecbp6, 0x1.1c0735fe3197ap6}, + {0x1.0p0, 0x1.1bffffffff1dbp6, 0x1.1c0735fe31ea5p6}, + {0x1.0p0, 0x1.1ffffffffebcap6, 0x1.20071c5b4ce64p6}, + {0x1.0p0, 0x1.1fffffffffaf1p6, 0x1.20071c5b4dd8bp6}, + {0x1.0p0, 0x1.23ffffffff83p6, 0x1.2407036c309fdp6}, + {0x1.0p0, 0x1.23ffffffff85p6, 0x1.2407036c30a1cp6}, + {0x1.0p0, 0x1.27ffffffffba8p6, 0x1.2806eb2991e76p6}, + {0x1.0p0, 0x1.28p6, 0x1.2806eb29922cep6}, + {0x1.0p0, 0x1.2bfffffffff7p6, 0x1.2c06d38c8b4ffp6}, + {0x1.0p0, 0x1.2bfffffffff9p6, 0x1.2c06d38c8b52p6}, + {0x1.0p0, 0x1.2fffffffffff4p6, 0x1.3006bc8e938c8p6}, + {0x1.0p0, 0x1.2fffffffffffcp6, 0x1.3006bc8e938cfp6}, + {0x1.0p0, 0x1.33ffffffff87p6, 0x1.3406a6297821ep6}, + {0x1.0p0, 0x1.33ffffffff89p6, 0x1.3406a6297823dp6}, + {0x1.0p0, 0x1.37ffffffff9d8p6, 0x1.380690575943dp6}, + {0x1.0p0, 0x1.37ffffffff9eap6, 0x1.380690575944fp6}, + {0x1.0p0, 0x1.3bffffffffffp6, 0x1.3c067b12a2013p6}, + {0x1.0p0, 0x1.3cp6, 0x1.3c067b12a2024p6}, + {0x1.0p0, 0x1.3fffffffffe19p6, 0x1.40066656044ep6}, + {0x1.0p0, 0x1.4p6, 0x1.40066656046c7p6}, + {0x1.0p0, 0x1.43ffffffff1dp6, 0x1.4406521c75c3p6}, + {0x1.0p0, 0x1.43ffffffffccfp6, 0x1.4406521c7672fp6}, + {0x1.0p0, 0x1.47ffffffff8a8p6, 0x1.48063e612ce7ap6}, + {0x1.0p0, 0x1.47ffffffffcb9p6, 0x1.48063e612d28bp6}, + {0x1.0p0, 0x1.4bfffffffe1fp6, 0x1.4c062b1f96823p6}, + {0x1.0p0, 0x1.4cp6, 0x1.4c062b1f98633p6}, + {0x1.0p0, 0x1.4ffffffffde04p6, 0x1.500618535d07dp6}, + {0x1.0p0, 0x1.5p6, 0x1.500618535f279p6}, + {0x1.0p0, 0x1.53fffffffef1p6, 0x1.540605f85c637p6}, + {0x1.0p0, 0x1.53ffffffffdf3p6, 0x1.540605f85d51ap6}, + {0x1.0p0, 0x1.57ffffffffff8p6, 0x1.5805f40aa0595p6}, + {0x1.0p0, 0x1.5bffffffffffp6, 0x1.5c05e286636b5p6}, + {0x1.0p0, 0x1.5bfffffffffffp6, 0x1.5c05e286636c4p6}, + {0x1.0p0, 0x1.5ffffffffd9cep6, 0x1.6005d1680baa2p6}, + {0x1.0p0, 0x1.5fffffffff873p6, 0x1.6005d1680d947p6}, + {0x1.0p0, 0x1.63ffffffffa5p6, 0x1.6405c0ac30a35p6}, + {0x1.0p0, 0x1.63ffffffffa7p6, 0x1.6405c0ac30a56p6}, + {0x1.0p0, 0x1.67ffffffff988p6, 0x1.6805b04f83ac3p6}, + {0x1.0p0, 0x1.68p6, 0x1.6805b04f8413bp6}, + {0x1.0p0, 0x1.6bfffffffffep6, 0x1.6c05a04ee40c3p6}, + {0x1.0p0, 0x1.6cp6, 0x1.6c05a04ee40e3p6}, + {0x1.0p0, 0x1.6fffffffff018p6, 0x1.700590a74f9b5p6}, + {0x1.0p0, 0x1.6fffffffffbe2p6, 0x1.700590a75057fp6}, + {0x1.0p0, 0x1.73ffffffff4ap6, 0x1.74058155e9b72p6}, + {0x1.0p0, 0x1.74p6, 0x1.74058155ea6d2p6}, + {0x1.0p0, 0x1.77ffffffffffp6, 0x1.78057257f1868p6}, + {0x1.0p0, 0x1.78p6, 0x1.78057257f1878p6}, + {0x1.0p0, 0x1.7bfffffffffep6, 0x1.7c0563aac389bp6}, + {0x1.0p0, 0x1.7bfffffffffe4p6, 0x1.7c0563aac389fp6}, + {0x1.0p0, 0x1.7ffffffffffffp6, 0x1.8005554bda349p6}, + {0x1.0p0, 0x1.8p6, 0x1.8005554bda34bp6}, + {0x1.0p0, 0x1.83fffffffffap6, 0x1.84054738c9dcdp6}, + {0x1.0p0, 0x1.84p6, 0x1.84054738c9e2dp6}, + {0x1.0p0, 0x1.87ffffffff09p6, 0x1.8805396f3f494p6}, + {0x1.0p0, 0x1.87ffffffff0bp6, 0x1.8805396f3f4b5p6}, + {0x1.0p0, 0x1.8bfffffffffep6, 0x1.8c052bed02f7ap6}, + {0x1.0p0, 0x1.8cp6, 0x1.8c052bed02f9bp6}, + {0x1.0p0, 0x1.8fffffffff7c8p6, 0x1.90051eafee07bp6}, + {0x1.0p0, 0x1.9p6, 0x1.90051eafee8b3p6}, + {0x1.0p1, 0x1.fffffffffdcb5p-1, 0x1.1e3779b97f0b5p1}, + {0x1.0p1, 0x1.ffffffffffab5p0, 0x1.6a09e667f39edp1}, + {0x1.0p1, 0x1.7ffffffffffffp1, 0x1.cd82b446159f2p1}, + {0x1.0p1, 0x1.8p1, 0x1.cd82b446159f3p1}, + {0x1.0p1, 0x1.ffffffffffffbp1, 0x1.1e3779b97f4a6p2}, + {0x1.0p1, 0x1.3fffffffffffdp2, 0x1.58a68a4a8d9fp2}, + {0x1.0p1, 0x1.3fffffffffffep2, 0x1.58a68a4a8d9f1p2}, + {0x1.0p1, 0x1.7ffffffffffffp2, 0x1.94c583ada5b51p2}, + {0x1.0p1, 0x1.bfffffffffffep2, 0x1.d1ed52076fbe7p2}, + {0x1.0p1, 0x1.cp2, 0x1.d1ed52076fbe9p2}, + {0x1.0p1, 0x1.ffffffffffffdp2, 0x1.07e0f66afed06p3}, + {0x1.0p1, 0x1.1fffffffffff2p3, 0x1.2706821902e8cp3}, + {0x1.0p1, 0x1.2p3, 0x1.2706821902e9ap3}, + {0x1.0p1, 0x1.3fffffffffffdp3, 0x1.465655f122ff3p3}, + {0x1.0p1, 0x1.4p3, 0x1.465655f122ff6p3}, + {0x1.0p1, 0x1.5ffffffffffd6p3, 0x1.65c55827df1a8p3}, + {0x1.0p1, 0x1.7ffffffffffffp3, 0x1.854bfb363dc38p3}, + {0x1.0p1, 0x1.8p3, 0x1.854bfb363dc39p3}, + {0x1.0p1, 0x1.9ffffffffffe4p3, 0x1.a4e4efeda34c2p3}, + {0x1.0p1, 0x1.ap3, 0x1.a4e4efeda34dep3}, + {0x1.0p1, 0x1.bfffffffffffep3, 0x1.c48c6001f0abdp3}, + {0x1.0p1, 0x1.dfffffffffffcp3, 0x1.e43f746f77956p3}, + {0x1.0p1, 0x1.ep3, 0x1.e43f746f7795bp3}, + {0x1.0p1, 0x1.fffffffffffffp3, 0x1.01fe03f61badp4}, + {0x1.0p1, 0x1.0ffffffffffc4p4, 0x1.11e039f40ee2ap4}, + {0x1.0p1, 0x1.0ffffffffffc7p4, 0x1.11e039f40ee2dp4}, + {0x1.0p1, 0x1.1fffffffffffap4, 0x1.21c5b70d9f81dp4}, + {0x1.0p1, 0x1.2fffffffffffcp4, 0x1.31adf859f9e5ap4}, + {0x1.0p1, 0x1.2fffffffffffep4, 0x1.31adf859f9e5cp4}, + {0x1.0p1, 0x1.3ffffffffffe5p4, 0x1.419894c2329d5p4}, + {0x1.0p1, 0x1.3ffffffffffe7p4, 0x1.419894c2329d8p4}, + {0x1.0p1, 0x1.4fffffffffff4p4, 0x1.518536f3ca668p4}, + {0x1.0p1, 0x1.5p4, 0x1.518536f3ca675p4}, + {0x1.0p1, 0x1.5ffffffffff7ep4, 0x1.617398f2aa9c6p4}, + {0x1.0p1, 0x1.5ffffffffff8dp4, 0x1.617398f2aa9d5p4}, + {0x1.0p1, 0x1.6ffffffffffb8p4, 0x1.716380ce70352p4}, + {0x1.0p1, 0x1.7p4, 0x1.716380ce7039ap4}, + {0x1.0p1, 0x1.7ffffffffff9bp4, 0x1.8154be27734c1p4}, + {0x1.0p1, 0x1.8p4, 0x1.8154be2773526p4}, + {0x1.0p1, 0x1.8ffffffffffe8p4, 0x1.9147284a4142fp4}, + {0x1.0p1, 0x1.8ffffffffffffp4, 0x1.9147284a41446p4}, + {0x1.0p1, 0x1.9fffffffffff4p4, 0x1.a13a9cb996644p4}, + {0x1.0p1, 0x1.9ffffffffffffp4, 0x1.a13a9cb99664fp4}, + {0x1.0p1, 0x1.affffffffff58p4, 0x1.b12efe0a8f113p4}, + {0x1.0p1, 0x1.affffffffffd2p4, 0x1.b12efe0a8f18dp4}, + {0x1.0p1, 0x1.bfffffffffffep4, 0x1.c12432fec0327p4}, + {0x1.0p1, 0x1.cp4, 0x1.c12432fec0329p4}, + {0x1.0p1, 0x1.cffffffffffe8p4, 0x1.d11a25cd6ed78p4}, + {0x1.0p1, 0x1.dp4, 0x1.d11a25cd6ed91p4}, + {0x1.0p1, 0x1.dffffffffffbcp4, 0x1.e110c39105f6bp4}, + {0x1.0p1, 0x1.ep4, 0x1.e110c39105fafp4}, + {0x1.0p1, 0x1.effffffffffe8p4, 0x1.f107fbd0adcf1p4}, + {0x1.0p1, 0x1.efffffffffff8p4, 0x1.f107fbd0addp4}, + {0x1.0p1, 0x1.ffffffffffeafp4, 0x1.007fe00ff5fc8p5}, + {0x1.0p1, 0x1.07fffffffffe8p5, 0x1.087c01e7d5092p5}, + {0x1.0p1, 0x1.08p5, 0x1.087c01e7d50abp5}, + {0x1.0p1, 0x1.0fffffffffff4p5, 0x1.10785dd689a1cp5}, + {0x1.0p1, 0x1.0fffffffffffbp5, 0x1.10785dd689a23p5}, + {0x1.0p1, 0x1.17ffffffffed8p5, 0x1.1874eee5c5cb1p5}, + {0x1.0p1, 0x1.17ffffffffee8p5, 0x1.1874eee5c5cc2p5}, + {0x1.0p1, 0x1.1ffffffffff92p5, 0x1.2071b0abcd7cap5}, + {0x1.0p1, 0x1.1ffffffffff99p5, 0x1.2071b0abcd7d1p5}, + {0x1.0p1, 0x1.27ffffffffea8p5, 0x1.286e9f388de9fp5}, + {0x1.0p1, 0x1.28p5, 0x1.286e9f388dff7p5}, + {0x1.0p1, 0x1.2fffffffffffcp5, 0x1.306bb705ae7bfp5}, + {0x1.0p1, 0x1.2ffffffffffffp5, 0x1.306bb705ae7c3p5}, + {0x1.0p1, 0x1.37ffffffffff8p5, 0x1.3868f4e9108b9p5}, + {0x1.0p1, 0x1.38p5, 0x1.3868f4e9108c1p5}, + {0x1.0p1, 0x1.3fffffffffffdp5, 0x1.4066560954a8bp5}, + {0x1.0p1, 0x1.47ffffffffe28p5, 0x1.4863d7d40ad39p5}, + {0x1.0p1, 0x1.48p5, 0x1.4863d7d40af11p5}, + {0x1.0p1, 0x1.4fffffffffe14p5, 0x1.506177f548fcfp5}, + {0x1.0p1, 0x1.5p5, 0x1.506177f5491bbp5}, + {0x1.0p1, 0x1.57ffffffffeb8p5, 0x1.585f34506bafbp5}, + {0x1.0p1, 0x1.58p5, 0x1.585f34506bc43p5}, + {0x1.0p1, 0x1.5fffffffffffdp5, 0x1.605d0af9d3a42p5}, + {0x1.0p1, 0x1.5fffffffffffep5, 0x1.605d0af9d3a42p5}, + {0x1.0p1, 0x1.67ffffffffda8p5, 0x1.685afa317791bp5}, + {0x1.0p1, 0x1.68p5, 0x1.685afa3177b73p5}, + {0x1.0p1, 0x1.6fffffffffff8p5, 0x1.7059005e2c015p5}, + {0x1.0p1, 0x1.6ffffffffffffp5, 0x1.7059005e2c01dp5}, + {0x1.0p1, 0x1.77ffffffffffp5, 0x1.78571c0982328p5}, + {0x1.0p1, 0x1.78p5, 0x1.78571c0982339p5}, + {0x1.0p1, 0x1.7fffffffffffdp5, 0x1.80554bdc2dc4dp5}, + {0x1.0p1, 0x1.7ffffffffffffp5, 0x1.80554bdc2dc4ep5}, + {0x1.0p1, 0x1.87fffffffffdp5, 0x1.88538e9ad8dacp5}, + {0x1.0p1, 0x1.87fffffffffffp5, 0x1.88538e9ad8ddbp5}, + {0x1.0p1, 0x1.8fffffffffe68p5, 0x1.9051e3235a2cp5}, + {0x1.0p1, 0x1.9p5, 0x1.9051e3235a458p5}, + {0x1.0p1, 0x1.97ffffffffffp5, 0x1.9850486a3f17p5}, + {0x1.0p1, 0x1.97fffffffffffp5, 0x1.9850486a3f17fp5}, + {0x1.0p1, 0x1.9fffffffffff4p5, 0x1.a04ebd789d00cp5}, + {0x1.0p1, 0x1.ap5, 0x1.a04ebd789d019p5}, + {0x1.0p1, 0x1.a7ffffffffe1p5, 0x1.a84d416a2354dp5}, + {0x1.0p1, 0x1.a8p5, 0x1.a84d416a2373dp5}, + {0x1.0p1, 0x1.afffffffffed8p5, 0x1.b04bd36b639fbp5}, + {0x1.0p1, 0x1.affffffffff43p5, 0x1.b04bd36b63a66p5}, + {0x1.0p1, 0x1.b7ffffffffd7p5, 0x1.b84a72b848951p5}, + {0x1.0p1, 0x1.b7ffffffffe2bp5, 0x1.b84a72b848a0cp5}, + {0x1.0p1, 0x1.bfffffffffe3ep5, 0x1.c0491e9ab90fdp5}, + {0x1.0p1, 0x1.cp5, 0x1.c0491e9ab92bfp5}, + {0x1.0p1, 0x1.c7fffffffffdp5, 0x1.c847d6695dbc5p5}, + {0x1.0p1, 0x1.c8p5, 0x1.c847d6695dbf6p5}, + {0x1.0p1, 0x1.cfffffffffed8p5, 0x1.d0469986884d6p5}, + {0x1.0p1, 0x1.cfffffffffee8p5, 0x1.d0469986884e5p5}, + {0x1.0p1, 0x1.d7ffffffffdfp5, 0x1.d845675f37721p5}, + {0x1.0p1, 0x1.d8p5, 0x1.d845675f37931p5}, + {0x1.0p1, 0x1.dfffffffffe5cp5, 0x1.e0443f6a33104p5}, + {0x1.0p1, 0x1.dffffffffffffp5, 0x1.e0443f6a332a7p5}, + {0x1.0p1, 0x1.e7fffffffff05p5, 0x1.e84321273f31ep5}, + {0x1.0p1, 0x1.e7fffffffff1p5, 0x1.e84321273f328p5}, + {0x1.0p1, 0x1.efffffffffff8p5, 0x1.f0420c1e63084p5}, + {0x1.0p1, 0x1.fp5, 0x1.f0420c1e6308dp5}, + {0x1.0p1, 0x1.f7ffffffffc3p5, 0x1.f840ffdf40effp5}, + {0x1.0p1, 0x1.f7fffffffff08p5, 0x1.f840ffdf411d7p5}, + {0x1.0p1, 0x1.ffffffffffffdp5, 0x1.001ffe003ff5fp6}, + {0x1.0p1, 0x1.03fffffffffdp6, 0x1.041f800f9f928p6}, + {0x1.0p1, 0x1.03ffffffffffap6, 0x1.041f800f9f953p6}, + {0x1.0p1, 0x1.07ffffffffed8p6, 0x1.081f05ef4d755p6}, + {0x1.0p1, 0x1.07ffffffffee8p6, 0x1.081f05ef4d764p6}, + {0x1.0p1, 0x1.0bfffffffff5p6, 0x1.0c1e8f739cdcap6}, + {0x1.0p1, 0x1.0bfffffffff7p6, 0x1.0c1e8f739cde9p6}, + {0x1.0p1, 0x1.0fffffffffff4p6, 0x1.101e1c7371c6bp6}, + {0x1.0p1, 0x1.0fffffffffffbp6, 0x1.101e1c7371c72p6}, + {0x1.0p1, 0x1.13fffffffffdp6, 0x1.141dacc811a34p6}, + {0x1.0p1, 0x1.13ffffffffffcp6, 0x1.141dacc811a6p6}, + {0x1.0p1, 0x1.17ffffffffff8p6, 0x1.181d404cf7f51p6}, + {0x1.0p1, 0x1.17ffffffffffdp6, 0x1.181d404cf7f56p6}, + {0x1.0p1, 0x1.1bffffffffffp6, 0x1.1c1cd6dfae4a5p6}, + {0x1.0p1, 0x1.1bffffffffffep6, 0x1.1c1cd6dfae4b4p6}, + {0x1.0p1, 0x1.1fffffffffbf2p6, 0x1.201c705fa7a27p6}, + {0x1.0p1, 0x1.1fffffffffc65p6, 0x1.201c705fa7a9ap6}, + {0x1.0p1, 0x1.23fffffffffdp6, 0x1.241c0cae201cap6}, + {0x1.0p1, 0x1.23ffffffffffp6, 0x1.241c0cae201ebp6}, + {0x1.0p1, 0x1.27ffffffffe08p6, 0x1.281babadfba01p6}, + {0x1.0p1, 0x1.28p6, 0x1.281babadfbbf9p6}, + {0x1.0p1, 0x1.2bffffffffc1p6, 0x1.2c1b4d43ac4cfp6}, + {0x1.0p1, 0x1.2bffffffffc3p6, 0x1.2c1b4d43ac4eep6}, + {0x1.0p1, 0x1.2ffffffffff64p6, 0x1.301af15517357p6}, + {0x1.0p1, 0x1.2ffffffffff6cp6, 0x1.301af1551735ep6}, + {0x1.0p1, 0x1.33ffffffffadp6, 0x1.341a97c97b22ep6}, + {0x1.0p1, 0x1.33ffffffffafp6, 0x1.341a97c97b24fp6}, + {0x1.0p1, 0x1.37ffffffffc78p6, 0x1.381a40895d3f5p6}, + {0x1.0p1, 0x1.37ffffffffc88p6, 0x1.381a40895d406p6}, + {0x1.0p1, 0x1.3bffffffffffp6, 0x1.3c19eb7e71afcp6}, + {0x1.0p1, 0x1.3bfffffffffffp6, 0x1.3c19eb7e71b0cp6}, + {0x1.0p1, 0x1.3fffffffffffdp6, 0x1.4019989389b2dp6}, + {0x1.0p1, 0x1.4p6, 0x1.4019989389b3p6}, + {0x1.0p1, 0x1.43fffffffffdp6, 0x1.441947b4829e8p6}, + {0x1.0p1, 0x1.43ffffffffff8p6, 0x1.441947b482a11p6}, + {0x1.0p1, 0x1.47fffffffffe8p6, 0x1.4818f8ce34e19p6}, + {0x1.0p1, 0x1.47ffffffffffap6, 0x1.4818f8ce34e2cp6}, + {0x1.0p1, 0x1.4bffffffffffp6, 0x1.4c18abce6501fp6}, + {0x1.0p1, 0x1.4bffffffffffcp6, 0x1.4c18abce6502cp6}, + {0x1.0p1, 0x1.4fffffffffa64p6, 0x1.501860a3b54bep6}, + {0x1.0p1, 0x1.4fffffffffe47p6, 0x1.501860a3b58a1p6}, + {0x1.0p1, 0x1.53ffffffffd5p6, 0x1.5418173d9a501p6}, + {0x1.0p1, 0x1.53ffffffffd7p6, 0x1.5418173d9a522p6}, + {0x1.0p1, 0x1.57ffffffffff8p6, 0x1.5817cf8c4c199p6}, + {0x1.0p1, 0x1.57fffffffffffp6, 0x1.5817cf8c4c1ap6}, + {0x1.0p1, 0x1.5bffffffff83p6, 0x1.5c178980bc34bp6}, + {0x1.0p1, 0x1.5bffffffff988p6, 0x1.5c178980bc4a3p6}, + {0x1.0p1, 0x1.5fffffffffbeep6, 0x1.6017450c8d3e7p6}, + {0x1.0p1, 0x1.6p6, 0x1.6017450c8d7f9p6}, + {0x1.0p1, 0x1.63fffffffffdp6, 0x1.6417022204f99p6}, + {0x1.0p1, 0x1.67fffffffffe8p6, 0x1.6816c0b405afp6}, + {0x1.0p1, 0x1.68p6, 0x1.6816c0b405b09p6}, + {0x1.0p1, 0x1.6bfffffffffep6, 0x1.6c1680b6059e8p6}, + {0x1.0p1, 0x1.6cp6, 0x1.6c1680b605a08p6}, + {0x1.0p1, 0x1.6fffffffffb78p6, 0x1.7016421c06043p6}, + {0x1.0p1, 0x1.7p6, 0x1.7016421c064cbp6}, + {0x1.0p1, 0x1.73fffffffffap6, 0x1.741604da8d2b9p6}, + {0x1.0p1, 0x1.73ffffffffff8p6, 0x1.741604da8d311p6}, + {0x1.0p1, 0x1.77ffffffffffp6, 0x1.7815c8e69cc37p6}, + {0x1.0p1, 0x1.77ffffffffffcp6, 0x1.7815c8e69cc43p6}, + {0x1.0p1, 0x1.7bfffffffffep6, 0x1.7c158e35adde4p6}, + {0x1.0p1, 0x1.7bfffffffffe8p6, 0x1.7c158e35addecp6}, + {0x1.0p1, 0x1.7ffffffffffffp6, 0x1.801554bda99c5p6}, + {0x1.0p1, 0x1.83ffffffffdap6, 0x1.84151c74e35e4p6}, + {0x1.0p1, 0x1.83ffffffffdep6, 0x1.84151c74e3625p6}, + {0x1.0p1, 0x1.87fffffffffdp6, 0x1.8814e55214271p6}, + {0x1.0p1, 0x1.87ffffffffffcp6, 0x1.8814e5521429ep6}, + {0x1.0p1, 0x1.8bfffffffffep6, 0x1.8c14af4c540b6p6}, + {0x1.0p1, 0x1.8bffffffffff6p6, 0x1.8c14af4c540cdp6}, + {0x1.0p1, 0x1.8ffffffffffe8p6, 0x1.90147a5b16ce5p6}, + {0x1.0p1, 0x1.8fffffffffffcp6, 0x1.90147a5b16cfap6}, + {0x1.8p1, 0x1.ffffffffffffdp-1, 0x1.94c583ada5b53p1}, + {0x1.8p1, 0x1.0p1, 0x1.cd82b446159f3p1}, + {0x1.8p1, 0x1.7fffffffffff7p1, 0x1.0f876ccdf6cd6p2}, + {0x1.8p1, 0x1.8p1, 0x1.0f876ccdf6cd9p2}, + {0x1.8p1, 0x1.fffffffffffffp1, 0x1.4p2}, + {0x1.8p1, 0x1.3ffffffffffe1p2, 0x1.752e50db3a387p2}, + {0x1.8p1, 0x1.4p2, 0x1.752e50db3a3a2p2}, + {0x1.8p1, 0x1.7ffffffffffffp2, 0x1.ad5336963eefap2}, + {0x1.8p1, 0x1.bfffffffffffep2, 0x1.e768d399dc46dp2}, + {0x1.8p1, 0x1.bffffffffffffp2, 0x1.e768d399dc46fp2}, + {0x1.8p1, 0x1.fffffffffffffp2, 0x1.11687a8ae14a3p3}, + {0x1.8p1, 0x1.1fffffffffff2p3, 0x1.2f9422c23c47p3}, + {0x1.8p1, 0x1.1fffffffffff7p3, 0x1.2f9422c23c475p3}, + {0x1.8p1, 0x1.3fffffffffff1p3, 0x1.4e16fdacff928p3}, + {0x1.8p1, 0x1.3fffffffffff4p3, 0x1.4e16fdacff92bp3}, + {0x1.8p1, 0x1.5ffffffffffffp3, 0x1.6cdb2bbb212ebp3}, + {0x1.8p1, 0x1.7fffffffffffdp3, 0x1.8bd171a07e388p3}, + {0x1.8p1, 0x1.7ffffffffffffp3, 0x1.8bd171a07e389p3}, + {0x1.8p1, 0x1.9ffffffffffe4p3, 0x1.aaeee979b481cp3}, + {0x1.8p1, 0x1.9ffffffffffecp3, 0x1.aaeee979b4825p3}, + {0x1.8p1, 0x1.bffffffffffeep3, 0x1.ca2b9714180e5p3}, + {0x1.8p1, 0x1.cp3, 0x1.ca2b9714180f7p3}, + {0x1.8p1, 0x1.dfffffffffffcp3, 0x1.e98180e9b47edp3}, + {0x1.8p1, 0x1.dfffffffffffep3, 0x1.e98180e9b47efp3}, + {0x1.8p1, 0x1.fffffffffffffp3, 0x1.04760c95db31p4}, + {0x1.8p1, 0x1.0fffffffffff4p4, 0x1.1433ec467efefp4}, + {0x1.8p1, 0x1.1ffffffffffeap4, 0x1.23f8fc68ae515p4}, + {0x1.8p1, 0x1.2p4, 0x1.23f8fc68ae52bp4}, + {0x1.8p1, 0x1.2fffffffffffcp4, 0x1.33c42213ee0c5p4}, + {0x1.8p1, 0x1.3p4, 0x1.33c42213ee0c9p4}, + {0x1.8p1, 0x1.3ffffffffffd9p4, 0x1.439479381ec96p4}, + {0x1.8p1, 0x1.3fffffffffff6p4, 0x1.439479381ecb3p4}, + {0x1.8p1, 0x1.4ffffffffffc4p4, 0x1.53694801747d4p4}, + {0x1.8p1, 0x1.4ffffffffffccp4, 0x1.53694801747dcp4}, + {0x1.8p1, 0x1.5ffffffffffbep4, 0x1.6341f58bad9d2p4}, + {0x1.8p1, 0x1.5ffffffffffc2p4, 0x1.6341f58bad9d7p4}, + {0x1.8p1, 0x1.6fffffffffff8p4, 0x1.731e02ed21f18p4}, + {0x1.8p1, 0x1.6ffffffffffffp4, 0x1.731e02ed21f2p4}, + {0x1.8p1, 0x1.7fffffffffffdp4, 0x1.82fd05f129836p4}, + {0x1.8p1, 0x1.7ffffffffffffp4, 0x1.82fd05f129837p4}, + {0x1.8p1, 0x1.8ffffffffffa8p4, 0x1.92dea50d28578p4}, + {0x1.8p1, 0x1.8ffffffffffffp4, 0x1.92dea50d285cep4}, + {0x1.8p1, 0x1.9ffffffffffe4p4, 0x1.a2c2943e2866p4}, + {0x1.8p1, 0x1.9fffffffffffcp4, 0x1.a2c2943e28678p4}, + {0x1.8p1, 0x1.afffffffffff8p4, 0x1.b2a892946f42dp4}, + {0x1.8p1, 0x1.afffffffffffep4, 0x1.b2a892946f434p4}, + {0x1.8p1, 0x1.bffffffffffeep4, 0x1.c2906842b6bf3p4}, + {0x1.8p1, 0x1.bfffffffffff2p4, 0x1.c2906842b6bf8p4}, + {0x1.8p1, 0x1.cffffffffffe8p4, 0x1.d279e51208c72p4}, + {0x1.8p1, 0x1.dp4, 0x1.d279e51208c8ap4}, + {0x1.8p1, 0x1.dfffffffffff4p4, 0x1.e264df234beddp4}, + {0x1.8p1, 0x1.dfffffffffffcp4, 0x1.e264df234bee4p4}, + {0x1.8p1, 0x1.efffffffffff8p4, 0x1.f25131ed54d64p4}, + {0x1.8p1, 0x1.fp4, 0x1.f25131ed54d6cp4}, + {0x1.8p1, 0x1.fffffffffffffp4, 0x1.011f5eb54147p5}, + {0x1.8p1, 0x1.07fffffffff88p5, 0x1.0916b2b5fff3ep5}, + {0x1.8p1, 0x1.07fffffffffaap5, 0x1.0916b2b5fff6p5}, + {0x1.8p1, 0x1.0ffffffffffc4p5, 0x1.110e8885865b8p5}, + {0x1.8p1, 0x1.0ffffffffffccp5, 0x1.110e8885865c1p5}, + {0x1.8p1, 0x1.17fffffffff58p5, 0x1.1906d51932b7ep5}, + {0x1.8p1, 0x1.17fffffffff77p5, 0x1.1906d51932b9dp5}, + {0x1.8p1, 0x1.1fffffffffffap5, 0x1.20ff8e9d967d6p5}, + {0x1.8p1, 0x1.1fffffffffffep5, 0x1.20ff8e9d967dbp5}, + {0x1.8p1, 0x1.27fffffffffc8p5, 0x1.28f8ac4cd98f2p5}, + {0x1.8p1, 0x1.27fffffffffd8p5, 0x1.28f8ac4cd9903p5}, + {0x1.8p1, 0x1.2ffffffffff7cp5, 0x1.30f2264b9c502p5}, + {0x1.8p1, 0x1.2ffffffffffafp5, 0x1.30f2264b9c535p5}, + {0x1.8p1, 0x1.37ffffffffff8p5, 0x1.38ebf58b30cb4p5}, + {0x1.8p1, 0x1.37fffffffffffp5, 0x1.38ebf58b30cbcp5}, + {0x1.8p1, 0x1.3fffffffffffdp5, 0x1.40e613b03f1dcp5}, + {0x1.8p1, 0x1.3ffffffffffffp5, 0x1.40e613b03f1dfp5}, + {0x1.8p1, 0x1.47fffffffffa1p5, 0x1.48e07afd169d5p5}, + {0x1.8p1, 0x1.47fffffffffa8p5, 0x1.48e07afd169dbp5}, + {0x1.8p1, 0x1.4ffffffffff84p5, 0x1.50db263f101e3p5}, + {0x1.8p1, 0x1.4ffffffffff8cp5, 0x1.50db263f101ecp5}, + {0x1.8p1, 0x1.57ffffffffff8p5, 0x1.58d610be831eep5}, + {0x1.8p1, 0x1.58p5, 0x1.58d610be831f7p5}, + {0x1.8p1, 0x1.5fffffffffffap5, 0x1.60d13630e611p5}, + {0x1.8p1, 0x1.5fffffffffffep5, 0x1.60d13630e6113p5}, + {0x1.8p1, 0x1.67fffffffffe8p5, 0x1.68cc92acc47abp5}, + {0x1.8p1, 0x1.68p5, 0x1.68cc92acc47c3p5}, + {0x1.8p1, 0x1.6fffffffffff8p5, 0x1.70c8229f43a38p5}, + {0x1.8p1, 0x1.6fffffffffffap5, 0x1.70c8229f43a3ap5}, + {0x1.8p1, 0x1.77ffffffffffp5, 0x1.78c3e2c2fb433p5}, + {0x1.8p1, 0x1.77ffffffffffep5, 0x1.78c3e2c2fb441p5}, + {0x1.8p1, 0x1.7ffffffffffffp5, 0x1.80bfd017f10a6p5}, + {0x1.8p1, 0x1.87fffffffff5p5, 0x1.88bbe7dc8d9ap5}, + {0x1.8p1, 0x1.88p5, 0x1.88bbe7dc8da5p5}, + {0x1.8p1, 0x1.8ffffffffffe8p5, 0x1.90b8278768b67p5}, + {0x1.8p1, 0x1.9p5, 0x1.90b8278768b8p5}, + {0x1.8p1, 0x1.97fffffffff2bp5, 0x1.98b48cc1ce669p5}, + {0x1.8p1, 0x1.97fffffffff3p5, 0x1.98b48cc1ce66dp5}, + {0x1.8p1, 0x1.9ffffffffff34p5, 0x1.a0b11562e5efcp5}, + {0x1.8p1, 0x1.ap5, 0x1.a0b11562e5fc8p5}, + {0x1.8p1, 0x1.a7fffffffffdp5, 0x1.a8adbf6b63874p5}, + {0x1.8p1, 0x1.a8p5, 0x1.a8adbf6b638a4p5}, + {0x1.8p1, 0x1.affffffffffd8p5, 0x1.b0aa8901b442cp5}, + {0x1.8p1, 0x1.affffffffffe8p5, 0x1.b0aa8901b443dp5}, + {0x1.8p1, 0x1.b7ffffffffffp5, 0x1.b8a7706e94761p5}, + {0x1.8p1, 0x1.b7ffffffffffep5, 0x1.b8a7706e9477p5}, + {0x1.8p1, 0x1.bfffffffffffep5, 0x1.c0a4741a02dcap5}, + {0x1.8p1, 0x1.cp5, 0x1.c0a4741a02dcdp5}, + {0x1.8p1, 0x1.c7fffffffffdp5, 0x1.c8a1928885b75p5}, + {0x1.8p1, 0x1.c7ffffffffff9p5, 0x1.c8a1928885b9fp5}, + {0x1.8p1, 0x1.cffffffffff28p5, 0x1.d09eca58b7d2cp5}, + {0x1.8p1, 0x1.dp5, 0x1.d09eca58b7e04p5}, + {0x1.8p1, 0x1.d7ffffffffffp5, 0x1.d89c1a4115253p5}, + {0x1.8p1, 0x1.d8p5, 0x1.d89c1a4115264p5}, + {0x1.8p1, 0x1.dfffffffffffcp5, 0x1.e099810dfefd1p5}, + {0x1.8p1, 0x1.e7fffffffffdp5, 0x1.e896fd9ff2afep5}, + {0x1.8p1, 0x1.e7ffffffffffap5, 0x1.e896fd9ff2b29p5}, + {0x1.8p1, 0x1.effffffffff98p5, 0x1.f0948ee9ebc7bp5}, + {0x1.8p1, 0x1.effffffffffcap5, 0x1.f0948ee9ebcadp5}, + {0x1.8p1, 0x1.f7fffffffff7p5, 0x1.f89233efeda08p5}, + {0x1.8p1, 0x1.f7fffffffffb2p5, 0x1.f89233efeda4ap5}, + {0x1.8p1, 0x1.ffffffffffda9p5, 0x1.0047f5e2d7ed7p6}, + {0x1.8p1, 0x1.03ffffffffedp6, 0x1.0446dac6b5468p6}, + {0x1.8p1, 0x1.04p6, 0x1.0446dac6b5598p6}, + {0x1.8p1, 0x1.07fffffffffe8p6, 0x1.0845c83b5eb9bp6}, + {0x1.8p1, 0x1.07ffffffffff9p6, 0x1.0845c83b5ebadp6}, + {0x1.8p1, 0x1.0bffffffffe9bp6, 0x1.0c44bdded82bdp6}, + {0x1.8p1, 0x1.0bffffffffebp6, 0x1.0c44bdded82d1p6}, + {0x1.8p1, 0x1.0fffffffffed4p6, 0x1.1043bb54e5cc9p6}, + {0x1.8p1, 0x1.0ffffffffff1fp6, 0x1.1043bb54e5d14p6}, + {0x1.8p1, 0x1.13ffffffffe9p6, 0x1.1442c046a0ea6p6}, + {0x1.8p1, 0x1.13fffffffff5ap6, 0x1.1442c046a0f7p6}, + {0x1.8p1, 0x1.17fffffffffa8p6, 0x1.1841cc62174cbp6}, + {0x1.8p1, 0x1.17fffffffffb8p6, 0x1.1841cc62174dap6}, + {0x1.8p1, 0x1.1bffffffffffp6, 0x1.1c40df59f1a57p6}, + {0x1.8p1, 0x1.1cp6, 0x1.1c40df59f1a67p6}, + {0x1.8p1, 0x1.1fffffffffffap6, 0x1.203ff8e522535p6}, + {0x1.8p1, 0x1.1ffffffffffffp6, 0x1.203ff8e52253bp6}, + {0x1.8p1, 0x1.23fffffffffdp6, 0x1.243f18be9a334p6}, + {0x1.8p1, 0x1.23ffffffffffbp6, 0x1.243f18be9a36p6}, + {0x1.8p1, 0x1.27fffffffffe8p6, 0x1.283e3ea503c63p6}, + {0x1.8p1, 0x1.27ffffffffff8p6, 0x1.283e3ea503c74p6}, + {0x1.8p1, 0x1.2bffffffffdfp6, 0x1.2c3d6a5a83932p6}, + {0x1.8p1, 0x1.2bffffffffe1p6, 0x1.2c3d6a5a83953p6}, + {0x1.8p1, 0x1.2fffffffffffcp6, 0x1.303c9ba47e6d4p6}, + {0x1.8p1, 0x1.3p6, 0x1.303c9ba47e6d8p6}, + {0x1.8p1, 0x1.33fffffffffdp6, 0x1.343bd24b62468p6}, + {0x1.8p1, 0x1.33fffffffffffp6, 0x1.343bd24b62498p6}, + {0x1.8p1, 0x1.37ffffffffff8p6, 0x1.383b0e1a75c0ap6}, + {0x1.8p1, 0x1.37fffffffffffp6, 0x1.383b0e1a75c12p6}, + {0x1.8p1, 0x1.3bffffffffffp6, 0x1.3c3a4edfa9748p6}, + {0x1.8p1, 0x1.3bffffffffffep6, 0x1.3c3a4edfa9756p6}, + {0x1.8p1, 0x1.3fffffffffd4dp6, 0x1.4039946b6d79fp6}, + {0x1.8p1, 0x1.3ffffffffffffp6, 0x1.4039946b6da51p6}, + {0x1.8p1, 0x1.43fffffffff9p6, 0x1.4438de908abeap6}, + {0x1.8p1, 0x1.43fffffffffbp6, 0x1.4438de908ac0bp6}, + {0x1.8p1, 0x1.47ffffffffd08p6, 0x1.48382d23fccedp6}, + {0x1.8p1, 0x1.47fffffffffa2p6, 0x1.48382d23fcf87p6}, + {0x1.8p1, 0x1.4bffffffffcebp6, 0x1.4c377ffcd212fp6}, + {0x1.8p1, 0x1.4bffffffffcfp6, 0x1.4c377ffcd2133p6}, + {0x1.8p1, 0x1.4ffffffffff44p6, 0x1.5036d6f40ad53p6}, + {0x1.8p1, 0x1.4ffffffffff9bp6, 0x1.5036d6f40adaap6}, + {0x1.8p1, 0x1.53ffffffffedp6, 0x1.543631e47c1e1p6}, + {0x1.8p1, 0x1.54p6, 0x1.543631e47c311p6}, + {0x1.8p1, 0x1.57ffffffffd78p6, 0x1.583590aab542dp6}, + {0x1.8p1, 0x1.58p6, 0x1.583590aab56b5p6}, + {0x1.8p1, 0x1.5bffffffffc7p6, 0x1.5c34f324e60eep6}, + {0x1.8p1, 0x1.5bffffffffc9p6, 0x1.5c34f324e610fp6}, + {0x1.8p1, 0x1.5fffffffffffdp6, 0x1.60345932c760dp6}, + {0x1.8p1, 0x1.5fffffffffffep6, 0x1.60345932c760dp6}, + {0x1.8p1, 0x1.63fffffffff79p6, 0x1.6433c2b58421fp6}, + {0x1.8p1, 0x1.63fffffffff9p6, 0x1.6433c2b584235p6}, + {0x1.8p1, 0x1.67ffffffffda8p6, 0x1.68332f8fa63a6p6}, + {0x1.8p1, 0x1.67fffffffff4dp6, 0x1.68332f8fa654bp6}, + {0x1.8p1, 0x1.6bfffffffffep6, 0x1.6c329fa502ccfp6}, + {0x1.8p1, 0x1.6cp6, 0x1.6c329fa502cefp6}, + {0x1.8p1, 0x1.6fffffffffff8p6, 0x1.703212daa75f3p6}, + {0x1.8p1, 0x1.6ffffffffffffp6, 0x1.703212daa75fbp6}, + {0x1.8p1, 0x1.73fffffffffap6, 0x1.74318916ca409p6}, + {0x1.8p1, 0x1.74p6, 0x1.74318916ca46ap6}, + {0x1.8p1, 0x1.77ffffffffffp6, 0x1.78310240ba47p6}, + {0x1.8p1, 0x1.78p6, 0x1.78310240ba481p6}, + {0x1.8p1, 0x1.7bfffffffffep6, 0x1.7c307e40cff7fp6}, + {0x1.8p1, 0x1.7bfffffffffe4p6, 0x1.7c307e40cff83p6}, + {0x1.8p1, 0x1.7fffffffffff7p6, 0x1.802ffd005ff07p6}, + {0x1.8p1, 0x1.7fffffffffff9p6, 0x1.802ffd005ff0ap6}, + {0x1.8p1, 0x1.83fffffffffap6, 0x1.842f7e69adc1ep6}, + {0x1.8p1, 0x1.83fffffffffffp6, 0x1.842f7e69adc7dp6}, + {0x1.8p1, 0x1.87fffffffffdp6, 0x1.882f0267dfef4p6}, + {0x1.8p1, 0x1.88p6, 0x1.882f0267dff24p6}, + {0x1.8p1, 0x1.8bfffffffffep6, 0x1.8c2e88e6f449ap6}, + {0x1.8p1, 0x1.8bffffffffff6p6, 0x1.8c2e88e6f44b1p6}, + {0x1.8p1, 0x1.8ffffffffffe8p6, 0x1.902e11d3b5549p6}, + {0x1.8p1, 0x1.8fffffffffffep6, 0x1.902e11d3b556p6}, + }; + + for (double[] testCase: testCases) + failures+=testHypotCase(testCase[0], testCase[1], testCase[2]); + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testHypot(); + + if (failures > 0) { + System.err.println("Testing log1p incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/Log10Tests.java b/jdk/test/java/lang/StrictMath/Log10Tests.java new file mode 100644 index 00000000000..2c61ba1acd3 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/Log10Tests.java @@ -0,0 +1,724 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4074599 + * @summary Tests for StrictMath.log10 + * @author Joseph D. Darcy + */ + + +/** + * The tests in ../Math/Log10Tests.java test properties that should + * hold for any log10 implementation, including the FDLIBM-based one + * required for StrictMath.log10. Therefore, the test cases in + * ../Math/Log10Tests.java are run against both the Math and + * StrictMath versions of log10. The role of this test is to verify + * that the FDLIBM log10 algorithm is being used by running golden + * file tests on values that may vary from one conforming log10 + * implementation to another. + */ + +public class Log10Tests { + private Log10Tests(){} + + static int testLog10Case(double input, double expected) { + return Tests.test("StrictMath.log10(double)", input, + StrictMath.log10(input), expected); + } + + static int testLog10() { + int failures = 0; + double [][] testCases = { + {0x1.3fffffffffec1p-297, -0x1.653c6a27ae2f8p6}, + {0x1.4p-297, -0x1.653c6a27ae2f7p6}, + {0x1.3fffffffffbe1p-296, -0x1.640828f2a4382p6}, + {0x1.4p-296, -0x1.640828f2a437dp6}, + {0x1.3fffffffffd52p-295, -0x1.62d3e7bd9a406p6}, + {0x1.4p-295, -0x1.62d3e7bd9a403p6}, + {0x1.3fffffffffa72p-294, -0x1.619fa6889049p6}, + {0x1.4p-294, -0x1.619fa68890489p6}, + {0x1.3fffffffff9bbp-293, -0x1.606b655386518p6}, + {0x1.4p-293, -0x1.606b65538650fp6}, + {0x1.3fffffffffbe4p-292, -0x1.5f37241e7c59ap6}, + {0x1.4p-292, -0x1.5f37241e7c595p6}, + {0x1.3ffffffffff7ep-291, -0x1.5e02e2e97261cp6}, + {0x1.4p-291, -0x1.5e02e2e97261bp6}, + {0x1.3fffffffffc9ep-290, -0x1.5ccea1b4686a6p6}, + {0x1.4p-290, -0x1.5ccea1b4686a1p6}, + {0x1.3fffffffffec7p-289, -0x1.5b9a607f5e728p6}, + {0x1.4p-289, -0x1.5b9a607f5e727p6}, + {0x1.3fffffffffbe7p-288, -0x1.5a661f4a547b2p6}, + {0x1.4p-288, -0x1.5a661f4a547adp6}, + {0x1.3fffffffff907p-287, -0x1.5931de154a83cp6}, + {0x1.4p-287, -0x1.5931de154a833p6}, + {0x1.3fffffffffd59p-286, -0x1.57fd9ce0408bcp6}, + {0x1.4p-286, -0x1.57fd9ce0408b9p6}, + {0x1.3fffffffffecap-285, -0x1.56c95bab3694p6}, + {0x1.4p-285, -0x1.56c95bab3693fp6}, + {0x1.3fffffffffbeap-284, -0x1.55951a762c9cap6}, + {0x1.4p-284, -0x1.55951a762c9c5p6}, + {0x1.3ffffffffff84p-283, -0x1.5460d94122a4cp6}, + {0x1.4p-283, -0x1.5460d94122a4bp6}, + {0x1.3fffffffffca4p-282, -0x1.532c980c18ad6p6}, + {0x1.4p-282, -0x1.532c980c18ad1p6}, + {0x1.3fffffffff9c4p-281, -0x1.51f856d70eb6p6}, + {0x1.4p-281, -0x1.51f856d70eb57p6}, + {0x1.3fffffffffe16p-280, -0x1.50c415a204bep6}, + {0x1.4p-280, -0x1.50c415a204bddp6}, + {0x1.3fffffffffd5ep-279, -0x1.4f8fd46cfac66p6}, + {0x1.4p-279, -0x1.4f8fd46cfac63p6}, + {0x1.3fffffffffd5fp-278, -0x1.4e5b9337f0cecp6}, + {0x1.4p-278, -0x1.4e5b9337f0ce9p6}, + {0x1.3fffffffffedp-277, -0x1.4d275202e6d7p6}, + {0x1.4p-277, -0x1.4d275202e6d6fp6}, + {0x1.3fffffffffbfp-276, -0x1.4bf310cddcdfap6}, + {0x1.4p-276, -0x1.4bf310cddcdf5p6}, + {0x1.3ffffffffff8ap-275, -0x1.4abecf98d2e7bp6}, + {0x1.4p-275, -0x1.4abecf98d2e7bp6}, + {0x1.3fffffffffd62p-274, -0x1.498a8e63c8f04p6}, + {0x1.4p-274, -0x1.498a8e63c8f01p6}, + {0x1.3fffffffff9cap-273, -0x1.48564d2ebef9p6}, + {0x1.4p-273, -0x1.48564d2ebef87p6}, + {0x1.3fffffffff6eap-272, -0x1.47220bf9b501ap6}, + {0x1.4p-272, -0x1.47220bf9b500dp6}, + {0x1.3fffffffffb3cp-271, -0x1.45edcac4ab09ap6}, + {0x1.4p-271, -0x1.45edcac4ab093p6}, + {0x1.3fffffffffd65p-270, -0x1.44b9898fa111cp6}, + {0x1.4p-270, -0x1.44b9898fa1119p6}, + {0x1.3fffffffffa85p-269, -0x1.4385485a971a6p6}, + {0x1.4p-269, -0x1.4385485a9719fp6}, + {0x1.3ffffffffe2c7p-268, -0x1.425107258d24dp6}, + {0x1.3fffffffffed7p-268, -0x1.425107258d226p6}, + {0x1.4p-268, -0x1.425107258d225p6}, + {0x1.3fffffffff916p-267, -0x1.411cc5f0832b4p6}, + {0x1.4p-267, -0x1.411cc5f0832abp6}, + {0x1.3fffffffffd68p-266, -0x1.3fe884bb79334p6}, + {0x1.4p-266, -0x1.3fe884bb79331p6}, + {0x1.3fffffffffe21p-265, -0x1.3eb443866f3b9p6}, + {0x1.4p-265, -0x1.3eb443866f3b7p6}, + {0x1.3fffffffffedap-264, -0x1.3d8002516543ep6}, + {0x1.4p-264, -0x1.3d8002516543dp6}, + {0x1.3fffffffffbfap-263, -0x1.3c4bc11c5b4c9p6}, + {0x1.4p-263, -0x1.3c4bc11c5b4c3p6}, + {0x1.3fffffffff862p-262, -0x1.3b177fe751554p6}, + {0x1.4p-262, -0x1.3b177fe751549p6}, + {0x1.3fffffffffa8bp-261, -0x1.39e33eb2475d6p6}, + {0x1.4p-261, -0x1.39e33eb2475cfp6}, + {0x1.3fffffffffeddp-260, -0x1.38aefd7d3d656p6}, + {0x1.4p-260, -0x1.38aefd7d3d655p6}, + {0x1.3fffffffffbfdp-259, -0x1.377abc48336ep6}, + {0x1.4p-259, -0x1.377abc48336dbp6}, + {0x1.3ffffffffff97p-258, -0x1.36467b1329762p6}, + {0x1.4p-258, -0x1.36467b1329761p6}, + {0x1.3fffffffffedfp-257, -0x1.351239de1f7e8p6}, + {0x1.4p-257, -0x1.351239de1f7e7p6}, + {0x1.3fffffffffeep-256, -0x1.33ddf8a91586ep6}, + {0x1.4p-256, -0x1.33ddf8a91586dp6}, + {0x1.3fffffffffcp-255, -0x1.32a9b7740b8f8p6}, + {0x1.4p-255, -0x1.32a9b7740b8f3p6}, + {0x1.3fffffffffd71p-254, -0x1.3175763f0197cp6}, + {0x1.4p-254, -0x1.3175763f01979p6}, + {0x1.3fffffffff588p-253, -0x1.30413509f7a0ep6}, + {0x1.4p-253, -0x1.30413509f79ffp6}, + {0x1.3fffffffff7b1p-252, -0x1.2f0cf3d4eda9p6}, + {0x1.4p-252, -0x1.2f0cf3d4eda85p6}, + {0x1.3fffffffffc03p-251, -0x1.2dd8b29fe3b1p6}, + {0x1.4p-251, -0x1.2dd8b29fe3b0bp6}, + {0x1.3fffffffff86bp-250, -0x1.2ca4716ad9b9cp6}, + {0x1.4p-250, -0x1.2ca4716ad9b91p6}, + {0x1.3fffffffffcbdp-249, -0x1.2b703035cfc1cp6}, + {0x1.4p-249, -0x1.2b703035cfc17p6}, + {0x1.3fffffffffee6p-248, -0x1.2a3bef00c5c9ep6}, + {0x1.4p-248, -0x1.2a3bef00c5c9dp6}, + {0x1.3fffffffffc06p-247, -0x1.2907adcbbbd28p6}, + {0x1.4p-247, -0x1.2907adcbbbd23p6}, + {0x1.3fffffffffd77p-246, -0x1.27d36c96b1dacp6}, + {0x1.4p-246, -0x1.27d36c96b1da9p6}, + {0x1.3fffffffffd78p-245, -0x1.269f2b61a7e32p6}, + {0x1.4p-245, -0x1.269f2b61a7e2fp6}, + {0x1.3ffffffffea0bp-244, -0x1.256aea2c9ded3p6}, + {0x1.3fffffffffee9p-244, -0x1.256aea2c9deb6p6}, + {0x1.4p-244, -0x1.256aea2c9deb5p6}, + {0x1.3fffffffffe32p-243, -0x1.2436a8f793f3ep6}, + {0x1.4p-243, -0x1.2436a8f793f3bp6}, + {0x1.3ffffffffffa3p-242, -0x1.230267c289fc2p6}, + {0x1.4p-242, -0x1.230267c289fc1p6}, + {0x1.3fffffffff591p-241, -0x1.21ce268d80056p6}, + {0x1.4p-241, -0x1.21ce268d80047p6}, + {0x1.3fffffffff9e3p-240, -0x1.2099e558760d6p6}, + {0x1.4p-240, -0x1.2099e558760cdp6}, + {0x1.3fffffffffc0cp-239, -0x1.1f65a4236c158p6}, + {0x1.4p-239, -0x1.1f65a4236c153p6}, + {0x1.3fffffffffd7dp-238, -0x1.1e3162ee621dcp6}, + {0x1.4p-238, -0x1.1e3162ee621d9p6}, + {0x1.3fffffffffd7ep-237, -0x1.1cfd21b958262p6}, + {0x1.4p-237, -0x1.1cfd21b95825fp6}, + {0x1.3fffffffffeefp-236, -0x1.1bc8e0844e2e6p6}, + {0x1.4p-236, -0x1.1bc8e0844e2e5p6}, + {0x1.3fffffffffc0fp-235, -0x1.1a949f4f4437p6}, + {0x1.4p-235, -0x1.1a949f4f4436bp6}, + {0x1.3ffffffffffa9p-234, -0x1.19605e1a3a3f1p6}, + {0x1.4p-234, -0x1.19605e1a3a3f1p6}, + {0x1.3ffffffffffaap-233, -0x1.182c1ce530478p6}, + {0x1.4p-233, -0x1.182c1ce530477p6}, + {0x1.3fffffffff2b7p-232, -0x1.16f7dbb02651p6}, + {0x1.4p-232, -0x1.16f7dbb0264fdp6}, + {0x1.3fffffffffef3p-231, -0x1.15c39a7b1c584p6}, + {0x1.4p-231, -0x1.15c39a7b1c583p6}, + {0x1.3fffffffff932p-230, -0x1.148f594612612p6}, + {0x1.4p-230, -0x1.148f594612609p6}, + {0x1.3fffffffffd84p-229, -0x1.135b181108692p6}, + {0x1.4p-229, -0x1.135b18110868fp6}, + {0x1.3fffffffffaa4p-228, -0x1.1226d6dbfe71cp6}, + {0x1.4p-228, -0x1.1226d6dbfe715p6}, + {0x1.3fffffffffef6p-227, -0x1.10f295a6f479cp6}, + {0x1.4p-227, -0x1.10f295a6f479bp6}, + {0x1.3fffffffffd86p-226, -0x1.0fbe5471ea824p6}, + {0x1.4p-226, -0x1.0fbe5471ea821p6}, + {0x1.3fffffffffd87p-225, -0x1.0e8a133ce08aap6}, + {0x1.4p-225, -0x1.0e8a133ce08a7p6}, + {0x1.3fffffffffef8p-224, -0x1.0d55d207d692ep6}, + {0x1.4p-224, -0x1.0d55d207d692dp6}, + {0x1.3fffffffffef9p-223, -0x1.0c2190d2cc9b4p6}, + {0x1.4p-223, -0x1.0c2190d2cc9b3p6}, + {0x1.3fffffffff42fp-222, -0x1.0aed4f9dc2a4ap6}, + {0x1.4p-222, -0x1.0aed4f9dc2a39p6}, + {0x1.3fffffffff658p-221, -0x1.09b90e68b8accp6}, + {0x1.4p-221, -0x1.09b90e68b8abfp6}, + {0x1.3fffffffffaaap-220, -0x1.0884cd33aeb4cp6}, + {0x1.4p-220, -0x1.0884cd33aeb45p6}, + {0x1.3fffffffffefcp-219, -0x1.07508bfea4bccp6}, + {0x1.4p-219, -0x1.07508bfea4bcbp6}, + {0x1.3fffffffffc1cp-218, -0x1.061c4ac99ac56p6}, + {0x1.4p-218, -0x1.061c4ac99ac51p6}, + {0x1.3fffffffffd8dp-217, -0x1.04e8099490cdap6}, + {0x1.4p-217, -0x1.04e8099490cd7p6}, + {0x1.3fffffffffaadp-216, -0x1.03b3c85f86d65p6}, + {0x1.3fffffffffefep-216, -0x1.03b3c85f86d5ep6}, + {0x1.4p-216, -0x1.03b3c85f86d5dp6}, + {0x1.3ffffffffdbbdp-215, -0x1.027f872a7ce16p6}, + {0x1.3fffffffffeffp-215, -0x1.027f872a7cde4p6}, + {0x1.4p-215, -0x1.027f872a7cde3p6}, + {0x1.3fffffffffc1fp-214, -0x1.014b45f572e6ep6}, + {0x1.4p-214, -0x1.014b45f572e69p6}, + {0x1.3ffffffffffb9p-213, -0x1.001704c068efp6}, + {0x1.4p-213, -0x1.001704c068eefp6}, + {0x1.3fffffffffdbfp-212, -0x1.fdc58716bdefp5}, + {0x1.4p-212, -0x1.fdc58716bdeeap5}, + {0x1.3ffffffffff3p-211, -0x1.fb5d04aca9ff8p5}, + {0x1.4p-211, -0x1.fb5d04aca9ff6p5}, + {0x1.3ffffffffffe9p-210, -0x1.f8f4824296102p5}, + {0x1.4p-210, -0x1.f8f4824296102p5}, + {0x1.3fffffffffd09p-209, -0x1.f68bffd882216p5}, + {0x1.4p-209, -0x1.f68bffd88220ep5}, + {0x1.3fffffffffdc2p-208, -0x1.f4237d6e6e32p5}, + {0x1.4p-208, -0x1.f4237d6e6e31ap5}, + {0x1.3fffffffff23fp-207, -0x1.f1bafb045a44cp5}, + {0x1.3fffffffffe7bp-207, -0x1.f1bafb045a42ap5}, + {0x1.4p-207, -0x1.f1bafb045a426p5}, + {0x1.3ffffffffffecp-206, -0x1.ef52789a46532p5}, + {0x1.4p-206, -0x1.ef52789a46532p5}, + {0x1.3fffffffffdc4p-205, -0x1.ece9f63032644p5}, + {0x1.4p-205, -0x1.ece9f6303263ep5}, + {0x1.3ffffffffe211p-204, -0x1.ea8173c61e79ep5}, + {0x1.3ffffffffff35p-204, -0x1.ea8173c61e74cp5}, + {0x1.4p-204, -0x1.ea8173c61e74ap5}, + {0x1.3ffffffffec25p-203, -0x1.e818f15c0a88ep5}, + {0x1.3fffffffffe7ep-203, -0x1.e818f15c0a85ap5}, + {0x1.4p-203, -0x1.e818f15c0a856p5}, + {0x1.3ffffffffdcadp-202, -0x1.e5b06ef1f69c5p5}, + {0x1.3fffffffffedbp-202, -0x1.e5b06ef1f6966p5}, + {0x1.4p-202, -0x1.e5b06ef1f6962p5}, + {0x1.3fffffffffd0fp-201, -0x1.e347ec87e2a76p5}, + {0x1.4p-201, -0x1.e347ec87e2a6ep5}, + {0x1.3fffffffffe8p-200, -0x1.e0df6a1dceb7ep5}, + {0x1.4p-200, -0x1.e0df6a1dceb7ap5}, + {0x1.3ffffffffff39p-199, -0x1.de76e7b3bac88p5}, + {0x1.4p-199, -0x1.de76e7b3bac86p5}, + {0x1.3fffffffffff2p-198, -0x1.dc0e6549a6d92p5}, + {0x1.4p-198, -0x1.dc0e6549a6d92p5}, + {0x1.3ffffffffff97p-197, -0x1.d9a5e2df92eap5}, + {0x1.4p-197, -0x1.d9a5e2df92e9ep5}, + {0x1.3fffffffffdcbp-196, -0x1.d73d60757efbp5}, + {0x1.4p-196, -0x1.d73d60757efaap5}, + {0x1.3ffffffffff3cp-195, -0x1.d4d4de0b6b0b8p5}, + {0x1.4p-195, -0x1.d4d4de0b6b0b6p5}, + {0x1.3fffffffffee1p-194, -0x1.d26c5ba1571c6p5}, + {0x1.4p-194, -0x1.d26c5ba1571c2p5}, + {0x1.3ffffffffff9ap-193, -0x1.d003d937432dp5}, + {0x1.4p-193, -0x1.d003d937432cep5}, + {0x1.3fffffffffdcep-192, -0x1.cd9b56cd2f3ep5}, + {0x1.4p-192, -0x1.cd9b56cd2f3dap5}, + {0x1.3fffffffffe87p-191, -0x1.cb32d4631b4eap5}, + {0x1.4p-191, -0x1.cb32d4631b4e6p5}, + {0x1.3fffffffffff8p-190, -0x1.c8ca51f9075f2p5}, + {0x1.4p-190, -0x1.c8ca51f9075f2p5}, + {0x1.3fffffffffff9p-189, -0x1.c661cf8ef36fep5}, + {0x1.4p-189, -0x1.c661cf8ef36fep5}, + {0x1.3fffffffffdd1p-188, -0x1.c3f94d24df81p5}, + {0x1.4p-188, -0x1.c3f94d24df80ap5}, + {0x1.3fffffffffe8ap-187, -0x1.c190cabacb91ap5}, + {0x1.4p-187, -0x1.c190cabacb916p5}, + {0x1.3ffffffffff43p-186, -0x1.bf284850b7a24p5}, + {0x1.4p-186, -0x1.bf284850b7a22p5}, + {0x1.3fffffffffffcp-185, -0x1.bcbfc5e6a3b2ep5}, + {0x1.4p-185, -0x1.bcbfc5e6a3b2ep5}, + {0x1.3ffffffffffa1p-184, -0x1.ba57437c8fc3cp5}, + {0x1.4p-184, -0x1.ba57437c8fc3ap5}, + {0x1.3fffffffffd79p-183, -0x1.b7eec1127bd4ep5}, + {0x1.4p-183, -0x1.b7eec1127bd46p5}, + {0x1.3fffffffffe32p-182, -0x1.b5863ea867e58p5}, + {0x1.4p-182, -0x1.b5863ea867e52p5}, + {0x1.3ffffffffe4a7p-181, -0x1.b31dbc3e53faap5}, + {0x1.3ffffffffffffp-181, -0x1.b31dbc3e53f5ep5}, + {0x1.4p-181, -0x1.b31dbc3e53f5ep5}, + {0x1.3fffffffffdd7p-180, -0x1.b0b539d44007p5}, + {0x1.4p-180, -0x1.b0b539d44006ap5}, + {0x1.3fffffffffa9bp-179, -0x1.ae4cb76a2c185p5}, + {0x1.3fffffffffe9p-179, -0x1.ae4cb76a2c17ap5}, + {0x1.4p-179, -0x1.ae4cb76a2c177p5}, + {0x1.3ffffffffe3f1p-178, -0x1.abe43500182d1p5}, + {0x1.3ffffffffff49p-178, -0x1.abe4350018284p5}, + {0x1.4p-178, -0x1.abe4350018283p5}, + {0x1.3fffffffffc69p-177, -0x1.a97bb29604398p5}, + {0x1.4p-177, -0x1.a97bb2960438fp5}, + {0x1.3fffffffffddap-176, -0x1.a713302bf04ap5}, + {0x1.4p-176, -0x1.a713302bf049bp5}, + {0x1.3fffffffffe93p-175, -0x1.a4aaadc1dc5aap5}, + {0x1.4p-175, -0x1.a4aaadc1dc5a7p5}, + {0x1.3fffffffff481p-174, -0x1.a2422b57c86d3p5}, + {0x1.3fffffffffe38p-174, -0x1.a2422b57c86b8p5}, + {0x1.4p-174, -0x1.a2422b57c86b3p5}, + {0x1.3fffffffffef1p-173, -0x1.9fd9a8edb47c2p5}, + {0x1.4p-173, -0x1.9fd9a8edb47bfp5}, + {0x1.3ffffffffffaap-172, -0x1.9d712683a08ccp5}, + {0x1.4p-172, -0x1.9d712683a08cbp5}, + {0x1.3fffffffffddep-171, -0x1.9b08a4198c9dcp5}, + {0x1.4p-171, -0x1.9b08a4198c9d7p5}, + {0x1.3ffffffffff4fp-170, -0x1.98a021af78ae4p5}, + {0x1.4p-170, -0x1.98a021af78ae3p5}, + {0x1.3fffffffffd27p-169, -0x1.96379f4564bf6p5}, + {0x1.4p-169, -0x1.96379f4564befp5}, + {0x1.3fffffffffdep-168, -0x1.93cf1cdb50dp5}, + {0x1.4p-168, -0x1.93cf1cdb50cfbp5}, + {0x1.3fffffffffe99p-167, -0x1.91669a713ce0ap5}, + {0x1.4p-167, -0x1.91669a713ce07p5}, + {0x1.3ffffffffff52p-166, -0x1.8efe180728f14p5}, + {0x1.4p-166, -0x1.8efe180728f13p5}, + {0x1.3fffffffffc72p-165, -0x1.8c95959d15028p5}, + {0x1.4p-165, -0x1.8c95959d1501fp5}, + {0x1.3ffffffffffbp-164, -0x1.8a2d13330112cp5}, + {0x1.4p-164, -0x1.8a2d13330112bp5}, + {0x1.3fffffffffd88p-163, -0x1.87c490c8ed23ep5}, + {0x1.4p-163, -0x1.87c490c8ed237p5}, + {0x1.3fffffffffe9dp-162, -0x1.855c0e5ed9346p5}, + {0x1.4p-162, -0x1.855c0e5ed9343p5}, + {0x1.3fffffffffefap-161, -0x1.82f38bf4c5452p5}, + {0x1.4p-161, -0x1.82f38bf4c544fp5}, + {0x1.3fffffffffd2ep-160, -0x1.808b098ab1562p5}, + {0x1.4p-160, -0x1.808b098ab155bp5}, + {0x1.3fffffffffe9fp-159, -0x1.7e2287209d66ap5}, + {0x1.4p-159, -0x1.7e2287209d667p5}, + {0x1.3ffffffffff58p-158, -0x1.7bba04b689774p5}, + {0x1.4p-158, -0x1.7bba04b689773p5}, + {0x1.3fffffffff099p-157, -0x1.7951824c758aap5}, + {0x1.3ffffffffff59p-157, -0x1.7951824c7588p5}, + {0x1.4p-157, -0x1.7951824c7587fp5}, + {0x1.3fffffffffd31p-156, -0x1.76e8ffe261992p5}, + {0x1.4p-156, -0x1.76e8ffe26198bp5}, + {0x1.3fffffffffdeap-155, -0x1.74807d784da9cp5}, + {0x1.4p-155, -0x1.74807d784da97p5}, + {0x1.3fffffffffea3p-154, -0x1.7217fb0e39ba6p5}, + {0x1.4p-154, -0x1.7217fb0e39ba3p5}, + {0x1.3fffffffffc7bp-153, -0x1.6faf78a425cb8p5}, + {0x1.3ffffffffff5cp-153, -0x1.6faf78a425cbp5}, + {0x1.4p-153, -0x1.6faf78a425cafp5}, + {0x1.3ffffffffffb9p-152, -0x1.6d46f63a11dbcp5}, + {0x1.4p-152, -0x1.6d46f63a11dbbp5}, + {0x1.3fffffffffa54p-151, -0x1.6ade73cffded6p5}, + {0x1.4p-151, -0x1.6ade73cffdec7p5}, + {0x1.3fffffffffbc5p-150, -0x1.6875f165e9fdfp5}, + {0x1.3fffffffffea6p-150, -0x1.6875f165e9fd6p5}, + {0x1.4p-150, -0x1.6875f165e9fd3p5}, + {0x1.3ffffffffff5fp-149, -0x1.660d6efbd60ep5}, + {0x1.4p-149, -0x1.660d6efbd60dfp5}, + {0x1.3fffffffffdefp-148, -0x1.63a4ec91c21fp5}, + {0x1.4p-148, -0x1.63a4ec91c21ebp5}, + {0x1.3fffffffffea8p-147, -0x1.613c6a27ae2fap5}, + {0x1.4p-147, -0x1.613c6a27ae2f7p5}, + {0x1.3ffffffffff61p-146, -0x1.5ed3e7bd9a404p5}, + {0x1.4p-146, -0x1.5ed3e7bd9a403p5}, + {0x1.3ffffffffff62p-145, -0x1.5c6b65538651p5}, + {0x1.4p-145, -0x1.5c6b65538650fp5}, + {0x1.3ffffffffffbfp-144, -0x1.5a02e2e97261cp5}, + {0x1.4p-144, -0x1.5a02e2e97261bp5}, + {0x1.3fffffffffcdfp-143, -0x1.579a607f5e73p5}, + {0x1.4p-143, -0x1.579a607f5e727p5}, + {0x1.3fffffffffd98p-142, -0x1.5531de154a83ap5}, + {0x1.4p-142, -0x1.5531de154a833p5}, + {0x1.3fffffffffe51p-141, -0x1.52c95bab36944p5}, + {0x1.4p-141, -0x1.52c95bab3693fp5}, + {0x1.3ffffffffffc2p-140, -0x1.5060d94122a4cp5}, + {0x1.4p-140, -0x1.5060d94122a4bp5}, + {0x1.3fffffffffdf6p-139, -0x1.4df856d70eb5cp5}, + {0x1.4p-139, -0x1.4df856d70eb57p5}, + {0x1.3fffffffffeafp-138, -0x1.4b8fd46cfac66p5}, + {0x1.4p-138, -0x1.4b8fd46cfac63p5}, + {0x1.3ffffffffff68p-137, -0x1.49275202e6d7p5}, + {0x1.4p-137, -0x1.49275202e6d6fp5}, + {0x1.3ffffffffffc5p-136, -0x1.46becf98d2e7bp5}, + {0x1.4p-136, -0x1.46becf98d2e7bp5}, + {0x1.3fffffffffdf9p-135, -0x1.44564d2ebef8cp5}, + {0x1.4p-135, -0x1.44564d2ebef87p5}, + {0x1.3fffffffffeb2p-134, -0x1.41edcac4ab096p5}, + {0x1.4p-134, -0x1.41edcac4ab093p5}, + {0x1.3ffffffffff6bp-133, -0x1.3f85485a971ap5}, + {0x1.4p-133, -0x1.3f85485a9719fp5}, + {0x1.3ffffffffe699p-132, -0x1.3d1cc5f0832f2p5}, + {0x1.3ffffffffff1p-132, -0x1.3d1cc5f0832aep5}, + {0x1.4p-132, -0x1.3d1cc5f0832abp5}, + {0x1.3ffffffffffc9p-131, -0x1.3ab443866f3b8p5}, + {0x1.4p-131, -0x1.3ab443866f3b7p5}, + {0x1.3fffffffffda1p-130, -0x1.384bc11c5b4cap5}, + {0x1.4p-130, -0x1.384bc11c5b4c3p5}, + {0x1.3ffffffffed15p-129, -0x1.35e33eb247604p5}, + {0x1.3ffffffffff6ep-129, -0x1.35e33eb2475dp5}, + {0x1.4p-129, -0x1.35e33eb2475cfp5}, + {0x1.3ffffffffdd9dp-128, -0x1.337abc483373bp5}, + {0x1.3fffffffffd46p-128, -0x1.337abc48336e2p5}, + {0x1.4p-128, -0x1.337abc48336dbp5}, + {0x1.3fffffffffdffp-127, -0x1.311239de1f7ecp5}, + {0x1.4p-127, -0x1.311239de1f7e7p5}, + {0x1.3fffffffff391p-126, -0x1.2ea9b7740b916p5}, + {0x1.3ffffffffff7p-126, -0x1.2ea9b7740b8f4p5}, + {0x1.4p-126, -0x1.2ea9b7740b8f3p5}, + {0x1.3ffffffffff71p-125, -0x1.2c413509f7ap5}, + {0x1.4p-125, -0x1.2c413509f79ffp5}, + {0x1.3fffffffffc91p-124, -0x1.29d8b29fe3b14p5}, + {0x1.4p-124, -0x1.29d8b29fe3b0bp5}, + {0x1.3fffffffffd4ap-123, -0x1.27703035cfc1ep5}, + {0x1.4p-123, -0x1.27703035cfc17p5}, + {0x1.3fffffffffe03p-122, -0x1.2507adcbbbd28p5}, + {0x1.4p-122, -0x1.2507adcbbbd23p5}, + {0x1.3fffffffffebcp-121, -0x1.229f2b61a7e32p5}, + {0x1.4p-121, -0x1.229f2b61a7e2fp5}, + {0x1.3ffffffffff19p-120, -0x1.2036a8f793f3ep5}, + {0x1.4p-120, -0x1.2036a8f793f3bp5}, + {0x1.3fffffffffd4dp-119, -0x1.1dce268d8004ep5}, + {0x1.4p-119, -0x1.1dce268d80047p5}, + {0x1.3fffffffffebep-118, -0x1.1b65a4236c156p5}, + {0x1.4p-118, -0x1.1b65a4236c153p5}, + {0x1.3ffffffffff77p-117, -0x1.18fd21b95826p5}, + {0x1.4p-117, -0x1.18fd21b95825fp5}, + {0x1.3ffffffffffd4p-116, -0x1.16949f4f4436bp5}, + {0x1.4p-116, -0x1.16949f4f4436bp5}, + {0x1.3fffffffffe08p-115, -0x1.142c1ce53047cp5}, + {0x1.4p-115, -0x1.142c1ce530477p5}, + {0x1.3fffffffffe09p-114, -0x1.11c39a7b1c588p5}, + {0x1.4p-114, -0x1.11c39a7b1c583p5}, + {0x1.3fffffffffec2p-113, -0x1.0f5b181108692p5}, + {0x1.4p-113, -0x1.0f5b18110868fp5}, + {0x1.3ffffffffff7bp-112, -0x1.0cf295a6f479cp5}, + {0x1.4p-112, -0x1.0cf295a6f479bp5}, + {0x1.3ffffffffffd8p-111, -0x1.0a8a133ce08a8p5}, + {0x1.4p-111, -0x1.0a8a133ce08a7p5}, + {0x1.3fffffffffa73p-110, -0x1.082190d2cc9c2p5}, + {0x1.4p-110, -0x1.082190d2cc9b3p5}, + {0x1.3fffffffffec5p-109, -0x1.05b90e68b8ac2p5}, + {0x1.4p-109, -0x1.05b90e68b8abfp5}, + {0x1.3ffffffffedddp-108, -0x1.03508bfea4bfep5}, + {0x1.3ffffffffff7ep-108, -0x1.03508bfea4bccp5}, + {0x1.4p-108, -0x1.03508bfea4bcbp5}, + {0x1.3ffffffffde65p-107, -0x1.00e8099490d35p5}, + {0x1.3fffffffffe0ep-107, -0x1.00e8099490cdcp5}, + {0x1.4p-107, -0x1.00e8099490cd7p5}, + {0x1.3ffffffffed3dp-106, -0x1.fcff0e54f9c2fp4}, + {0x1.3fffffffffe82p-106, -0x1.fcff0e54f9bcep4}, + {0x1.4p-106, -0x1.fcff0e54f9bc6p4}, + {0x1.3fffffffffff3p-105, -0x1.f82e0980d1ddep4}, + {0x1.4p-105, -0x1.f82e0980d1ddep4}, + {0x1.3ffffffffff98p-104, -0x1.f35d04aca9ff8p4}, + {0x1.4p-104, -0x1.f35d04aca9ff6p4}, + {0x1.3ffffffffe3b7p-103, -0x1.ee8bffd8822abp4}, + {0x1.3ffffffffffc7p-103, -0x1.ee8bffd88221p4}, + {0x1.4p-103, -0x1.ee8bffd88220ep4}, + {0x1.3fffffffffdcdp-102, -0x1.e9bafb045a432p4}, + {0x1.4p-102, -0x1.e9bafb045a426p4}, + {0x1.3ffffffffff3ep-101, -0x1.e4e9f63032642p4}, + {0x1.4p-101, -0x1.e4e9f6303263ep4}, + {0x1.3ffffffffe301p-100, -0x1.e018f15c0a8f8p4}, + {0x1.3fffffffffff7p-100, -0x1.e018f15c0a856p4}, + {0x1.4p-100, -0x1.e018f15c0a856p4}, + {0x1.3fffffffffd73p-99, -0x1.db47ec87e2a7cp4}, + {0x1.4p-99, -0x1.db47ec87e2a6ep4}, + {0x1.3ffffffffdd9dp-98, -0x1.d676e7b3bad46p4}, + {0x1.3fffffffffee4p-98, -0x1.d676e7b3bac8cp4}, + {0x1.4p-98, -0x1.d676e7b3bac86p4}, + {0x1.3ffffffffff9dp-97, -0x1.d1a5e2df92eap4}, + {0x1.4p-97, -0x1.d1a5e2df92e9ep4}, + {0x1.3fffffffffffap-96, -0x1.ccd4de0b6b0b6p4}, + {0x1.4p-96, -0x1.ccd4de0b6b0b6p4}, + {0x1.3ffffffffffcdp-95, -0x1.c803d937432dp4}, + {0x1.4p-95, -0x1.c803d937432cep4}, + {0x1.3ffffffffffcep-94, -0x1.c332d4631b4e8p4}, + {0x1.4p-94, -0x1.c332d4631b4e6p4}, + {0x1.3fffffffffe8cp-93, -0x1.be61cf8ef3706p4}, + {0x1.4p-93, -0x1.be61cf8ef36fep4}, + {0x1.3fffffffff983p-92, -0x1.b990cabacb93ap4}, + {0x1.3ffffffffff45p-92, -0x1.b990cabacb91ap4}, + {0x1.4p-92, -0x1.b990cabacb916p4}, + {0x1.3fffffffffffep-91, -0x1.b4bfc5e6a3b2ep4}, + {0x1.4p-91, -0x1.b4bfc5e6a3b2ep4}, + {0x1.3fffffffffdd6p-90, -0x1.afeec1127bd52p4}, + {0x1.4p-90, -0x1.afeec1127bd46p4}, + {0x1.3fffffffffeebp-89, -0x1.ab1dbc3e53f64p4}, + {0x1.4p-89, -0x1.ab1dbc3e53f5ep4}, + {0x1.3ffffffffffa4p-88, -0x1.a64cb76a2c178p4}, + {0x1.4p-88, -0x1.a64cb76a2c177p4}, + {0x1.3fffffffffa9bp-87, -0x1.a17bb296043acp4}, + {0x1.3fffffffffd7cp-87, -0x1.a17bb2960439cp4}, + {0x1.4p-87, -0x1.a17bb2960438fp4}, + {0x1.3fffffffffe91p-86, -0x1.9caaadc1dc5aep4}, + {0x1.3ffffffffffc5p-86, -0x1.9caaadc1dc5a8p4}, + {0x1.3fffffffffe36p-85, -0x1.97d9a8edb47c8p4}, + {0x1.3ffffffffffa7p-84, -0x1.9308a4198c9d8p4}, + {0x1.3ffffffffff7ap-83, -0x1.8e379f4564bf2p4}, + {0x1.3ffffffffffd7p-82, -0x1.89669a713ce08p4}, + {0x1.3fffffffffe95p-81, -0x1.8495959d15026p4}, + {0x1.3ffffffffff4ep-80, -0x1.7fc490c8ed23ap4}, + {0x1.3ffffffffeafbp-79, -0x1.7af38bf4c54c3p4}, + {0x1.3ffffffffffd9p-79, -0x1.7af38bf4c544fp4}, + {0x1.3fffffffffe3bp-78, -0x1.762287209d67p4}, + {0x1.3ffffffffde65p-77, -0x1.7151824c7593ap4}, + {0x1.3fffffffffef4p-77, -0x1.7151824c75884p4}, + {0x1.3ffffffffffadp-76, -0x1.6c807d784da98p4}, + {0x1.3fffffffffb8bp-75, -0x1.67af78a425cc7p4}, + {0x1.3ffffffffffaep-75, -0x1.67af78a425cbp4}, + {0x1.3ffffffffffddp-74, -0x1.62de73cffdec8p4}, + {0x1.3fffffffffe3fp-73, -0x1.5e0d6efbd60e8p4}, + {0x1.3ffffffffff54p-72, -0x1.593c6a27ae2fap4}, + {0x1.3ffffffffffb1p-71, -0x1.546b65538651p4}, + {0x1.3fffffffff571p-70, -0x1.4f9a607f5e762p4}, + {0x1.3fffffffffde5p-70, -0x1.4f9a607f5e732p4}, + {0x1.3fffffffffe9ep-69, -0x1.4ac95bab36946p4}, + {0x1.3ffffffffffb3p-68, -0x1.45f856d70eb58p4}, + {0x1.3ffffffffe1d7p-67, -0x1.41275202e6e16p4}, + {0x1.3ffffffffffb4p-67, -0x1.41275202e6d7p4}, + {0x1.3fffffffffe44p-66, -0x1.3c564d2ebef9p4}, + {0x1.3fffffffffd5fp-65, -0x1.3785485a971aep4}, + {0x1.3fffffffffaadp-64, -0x1.32b443866f3d5p4}, + {0x1.3fffffffffefep-64, -0x1.32b443866f3bcp4}, + {0x1.3ffffffffeb35p-63, -0x1.2de33eb247643p4}, + {0x1.3ffffffffffb7p-63, -0x1.2de33eb2475dp4}, + {0x1.3ffffffffffe6p-62, -0x1.291239de1f7e8p4}, + {0x1.3fffffffffdecp-61, -0x1.24413509f7a0ap4}, + {0x1.3ffffffffff5dp-60, -0x1.1f703035cfc1ap4}, + {0x1.3ffffffffffbap-59, -0x1.1a9f2b61a7e3p4}, + {0x1.3fffffffffd92p-58, -0x1.15ce268d80054p4}, + {0x1.3ffffffffff03p-57, -0x1.10fd21b958264p4}, + {0x1.3ffffffffe6e9p-56, -0x1.0c2c1ce530503p4}, + {0x1.3ffffffffffbcp-56, -0x1.0c2c1ce530478p4}, + {0x1.3ffffffffe2c7p-55, -0x1.075b181108731p4}, + {0x1.3ffffffffff61p-55, -0x1.075b181108692p4}, + {0x1.3ffffffffffecp-54, -0x1.028a133ce08a8p4}, + {0x1.3fffffffff14fp-53, -0x1.fb721cd171621p3}, + {0x1.3fffffffffff8p-53, -0x1.fb721cd17157ep3}, + {0x1.3ffffffffdd9dp-52, -0x1.f1d0132921b2dp3}, + {0x1.3ffffffffffe2p-52, -0x1.f1d01329219bp3}, + {0x1.3ffffffffebebp-51, -0x1.e82e0980d1ebdp3}, + {0x1.3fffffffffe2dp-51, -0x1.e82e0980d1df2p3}, + {0x1.3ffffffffff7p-50, -0x1.de8bffd882214p3}, + {0x1.3fffffffffaadp-49, -0x1.d4e9f6303267ap3}, + {0x1.3ffffffffffcdp-49, -0x1.d4e9f6303264p3}, + {0x1.3fffffffffd77p-48, -0x1.cb47ec87e2a8ap3}, + {0x1.3fffffffffda5p-48, -0x1.cb47ec87e2a89p3}, + {0x1.3ffffffffff16p-47, -0x1.c1a5e2df92ea8p3}, + {0x1.3fffffffff983p-46, -0x1.b803d93743316p3}, + {0x1.3ffffffffffcfp-46, -0x1.b803d937432dp3}, + {0x1.3ffffffffffa2p-45, -0x1.ae61cf8ef3702p3}, + {0x1.3fffffffffbc5p-44, -0x1.a4bfc5e6a3b5ep3}, + {0x1.3ffffffffffffp-44, -0x1.a4bfc5e6a3b2ep3}, + {0x1.3fffffffffdd7p-43, -0x1.9b1dbc3e53f76p3}, + {0x1.3fffffffffebep-42, -0x1.917bb2960439cp3}, + {0x1.3ffffffffe3f1p-41, -0x1.87d9a8edb48f7p3}, + {0x1.3ffffffffff77p-41, -0x1.87d9a8edb47c4p3}, + {0x1.3fffffffff23fp-40, -0x1.7e379f4564c87p3}, + {0x1.3ffffffffffbdp-40, -0x1.7e379f4564bf2p3}, + {0x1.3fffffffffe36p-39, -0x1.7495959d15032p3}, + {0x1.3ffffffffecdbp-38, -0x1.6af38bf4c5523p3}, + {0x1.3ffffffffffa7p-38, -0x1.6af38bf4c5452p3}, + {0x1.3ffffffffffd6p-37, -0x1.6151824c7588p3}, + {0x1.3ffffffffffeep-36, -0x1.57af78a425cafp3}, + {0x1.3ffffffffdcadp-35, -0x1.4e0d6efbd6268p3}, + {0x1.3ffffffffffefp-35, -0x1.4e0d6efbd60ep3}, + {0x1.3fffffffffe68p-34, -0x1.446b65538652p3}, + {0x1.3ffffffffeafbp-33, -0x1.3ac95bab36a28p3}, + {0x1.3ffffffffffd9p-33, -0x1.3ac95bab3694p3}, + {0x1.3ffffffffffdap-32, -0x1.31275202e6d7p3}, + {0x1.3fffffffffcb5p-31, -0x1.2785485a971c4p3}, + {0x1.3ffffffffffc4p-31, -0x1.2785485a971a2p3}, + {0x1.3fffffffffec7p-30, -0x1.1de33eb2475dcp3}, + {0x1.3ffffffffffaep-29, -0x1.14413509f7a02p3}, + {0x1.3ffffffffd9a3p-28, -0x1.0a9f2b61a7fd9p3}, + {0x1.3ffffffffffddp-28, -0x1.0a9f2b61a7e3p3}, + {0x1.3fffffffff32fp-27, -0x1.00fd21b9582edp3}, + {0x1.3fffffffffe6dp-27, -0x1.00fd21b95827p3}, + {0x1.3ffffffffffe4p-26, -0x1.eeb6302210d2p2}, + {0x1.3ffffffffeb35p-25, -0x1.db721cd17174dp2}, + {0x1.3fffffffffffcp-25, -0x1.db721cd17157ep2}, + {0x1.3ffffffffde65p-24, -0x1.c82e0980d20cap2}, + {0x1.3fffffffffeafp-24, -0x1.c82e0980d1dfcp2}, + {0x1.3ffffffffed3dp-23, -0x1.b4e9f630327ep2}, + {0x1.3ffffffffff7fp-23, -0x1.b4e9f6303264ap2}, + {0x1.3ffffffffffdcp-22, -0x1.a1a5e2df92ea2p2}, + {0x1.3ffffffffe91bp-21, -0x1.8e61cf8ef38fbp2}, + {0x1.3ffffffffffffp-21, -0x1.8e61cf8ef36fep2}, + {0x1.3fffffffffeb2p-20, -0x1.7b1dbc3e53f7bp2}, + {0x1.3ffffffffe3b7p-19, -0x1.67d9a8edb4a33p2}, + {0x1.3ffffffffff3dp-19, -0x1.67d9a8edb47dp2}, + {0x1.3ffffffffe6e9p-18, -0x1.5495959d1524dp2}, + {0x1.3fffffffffff6p-18, -0x1.5495959d1502p2}, + {0x1.3ffffffffdb5bp-17, -0x1.4151824c75badp2}, + {0x1.3ffffffffffebp-17, -0x1.4151824c7588p2}, + {0x1.3ffffffffe301p-16, -0x1.2e0d6efbd6364p2}, + {0x1.3ffffffffff11p-16, -0x1.2e0d6efbd60f3p2}, + {0x1.3fffffffff14fp-15, -0x1.1ac95bab36a85p2}, + {0x1.3ffffffffff57p-15, -0x1.1ac95bab3694ep2}, + {0x1.3fffffffff481p-14, -0x1.0785485a9729fp2}, + {0x1.3fffffffffff9p-14, -0x1.0785485a971ap2}, + {0x1.3fffffffff571p-13, -0x1.e8826a13ef5d4p1}, + {0x1.3fffffffffff1p-13, -0x1.e8826a13ef4p1}, + {0x1.3fffffffffc7bp-12, -0x1.c1fa4372b055ap1}, + {0x1.3ffffffffffcfp-12, -0x1.c1fa4372b04c6p1}, + {0x1.3fffffffff189p-11, -0x1.9b721cd171802p1}, + {0x1.3fffffffffffep-11, -0x1.9b721cd17157ep1}, + {0x1.3ffffffffe211p-10, -0x1.74e9f63032b72p1}, + {0x1.3fffffffffff3p-10, -0x1.74e9f6303264p1}, + {0x1.3fffffffffbc5p-9, -0x1.4e61cf8ef37bbp1}, + {0x1.3fffffffffff4p-9, -0x1.4e61cf8ef37p1}, + {0x1.3fffffffff391p-8, -0x1.27d9a8edb49e8p1}, + {0x1.3ffffffffffe9p-8, -0x1.27d9a8edb47c2p1}, + {0x1.3fffffffffaadp-7, -0x1.0151824c7596cp1}, + {0x1.3ffffffffffeap-7, -0x1.0151824c75882p1}, + {0x1.3fffffffffc7bp-6, -0x1.b592b7566d3b6p0}, + {0x1.3fffffffffff2p-6, -0x1.b592b7566d282p0}, + {0x1.3fffffffffda5p-5, -0x1.68826a13ef4dp0}, + {0x1.3fffffffffff6p-5, -0x1.68826a13ef402p0}, + {0x1.3fffffffffb8bp-4, -0x1.1b721cd17170ap0}, + {0x1.3ffffffffffffp-4, -0x1.1b721cd17157ep0}, + {0x1.3fffffffffcb5p-3, -0x1.9cc39f1de7047p-1}, + {0x1.3fffffffffff2p-3, -0x1.9cc39f1de6e06p-1}, + {0x1.3fffffffffc7bp-2, -0x1.02a30498eb36fp-1}, + {0x1.4p-2, -0x1.02a30498eb0fep-1}, + {0x1.3fffffffffda5p-1, -0x1.a209a84fbd684p-3}, + {0x1.3fffffffffffcp-1, -0x1.a209a84fbd002p-3}, + {0x1.3fffffffffff3p0, 0x1.8cf18388647c5p-4}, + {0x1.3fffffffffffdp0, 0x1.8cf18388647fbp-4}, + {0x1.3ffffffffff7bp1, 0x1.977d95ec10b4ap-2}, + {0x1.3fffffffffffcp1, 0x1.977d95ec10bfcp-2}, + {0x1.3ffffffffff2bp2, 0x1.65df657b0426dp-1}, + {0x1.3fffffffffff3p2, 0x1.65df657b042f8p-1}, + {0x1.3fffffffffc83p4, 0x1.4d104d427dd4ap0}, + {0x1.3fffffffffff1p4, 0x1.4d104d427de7ap0}, + {0x1.4p4, 0x1.4d104d427de8p0}, + {0x1.3ffffffffff2bp5, 0x1.9a209a84fbcb6p0}, + {0x1.4p5, 0x1.9a209a84fbdp0}, + {0x1.3fffffffffd23p6, 0x1.e730e7c779a81p0}, + {0x1.3fffffffffffep6, 0x1.e730e7c779b7ep0}, + {0x1.4p6, 0x1.e730e7c779b7fp0}, + {0x1.3ffffffffece3p7, 0x1.1a209a84fb9aep1}, + {0x1.4p7, 0x1.1a209a84fbdp1}, + {0x1.3fffffffffeb3p8, 0x1.40a8c1263ac06p1}, + {0x1.3ffffffffff71p8, 0x1.40a8c1263ac26p1}, + {0x1.4p8, 0x1.40a8c1263ac3fp1}, + {0x1.3fffffffffe3bp9, 0x1.6730e7c779b31p1}, + {0x1.3fffffffffffcp9, 0x1.6730e7c779b7ep1}, + {0x1.4p9, 0x1.6730e7c779b7fp1}, + {0x1.3fffffffff657p10, 0x1.8db90e68b8912p1}, + {0x1.3ffffffffff67p10, 0x1.8db90e68b8aa4p1}, + {0x1.4p10, 0x1.8db90e68b8abfp1}, + {0x1.3fffffffff8ffp11, 0x1.b4413509f78c8p1}, + {0x1.3ffffffffffecp11, 0x1.b4413509f79fcp1}, + {0x1.4p11, 0x1.b4413509f79ffp1}, + {0x1.3fffffffffd23p12, 0x1.dac95bab368cp1}, + {0x1.3ffffffffff5dp12, 0x1.dac95bab36922p1}, + {0x1.4p12, 0x1.dac95bab3693fp1}, + {0x1.3fffffffffe13p13, 0x1.00a8c1263ac15p2}, + {0x1.3fffffffffee2p13, 0x1.00a8c1263ac26p2}, + {0x1.4p13, 0x1.00a8c1263ac3fp2}, + {0x1.3fffffffff193p14, 0x1.13ecd476da29fp2}, + {0x1.3ffffffffffc9p14, 0x1.13ecd476da3dap2}, + {0x1.4p14, 0x1.13ecd476da3dfp2}, + {0x1.3fffffffff5b7p15, 0x1.2730e7c779a9bp2}, + {0x1.3ffffffffff1dp15, 0x1.2730e7c779b6cp2}, + {0x1.4p15, 0x1.2730e7c779b7fp2}, + {0x1.3ffffffffec2fp16, 0x1.3a74fb1819167p2}, + {0x1.3ffffffffffedp16, 0x1.3a74fb181931ep2}, + {0x1.4p16, 0x1.3a74fb181931fp2}, + {0x1.3fffffffffb07p17, 0x1.4db90e68b8a51p2}, + {0x1.3fffffffffecep17, 0x1.4db90e68b8aa4p2}, + {0x1.4p17, 0x1.4db90e68b8abfp2}, + {0x1.3ffffffffff2bp18, 0x1.60fd21b95824dp2}, + {0x1.3ffffffffffb5p18, 0x1.60fd21b958258p2}, + {0x1.4p18, 0x1.60fd21b95825fp2}, + {0x1.3ffffffffffe4p19, 0x1.74413509f79fcp2}, + {0x1.4p19, 0x1.74413509f79ffp2}, + {0x1.3fffffffff6cfp20, 0x1.8785485a970d3p2}, + {0x1.3ffffffffffd9p20, 0x1.8785485a9719cp2}, + {0x1.4p20, 0x1.8785485a9719fp2}, + {0x1.3ffffffffed47p21, 0x1.9ac95bab3679fp2}, + {0x1.3fffffffffebap21, 0x1.9ac95bab36922p2}, + {0x1.4p21, 0x1.9ac95bab3693fp2}, + {0x1.3fffffffff16bp22, 0x1.ae0d6efbd5f9bp2}, + {0x1.3ffffffffff8ap22, 0x1.ae0d6efbd60d4p2}, + {0x1.4p22, 0x1.ae0d6efbd60dfp2}, + {0x1.3ffffffffe667p23, 0x1.c151824c75646p2}, + {0x1.3fffffffffffep23, 0x1.c151824c7587ep2}, + {0x1.4p23, 0x1.c151824c7587fp2}, + {0x1.3fffffffffff3p24, 0x1.d495959d1501ep2}, + {0x1.4p24, 0x1.d495959d1501fp2}, + {0x1.3fffffffffadfp25, 0x1.e7d9a8edb474dp2}, + {0x1.3fffffffffebdp25, 0x1.e7d9a8edb47a2p2}, + {0x1.4p25, 0x1.e7d9a8edb47bfp2}, + }; + + for (double[] testCase: testCases) + failures+=testLog10Case(testCase[0], testCase[1]); + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testLog10(); + + if (failures > 0) { + System.err.println("Testing log10 incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/Log1pTests.java b/jdk/test/java/lang/StrictMath/Log1pTests.java new file mode 100644 index 00000000000..03b31f649d1 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/Log1pTests.java @@ -0,0 +1,210 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851638 + * @summary Tests for StrictMath.log1p + * @author Joseph D. Darcy + */ + +/** + * The tests in ../Math/Log1pTests.java test properties that should + * hold for any log1p implementation, including the FDLIBM-based one + * required for StrictMath.log1p. Therefore, the test cases in + * ../Math/Log1pTests.java are run against both the Math and + * StrictMath versions of log1p. The role of this test is to verify + * that the FDLIBM log1p algorithm is being used by running golden + * file tests on values that may vary from one conforming log1p + * implementation to another. + */ + +public class Log1pTests { + private Log1pTests(){} + + static int testLog1pCase(double input, double expected) { + return Tests.test("StrictMath.log1p(double)", input, + StrictMath.log1p(input), expected); + } + + static int testLog1p() { + int failures = 0; + + double [][] testCases = { + {0x1.fffffffffffffp-54, 0x1.fffffffffffffp-54}, + {0x1.fffffffffcc48p-15, 0x1.fffc000aa74f3p-15}, + {0x1.ffffffffff224p-14, 0x1.fff8002aa8ccfp-14}, + {0x1.ffffffffff90cp-13, 0x1.fff000aaa23bdp-13}, + {0x1.fffffffffffcep-4, 0x1.e27076e2af2bap-4}, + {0x1.fffffffffffffp-2, 0x1.9f323ecbf984bp-2}, + {0x1.ffffffffffffdp-1, 0x1.62e42fefa39eep-1}, + {0x1.0p1, 0x1.193ea7aad030ap0}, + {0x1.ffffffffffffbp1, 0x1.9c041f7ed8d31p0}, + {0x1.fffffffffffffp2, 0x1.193ea7aad030ap1}, + {0x1.fffffffffffe1p3, 0x1.6aa6bc1fa7f73p1}, + {0x1.fffffffffffe1p4, 0x1.bf8d8f4d5b8cap1}, + {0x1.ffffffffffff1p5, 0x1.0b29293942974p2}, + {0x1.fffffffffff41p6, 0x1.37072a9b5b6b4p2}, + {0x1.ffffffffffe65p7, 0x1.63241004e8fdep2}, + {0x1.ffffffffffca1p8, 0x1.8f60adf041b73p2}, + {0x1.fffffffffffffp9, 0x1.bbad39ebe1ccp2}, + {0x1.fffffffffffffp10, 0x1.e801c1698ba43p2}, + {0x1.ffffffffff2dep11, 0x1.0a2d23e3bb54bp3}, + {0x1.ffffffffff18dp12, 0x1.205a66eeb4f81p3}, + {0x1.ffffffffffff9p13, 0x1.368829f0af2dcp3}, + {0x1.fffffffffbc1ep14, 0x1.4cb62cf069217p3}, + {0x1.ffffffffffff5p16, 0x1.791282ee99d8ep3}, + {0x1.fffffffffba46p17, 0x1.8f40bded96cd1p3}, + {0x1.ffffffffffff7p18, 0x1.a56efcec920cbp3}, + {0x1.ffffffffffff7p19, 0x1.bb9d3deb8c76ap3}, + {0x1.ffffffffffff9p20, 0x1.d1cb7fea86bcap3}, + {0x1.ffffffffffff7p24, 0x1.1542457b37d42p4}, + {0x1.fffffffffffe7p29, 0x1.4cb5ecf0e964fp4}, + {0x1.ffffffffffff9p30, 0x1.57cd0e704682p4}, + {0x1.ffffffffffffbp34, 0x1.8429946e1cf5dp4}, + {0x1.fffffffffffedp35, 0x1.8f40b5ed9912dp4}, + {0x1.fffffffffffefp39, 0x1.bb9d3beb8c96ap4}, + {0x1.fffffffffffe1p40, 0x1.c6b45d6b09abap4}, + {0x1.fffffffffffe3p44, 0x1.f310e368fe17fp4}, + {0x1.ffffffffffff5p45, 0x1.fe2804e87b34cp4}, + {0x1.fffffffffffc5p66, 0x1.7386e22edf4a5p5}, + {0x1.fffffffffff98p90, 0x1.f89c7428bca5fp5}, + {0x1.a36e2eb1c317dp-14, 0x1.a368d0657ee51p-14}, + {0x1.0624dd2f18d5cp-10, 0x1.060354f8c2226p-10}, + {0x1.ffffffffffffdp-1, 0x1.62e42fefa39eep-1}, + {0x1.8ffffffffffccp6, 0x1.275e2271bba28p2}, + {0x1.f3fffffffff1p9, 0x1.ba2909ce4f846p2}, + {0x1.387ffffffffa8p13, 0x1.26bbed6fbd838p3}, + {0x1.869ffffffffe4p16, 0x1.7069f7a2d94f4p3}, + {0x1.e847fffffff3ep19, 0x1.ba18abb1dedbcp3}, + {0x1.312cfffffff23p23, 0x1.01e3b85ec299p4}, + {0x1.7d783ffffff17p26, 0x1.26bb1bbe0482ap4}, + {0x1.dcd64ffffffcep29, 0x1.4b927f3304b3ap4}, + {0x1.2a05f1ffffa3p33, 0x1.7069e2aa317fep4}, + {0x1.74876e7ffffbep36, 0x1.9541462195ffap4}, + {0x1.d1a94a1fffddp39, 0x1.ba18a999000a6p4}, + {0x1.2309ce53ffed2p43, 0x1.def00d106aa4ep4}, + {0x1.6bcc41e8ffe73p46, 0x1.01e3b843eaa6cp5}, + {0x1.c6bf52633fe7dp49, 0x1.144f69ff9ffbep5}, + {0x1.1c37937e07fffp53, 0x1.26bb1bbb55515p5}, + {0x1.6345785d89f12p56, 0x1.3926cd770aa62p5}, + {0x1.bc16d674ec76ap59, 0x1.4b927f32bffb6p5}, + {0x1.158e460913c51p63, 0x1.5dfe30ee75504p5}, + {0x1.5af1d78b58badp66, 0x1.7069e2aa2aa58p5}, + {0x1.b1ae4d6e2ecd4p69, 0x1.82d59465dffap5}, + {0x1.0f0cf064dd066p73, 0x1.95414621954d6p5}, + {0x1.52d02c7e14a9p76, 0x1.a7acf7dd4aa4cp5}, + {0x1.a784379d99c19p79, 0x1.ba18a998fff98p5}, + {0x1.08b2a2c27fb5p83, 0x1.cc845b54b54bap5}, + {0x1.4adf4b7320322p86, 0x1.def00d106aa42p5}, + {0x1.9d971e4fe7b91p89, 0x1.f15bbecc1ff6ap5}, + {0x1.027e72f1f0ea3p93, 0x1.01e3b843eaa63p6}, + {0x1.431e0fae6d44bp96, 0x1.0b199121c5512p6}, + {0x1.93e5939a086bcp99, 0x1.144f69ff9ffb4p6}, + {0x1.f8def8808ac86p102, 0x1.1d8542dd7aa65p6}, + {0x1.3b8b5b5056dc7p106, 0x1.26bb1bbb55514p6}, + {0x1.8a6e32246c76cp109, 0x1.2ff0f4992ffb8p6}, + {0x1.ed09bead86a07p112, 0x1.3926cd770aa41p6}, + {0x1.3426172c74d33p116, 0x1.425ca654e550ep6}, + {0x1.812f9cf791f1ep119, 0x1.4b927f32bffb4p6}, + {0x1.e17b8435758f2p122, 0x1.54c858109aa3ep6}, + {0x1.2ced32a169cfap126, 0x1.5dfe30ee754fap6}, + {0x1.78287f49c497cp129, 0x1.673409cc4ffbp6}, + {0x1.d6329f1c3492ep132, 0x1.7069e2aa2aa3p6}, + {0x1.25dfa371a14b8p136, 0x1.799fbb88054f2p6}, + {0x1.6f578c4e09f0ap139, 0x1.82d59465dffa8p6}, + {0x1.cb2d6f618c4b4p142, 0x1.8c0b6d43baa4cp6}, + {0x1.1efc659cf77abp146, 0x1.95414621954eap6}, + {0x1.66bb7f0435c5bp149, 0x1.9e771eff6ffa6p6}, + {0x1.c06a5ec5428a4p152, 0x1.a7acf7dd4aa36p6}, + {0x1.18427b3b49fc9p156, 0x1.b0e2d0bb254f6p6}, + {0x1.5e531a0a1c729p159, 0x1.ba18a998fff9cp6}, + {0x1.b5e7e08ca3686p162, 0x1.c34e8276daa4p6}, + {0x1.11b0ec57e6492p166, 0x1.cc845b54b54f2p6}, + {0x1.561d276ddfd7dp169, 0x1.d5ba34328ff9ap6}, + {0x1.aba471495757bp172, 0x1.def00d106aa3p6}, + {0x1.0b46c6cdd6a8ep176, 0x1.e825e5ee454ddp6}, + {0x1.4e1878814c5f4p179, 0x1.f15bbecc1ff88p6}, + {0x1.a19e96a19f65ap182, 0x1.fa9197a9faa2ep6}, + {0x1.05031e2503cfcp186, 0x1.01e3b843eaa71p7}, + {0x1.4643e5ae441d2p189, 0x1.067ea4b2d7fb6p7}, + {0x1.97d4df19d5c5dp192, 0x1.0b199121c5516p7}, + {0x1.fdca16e04ae24p195, 0x1.0fb47d90b2a65p7}, + {0x1.3e9e4e4c2f2dap199, 0x1.144f69ff9ffc4p7}, + {0x1.8e45e1df3ac31p202, 0x1.18ea566e8d514p7}, + {0x1.f1d75a5709306p205, 0x1.1d8542dd7aa63p7}, + {0x1.372698766608cp209, 0x1.22202f4c67fcp7}, + {0x1.84f03e93fef5p212, 0x1.26bb1bbb55508p7}, + {0x1.e62c4e38fdba1p215, 0x1.2b56082a42a4bp7}, + {0x1.2fdbb0e39f6b8p219, 0x1.2ff0f4992ffb6p7}, + {0x1.7bd29d1c875a2p222, 0x1.348be1081d50cp7}, + {0x1.dac74463a76e9p225, 0x1.3926cd770aa42p7}, + {0x1.28bc8abe48f57p229, 0x1.3dc1b9e5f7fap7}, + {0x1.72ebad6ddc67ep232, 0x1.425ca654e550ep7}, + {0x1.cfa698c952a3ap235, 0x1.46f792c3d2a53p7}, + {0x1.21c81f7dd42b1p239, 0x1.4b927f32bffb6p7}, + {0x1.6a3a275d4926bp242, 0x1.502d6ba1ad50ap7}, + {0x1.c4c8b134970ddp245, 0x1.54c858109aa0ep7}, + {0x1.61bcca711985dp252, 0x1.5dfe30ee75508p7}, + {0x1.ba2bfd0d5fe2ap255, 0x1.62991d5d62a5cp7}, + {0x1.59725db2728b7p262, 0x1.6bcef63b3d4fcp7}, + {0x1.afcef51f0fa33p265, 0x1.7069e2aa2aa5ap7}, + {0x1.0de1593368f8cp269, 0x1.7504cf1917f95p7}, + {0x1.5159af804425ep272, 0x1.799fbb88055p7}, + {0x1.a5b01b605409p275, 0x1.7e3aa7f6f2a3ep7}, + {0x1.078e111c34e5bp279, 0x1.82d59465dff9fp7}, + {0x1.497195634225fp282, 0x1.877080d4cd4f4p7}, + {0x1.9bcdfabc13053p285, 0x1.8c0b6d43baa4ep7}, + {0x1.0160bcb58c08cp289, 0x1.90a659b2a7fa7p7}, + {0x1.41b8ebe2eec13p292, 0x1.95414621954f4p7}, + {0x1.922726dbaa542p295, 0x1.99dc329082a46p7}, + {0x1.f6b0f09295714p298, 0x1.9e771eff6ffa3p7}, + {0x1.3a2e965b9d0b2p302, 0x1.a3120b6e5d4eep7}, + {0x1.88ba3bf284dd1p305, 0x1.a7acf7dd4aa4ep7}, + {0x1.32d17ed576f35p312, 0x1.b0e2d0bb254ep7}, + {0x1.7f85de8ad56bep315, 0x1.b57dbd2a12a44p7}, + {0x1.df67562d87c5cp318, 0x1.ba18a998fff65p7}, + {0x1.2ba095dc76db7p322, 0x1.beb39607ed4fp7}, + {0x1.7688bb5394bd3p325, 0x1.c34e8276daa48p7}, + {0x1.d42aea2878b45p328, 0x1.c7e96ee5c7f87p7}, + {0x1.249ad2594989p332, 0x1.cc845b54b54a6p7}, + }; + + for (double[] testCase: testCases) + failures+=testLog1pCase(testCase[0], testCase[1]); + + return failures; + } + + public static void main(String [] argv) { + int failures = 0; + + failures += testLog1p(); + + if (failures > 0) { + System.err.println("Testing log1p incurred " + + failures + " failures."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/lang/StrictMath/Tests.java b/jdk/test/java/lang/StrictMath/Tests.java new file mode 100644 index 00000000000..268fc0613c5 --- /dev/null +++ b/jdk/test/java/lang/StrictMath/Tests.java @@ -0,0 +1,65 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * + * + * Shared static test method for StrictMath tests. + */ + + +public class Tests { + private Tests(){} + + static int test(String testName, + double input, + double result, + double expected) { + if (Double.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input + "\t(" + Double.toHexString(input) + ")\n" + + "\texpected " + expected + "\t(" + Double.toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + Double.toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + static int test(String testName, double input1, double input2, + double result, double expected) { + if (Double.compare(expected, result ) != 0) { + System.err.println("Failure for " + testName + ":\n" + + "\tFor input " + input1 + "\t(" + Double.toHexString(input1) + "), " + + + input2 + "\t(" + Double.toHexString(input2) + ")\n" + + "\texpected " + expected + "\t(" + Double.toHexString(expected) + ")\n" + + "\tgot " + result + "\t(" + Double.toHexString(result) + ")."); + return 1; + } + else + return 0; + } + + + +} diff --git a/jdk/test/java/lang/ToString.java b/jdk/test/java/lang/ToString.java new file mode 100644 index 00000000000..6033368716c --- /dev/null +++ b/jdk/test/java/lang/ToString.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4031762 + * @summary Test the primitive wrappers static toString() + */ + +import java.util.Random; + +public class ToString { + + private static Random generator = new Random(); + + public static void main(String args[]) throws Exception { + // boolean wrapper + boolean b = false; + Boolean B = new Boolean(b); + if (!B.toString().equals(Boolean.toString(b))) + throw new RuntimeException("Boolean wrapper toString() failure."); + b = true; + B = new Boolean(b); + if (!B.toString().equals(Boolean.toString(b))) + throw new RuntimeException("Boolean wrapper toString() failure."); + + // char wrapper + for(int x=0; x<100; x++) { + char c = (char)generator.nextInt(); + Character C = new Character(c); + if (!C.toString().equals(Character.toString(c))) + throw new RuntimeException("Character wrapper toString() failure."); + } + + // byte wrapper + for(int x=0; x<100; x++) { + byte y = (byte)generator.nextInt(); + Byte Y = new Byte(y); + if (!Y.toString().equals(Byte.toString(y))) + throw new RuntimeException("Byte wrapper toString() failure."); + } + + // short wrapper + for(int x=0; x<100; x++) { + short s = (short)generator.nextInt(); + Short S = new Short(s); + if (!S.toString().equals(Short.toString(s))) + throw new RuntimeException("Short wrapper toString() failure."); + } + + // int wrapper + for(int x=0; x<100; x++) { + int i = generator.nextInt(); + Integer I = new Integer(i); + if (!I.toString().equals(Integer.toString(i))) + throw new RuntimeException("Integer wrapper toString() failure."); + } + + // long wrapper + for(int x=0; x<100; x++) { + long l = generator.nextLong(); + Long L = new Long(l); + if (!L.toString().equals(Long.toString(l))) + throw new RuntimeException("Long wrapper toString() failure."); + } + + // float wrapper + for(int x=0; x<100; x++) { + float f = generator.nextFloat(); + Float F = new Float(f); + if (!F.toString().equals(Float.toString(f))) + throw new RuntimeException("Float wrapper toString() failure."); + } + + // double wrapper + for(int x=0; x<100; x++) { + double d = generator.nextDouble(); + Double D = new Double(d); + if (!D.toString().equals(Double.toString(d))) + throw new RuntimeException("Double wrapper toString() failure."); + } + + } +} diff --git a/jdk/test/java/lang/annotation/AnnotationTypeMismatchException/FoundType.java b/jdk/test/java/lang/annotation/AnnotationTypeMismatchException/FoundType.java new file mode 100644 index 00000000000..b856b574a38 --- /dev/null +++ b/jdk/test/java/lang/annotation/AnnotationTypeMismatchException/FoundType.java @@ -0,0 +1,44 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6179014 + * @summary AnnotationTypeMismatchException.foundType method shouldn't loop. + * @author Scott Seligman + * @run main/timeout=30 FoundType + */ + +import java.lang.annotation.*; + +public class FoundType { + + private static final String TYPE = "a.halting.Problem"; + + public static void main(String[] args) { + AnnotationTypeMismatchException ex = + new AnnotationTypeMismatchException(null, TYPE); + if (!TYPE.equals(ex.foundType())) + throw new Error(); + } +} diff --git a/jdk/test/java/lang/annotation/Missing/A.java b/jdk/test/java/lang/annotation/Missing/A.java new file mode 100644 index 00000000000..190d4e19750 --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/A.java @@ -0,0 +1,30 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Class to have a missing annotation applied for running MissingTest. + */ +@Missing +@Marker +public class A { +} diff --git a/jdk/test/java/lang/annotation/Missing/B.java b/jdk/test/java/lang/annotation/Missing/B.java new file mode 100644 index 00000000000..9546db03a8d --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/B.java @@ -0,0 +1,31 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Class to have an indirectly missing annotation applied for for + * running MisssingTest. + */ +@MissingWrapper(@Missing) +@Marker +public class B { +} diff --git a/jdk/test/java/lang/annotation/Missing/C.java b/jdk/test/java/lang/annotation/Missing/C.java new file mode 100644 index 00000000000..55ff14dc8cb --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/C.java @@ -0,0 +1,31 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Class to have a missing annotation applied for running MissingTest. + */ +public class C { + public void method1(@Missing @Marker Object param1) { + return; + } +} diff --git a/jdk/test/java/lang/annotation/Missing/D.java b/jdk/test/java/lang/annotation/Missing/D.java new file mode 100644 index 00000000000..a3b091c841e --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/D.java @@ -0,0 +1,31 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * Class to have a missing annotation applied for running MissingTest. + */ +public class D { + public void method1(@MissingWrapper(@Missing) @Marker Object param1) { + return; + } +} diff --git a/jdk/test/java/lang/annotation/Missing/Marker.java b/jdk/test/java/lang/annotation/Missing/Marker.java new file mode 100644 index 00000000000..61f0719e88d --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/Marker.java @@ -0,0 +1,32 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.*; + +/** + * A marker annotation. Used so that at least one annotation will be + * present on the classes tested by MissingTest. + */ +@Retention(RUNTIME) +public @interface Marker {} diff --git a/jdk/test/java/lang/annotation/Missing/Missing.java b/jdk/test/java/lang/annotation/Missing/Missing.java new file mode 100644 index 00000000000..9e47adfff7e --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/Missing.java @@ -0,0 +1,32 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.*; + +/** + * The class file for this annotation type is missing when MissingTest + * is run. + */ +@Retention(RUNTIME) +public @interface Missing {} diff --git a/jdk/test/java/lang/annotation/Missing/MissingTest.java b/jdk/test/java/lang/annotation/Missing/MissingTest.java new file mode 100644 index 00000000000..e0583f278f1 --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/MissingTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6322301 + * @summary Verify when missing annotation classes cause exceptions + * @author Joseph D. Darcy + * @compile MissingTest.java A.java B.java C.java D.java Marker.java Missing.java MissingWrapper.java + * @clean Missing + * @run main MissingTest + */ + +import java.lang.reflect.*; + +/** + * This test verifies that a missing annotation class leads to the + * expected exceptional behavior; a missing directly applied + * annotation is currently ignored but a missing annotation value + * inside another annotation throws an exception. + * + * To be run as intended, the annotation type Missing should *not* be + * on the classpath when the test is run; with jtreg, it is deleted by + * the @clean directive. + */ +public class MissingTest { + /** + * For the annotated element argument, get all its annotations and + * see whether or not an exception is throw upon reading the + * annotations. Additionally, verify at least one annotation is + * present. + */ + private static void testAnnotation(AnnotatedElement element, + boolean exceptionExpected) { + java.lang.annotation.Annotation[] annotations; + try { + annotations = element.getAnnotations(); + if (exceptionExpected) { + System.err.println("Error: Did not get an exception reading annotations on " + + element); + System.err.println("Annotations found: " + + java.util.Arrays.toString(annotations)); + throw new RuntimeException(); + } + if (annotations.length == 0) { + System.err.println("Error: no annotations found on " + element); + throw new RuntimeException(); + } + } catch (Throwable t) { + if (!exceptionExpected) { + System.err.println("Error: Got an unexpected exception reading annotations on " + + element); + throw new RuntimeException(t); + } + } + } + + /** + * For the annotated element argument, get all its annotations and + * see whether or not an exception is throw upon reading the + * annotations. Additionally, verify at least one annotation is + * present. + */ + private static void testParameterAnnotation(Method m, + boolean exceptionExpected) { + java.lang.annotation.Annotation[][] annotationsArray; + try { + annotationsArray = m.getParameterAnnotations(); + if (exceptionExpected) { + System.err.println("Error: Did not get an exception reading annotations on method" + + m); + System.err.println("Annotations found: " + + java.util.Arrays.toString(annotationsArray)); + throw new RuntimeException(); + } + if (annotationsArray.length == 0 ) { + System.err.println("Error: no parameters for " + m); + throw new RuntimeException(); + } else { + java.lang.annotation.Annotation[] annotations = annotationsArray[0]; + if (annotations.length == 0) { + System.err.println("Error: no annotations on " + m); + throw new RuntimeException(); + } + } + } catch (Throwable t) { + if (!exceptionExpected) { + System.err.println("Error: Got an unexpected exception reading annotations on " + + m); + throw new RuntimeException(t); + } + } + } + + public static void main(String argv[]) throws Exception { + // Class A has a directly applied annotation whose class is + // missing. + testAnnotation(A.class, false); + + // Class B has a directly applied annotation whose value + // includes to an annotation class that is missing. + testAnnotation(B.class, true); + + + // Class C has a directly applied parameter annotation whose + // class is missing. + testParameterAnnotation(C.class.getDeclaredMethod("method1", Object.class), + false); + + // Class D has a directly applied parameter annotation whose value + // includes to an annotation class that is missing. + testParameterAnnotation(D.class.getDeclaredMethod("method1", Object.class), + true); + } +} diff --git a/jdk/test/java/lang/annotation/Missing/MissingWrapper.java b/jdk/test/java/lang/annotation/Missing/MissingWrapper.java new file mode 100644 index 00000000000..7cb4141de1f --- /dev/null +++ b/jdk/test/java/lang/annotation/Missing/MissingWrapper.java @@ -0,0 +1,34 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.*; + +/** + * Annotation wrapper around an annotation whose class will be missing + * when MissingTest is run. + */ +@Retention(RUNTIME) +public @interface MissingWrapper { + Missing value(); +} diff --git a/jdk/test/java/lang/annotation/PackageMain.java b/jdk/test/java/lang/annotation/PackageMain.java new file mode 100644 index 00000000000..d545682ef4b --- /dev/null +++ b/jdk/test/java/lang/annotation/PackageMain.java @@ -0,0 +1,36 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.lang.annotation.Documented; + +public class PackageMain { + public static void main(String[] args) throws Exception { + Class c = Class.forName("foo.bar.Baz"); + System.out.println("c=" + c); + System.out.println("cl=" + c.getClassLoader()); + Package p = c.getPackage(); + System.out.println("p=" + p); + Documented d = p.getAnnotation(Documented.class); + if (d == null) throw new Error(); + } +} diff --git a/jdk/test/java/lang/annotation/RecursiveAnnotation.java b/jdk/test/java/lang/annotation/RecursiveAnnotation.java new file mode 100644 index 00000000000..ab16f5c8e8f --- /dev/null +++ b/jdk/test/java/lang/annotation/RecursiveAnnotation.java @@ -0,0 +1,44 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5037685 + * @summary Under certain circumstances, recursive annotations disappeared + * @author Josh Bloch + */ + +import java.lang.annotation.*; +import static java.lang.annotation.RetentionPolicy.*; + +@Rat public class RecursiveAnnotation { + public static void main(String[] args) { + if (!RecursiveAnnotation.class.isAnnotationPresent(Rat.class)) + throw new RuntimeException("RecursiveAnnotation"); + + if (!Rat.class.isAnnotationPresent(Rat.class)) + throw new RuntimeException("Rat"); + } +} + +@Retention(RUNTIME) @Rat @interface Rat { } diff --git a/jdk/test/java/lang/annotation/UnitTest.java b/jdk/test/java/lang/annotation/UnitTest.java new file mode 100644 index 00000000000..ed8b05c3cc0 --- /dev/null +++ b/jdk/test/java/lang/annotation/UnitTest.java @@ -0,0 +1,4983 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4906359 4963461 4965058 4965039 4986770 + * @summary Unit test for annotation reading + * @author Josh Bloch + * @compile -source 1.5 UnitTest.java + * @run main UnitTest + */ + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.*; +import java.util.*; +import java.lang.reflect.*; +import java.io.*; + +public class UnitTest { + private static final Class[] X = new Class[0]; + private static final Class[] Y = { int.class }; + + static int numTests = 0; + + public static void main(String[] args) throws Exception { + + // *** TESTS ON ANNOTATED METHODS *** + + // MULTIMEMBER SCALAR TYPES ON METHOD + checkScalarTypes(UnitTest.class.getMethod("scalarTypesMethod", X)); + checkScalarTypesOverrideDefault(UnitTest.class.getMethod("scalarTypesOverrideDefaultMethod", X)); + checkScalarTypesAcceptDefault(UnitTest.class.getMethod("scalarTypesAcceptDefaultMethod", X)); + + // MULTIMEMBER ARRAY TYPES ON METHOD + checkArrayTypes0(UnitTest.class.getMethod("emptyArrayTypesMethod", X)); + checkArrayTypes1(UnitTest.class.getMethod("singleElementArrayTypesMethod", X)); + checkArrayTypes2(UnitTest.class.getMethod("twoElementArrayTypesMethod", X)); + checkArrayTypesAcceptDefault(UnitTest.class.getMethod("arrayTypesAcceptDefaultMethod", X)); + checkArrayTypesOverrideDefault(UnitTest.class.getMethod("arrayTypesOverrideDefaultMethod", X)); + + // MARKER TYPE ON METHOD + checkMarker(UnitTest.class.getMethod("markerMethod", X)); + + // SINGLE-MEMBER SCALAR TYPES ON METHOD + checkSingleMemberByte(UnitTest.class.getMethod("SingleMemberByte", X)); + checkSingleMemberShort(UnitTest.class.getMethod("SingleMemberShort", X)); + checkSingleMemberInt(UnitTest.class.getMethod("SingleMemberInt", X)); + checkSingleMemberLong(UnitTest.class.getMethod("SingleMemberLong", X)); + checkSingleMemberChar(UnitTest.class.getMethod("SingleMemberChar", X)); + checkSingleMemberFloat(UnitTest.class.getMethod("SingleMemberFloat", X)); + checkSingleMemberDouble(UnitTest.class.getMethod("SingleMemberDouble", X)); + checkSingleMemberBoolean(UnitTest.class.getMethod("SingleMemberBoolean", X)); + checkSingleMemberString(UnitTest.class.getMethod("SingleMemberString", X)); + checkSingleMemberClass(UnitTest.class.getMethod("SingleMemberClass", X)); + checkSingleMemberEnum(UnitTest.class.getMethod("SingleMemberEnum", X)); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON METHOD + checkSingleMemberByteOvrdDef(UnitTest.class.getMethod("SingleMemberByteOvrdDef", X)); + checkSingleMemberShortOvrdDef(UnitTest.class.getMethod("SingleMemberShortOvrdDef", X)); + checkSingleMemberIntOvrdDef(UnitTest.class.getMethod("SingleMemberIntOvrdDef", X)); + checkSingleMemberLongOvrdDef(UnitTest.class.getMethod("SingleMemberLongOvrdDef", X)); + checkSingleMemberCharOvrdDef(UnitTest.class.getMethod("SingleMemberCharOvrdDef", X)); + checkSingleMemberFloatOvrdDef(UnitTest.class.getMethod("SingleMemberFloatOvrdDef", X)); + checkSingleMemberDoubleOvrdDef(UnitTest.class.getMethod("SingleMemberDoubleOvrdDef", X)); + checkSingleMemberBooleanOvrdDef(UnitTest.class.getMethod("SingleMemberBooleanOvrdDef", X)); + checkSingleMemberStringOvrdDef(UnitTest.class.getMethod("SingleMemberStringOvrdDef", X)); + checkSingleMemberClassOvrdDef(UnitTest.class.getMethod("SingleMemberClassOvrdDef", X)); + checkSingleMemberEnumOvrdDef(UnitTest.class.getMethod("SingleMemberEnumOvrdDef", X)); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON METHOD + checkSingleMemberByteAcceptDef(UnitTest.class.getMethod("SingleMemberByteAcceptDef", X)); + checkSingleMemberShortAcceptDef(UnitTest.class.getMethod("SingleMemberShortAcceptDef", X)); + checkSingleMemberIntAcceptDef(UnitTest.class.getMethod("SingleMemberIntAcceptDef", X)); + checkSingleMemberLongAcceptDef(UnitTest.class.getMethod("SingleMemberLongAcceptDef", X)); + checkSingleMemberCharAcceptDef(UnitTest.class.getMethod("SingleMemberCharAcceptDef", X)); + checkSingleMemberFloatAcceptDef(UnitTest.class.getMethod("SingleMemberFloatAcceptDef", X)); + checkSingleMemberDoubleAcceptDef(UnitTest.class.getMethod("SingleMemberDoubleAcceptDef", X)); + checkSingleMemberBooleanAcceptDef(UnitTest.class.getMethod("SingleMemberBooleanAcceptDef", X)); + checkSingleMemberStringAcceptDef(UnitTest.class.getMethod("SingleMemberStringAcceptDef", X)); + checkSingleMemberClassAcceptDef(UnitTest.class.getMethod("SingleMemberClassAcceptDef", X)); + checkSingleMemberEnumAcceptDef(UnitTest.class.getMethod("SingleMemberEnumAcceptDef", X)); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) ON METHOD + checkSingleMemberByteArrEmpty(UnitTest.class.getMethod("SingleMemberByteArrEmpty", X)); + checkSingleMemberShortArrEmpty(UnitTest.class.getMethod("SingleMemberShortArrEmpty", X)); + checkSingleMemberIntArrEmpty(UnitTest.class.getMethod("SingleMemberIntArrEmpty", X)); + checkSingleMemberLongArrEmpty(UnitTest.class.getMethod("SingleMemberLongArrEmpty", X)); + checkSingleMemberCharArrEmpty(UnitTest.class.getMethod("SingleMemberCharArrEmpty", X)); + checkSingleMemberFloatArrEmpty(UnitTest.class.getMethod("SingleMemberFloatArrEmpty", X)); + checkSingleMemberDoubleArrEmpty(UnitTest.class.getMethod("SingleMemberDoubleArrEmpty", X)); + checkSingleMemberBooleanArrEmpty(UnitTest.class.getMethod("SingleMemberBooleanArrEmpty", X)); + checkSingleMemberStringArrEmpty(UnitTest.class.getMethod("SingleMemberStringArrEmpty", X)); + checkSingleMemberClassArrEmpty(UnitTest.class.getMethod("SingleMemberClassArrEmpty", X)); + checkSingleMemberEnumArrEmpty(UnitTest.class.getMethod("SingleMemberEnumArrEmpty", X)); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) ON METHOD + checkSingleMemberByteArrOne(UnitTest.class.getMethod("SingleMemberByteArrOne", X)); + checkSingleMemberShortArrOne(UnitTest.class.getMethod("SingleMemberShortArrOne", X)); + checkSingleMemberIntArrOne(UnitTest.class.getMethod("SingleMemberIntArrOne", X)); + checkSingleMemberLongArrOne(UnitTest.class.getMethod("SingleMemberLongArrOne", X)); + checkSingleMemberCharArrOne(UnitTest.class.getMethod("SingleMemberCharArrOne", X)); + checkSingleMemberFloatArrOne(UnitTest.class.getMethod("SingleMemberFloatArrOne", X)); + checkSingleMemberDoubleArrOne(UnitTest.class.getMethod("SingleMemberDoubleArrOne", X)); + checkSingleMemberBooleanArrOne(UnitTest.class.getMethod("SingleMemberBooleanArrOne", X)); + checkSingleMemberStringArrOne(UnitTest.class.getMethod("SingleMemberStringArrOne", X)); + checkSingleMemberClassArrOne(UnitTest.class.getMethod("SingleMemberClassArrOne", X)); + checkSingleMemberEnumArrOne(UnitTest.class.getMethod("SingleMemberEnumArrOne", X)); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) ON METHOD + checkSingleMemberByteArrTwo(UnitTest.class.getMethod("SingleMemberByteArrTwo", X)); + checkSingleMemberShortArrTwo(UnitTest.class.getMethod("SingleMemberShortArrTwo", X)); + checkSingleMemberIntArrTwo(UnitTest.class.getMethod("SingleMemberIntArrTwo", X)); + checkSingleMemberLongArrTwo(UnitTest.class.getMethod("SingleMemberLongArrTwo", X)); + checkSingleMemberCharArrTwo(UnitTest.class.getMethod("SingleMemberCharArrTwo", X)); + checkSingleMemberFloatArrTwo(UnitTest.class.getMethod("SingleMemberFloatArrTwo", X)); + checkSingleMemberDoubleArrTwo(UnitTest.class.getMethod("SingleMemberDoubleArrTwo", X)); + checkSingleMemberBooleanArrTwo(UnitTest.class.getMethod("SingleMemberBooleanArrTwo", X)); + checkSingleMemberStringArrTwo(UnitTest.class.getMethod("SingleMemberStringArrTwo", X)); + checkSingleMemberClassArrTwo(UnitTest.class.getMethod("SingleMemberClassArrTwo", X)); + checkSingleMemberEnumArrTwo(UnitTest.class.getMethod("SingleMemberEnumArrTwo", X)); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE)ON METHOD + checkSingleMemberByteArrOvrdDef(UnitTest.class.getMethod("SingleMemberByteArrOvrdDef", X)); + checkSingleMemberShortArrOvrdDef(UnitTest.class.getMethod("SingleMemberShortArrOvrdDef", X)); + checkSingleMemberIntArrOvrdDef(UnitTest.class.getMethod("SingleMemberIntArrOvrdDef", X)); + checkSingleMemberLongArrOvrdDef(UnitTest.class.getMethod("SingleMemberLongArrOvrdDef", X)); + checkSingleMemberCharArrOvrdDef(UnitTest.class.getMethod("SingleMemberCharArrOvrdDef", X)); + checkSingleMemberFloatArrOvrdDef(UnitTest.class.getMethod("SingleMemberFloatArrOvrdDef", X)); + checkSingleMemberDoubleArrOvrdDef(UnitTest.class.getMethod("SingleMemberDoubleArrOvrdDef", X)); + checkSingleMemberBooleanArrOvrdDef(UnitTest.class.getMethod("SingleMemberBooleanArrOvrdDef", X)); + checkSingleMemberStringArrOvrdDef(UnitTest.class.getMethod("SingleMemberStringArrOvrdDef", X)); + checkSingleMemberClassArrOvrdDef(UnitTest.class.getMethod("SingleMemberClassArrOvrdDef", X)); + checkSingleMemberEnumArrOvrdDef(UnitTest.class.getMethod("SingleMemberEnumArrOvrdDef", X)); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT)ON METHOD + checkSingleMemberByteArrAcceptDef(UnitTest.class.getMethod("SingleMemberByteArrAcceptDef", X)); + checkSingleMemberShortArrAcceptDef(UnitTest.class.getMethod("SingleMemberShortArrAcceptDef", X)); + checkSingleMemberIntArrAcceptDef(UnitTest.class.getMethod("SingleMemberIntArrAcceptDef", X)); + checkSingleMemberLongArrAcceptDef(UnitTest.class.getMethod("SingleMemberLongArrAcceptDef", X)); + checkSingleMemberCharArrAcceptDef(UnitTest.class.getMethod("SingleMemberCharArrAcceptDef", X)); + checkSingleMemberFloatArrAcceptDef(UnitTest.class.getMethod("SingleMemberFloatArrAcceptDef", X)); + checkSingleMemberDoubleArrAcceptDef(UnitTest.class.getMethod("SingleMemberDoubleArrAcceptDef", X)); + checkSingleMemberBooleanArrAcceptDef(UnitTest.class.getMethod("SingleMemberBooleanArrAcceptDef", X)); + checkSingleMemberStringArrAcceptDef(UnitTest.class.getMethod("SingleMemberStringArrAcceptDef", X)); + checkSingleMemberClassArrAcceptDef(UnitTest.class.getMethod("SingleMemberClassArrAcceptDef", X)); + checkSingleMemberEnumArrAcceptDef(UnitTest.class.getMethod("SingleMemberEnumArrAcceptDef", X)); + + // *** TESTS ON ANNOTATED FIELDS *** + + // MULTIMEMBER SCALAR TYPES ON FIELD + checkScalarTypes(UnitTest.class.getField("scalarTypesField")); + checkScalarTypesAcceptDefault(UnitTest.class.getField("scalarTypesAcceptDefaultField")); + checkScalarTypesOverrideDefault(UnitTest.class.getField("scalarTypesOverrideDefaultField")); + + // MULTIMEMBER ARRAY TYPES ON FIELD + checkArrayTypes0(UnitTest.class.getField("emptyArrayTypesField")); + checkArrayTypes1(UnitTest.class.getField("singleElementArrayTypesField")); + checkArrayTypes2(UnitTest.class.getField("twoElementArrayTypesField")); + checkArrayTypesAcceptDefault(UnitTest.class.getField("arrayTypesAcceptDefaultField")); + checkArrayTypesOverrideDefault(UnitTest.class.getField("arrayTypesOverrideDefaultField")); + + // MARKER TYPE ON FIELD + checkMarker(UnitTest.class.getField("markerField")); + + // SINGLE-MEMBER SCALAR TYPES ON FIELD + checkSingleMemberByte(UnitTest.class.getField("SingleMemberByteField")); + checkSingleMemberShort(UnitTest.class.getField("SingleMemberShortField")); + checkSingleMemberInt(UnitTest.class.getField("SingleMemberIntField")); + checkSingleMemberLong(UnitTest.class.getField("SingleMemberLongField")); + checkSingleMemberChar(UnitTest.class.getField("SingleMemberCharField")); + checkSingleMemberFloat(UnitTest.class.getField("SingleMemberFloatField")); + checkSingleMemberDouble(UnitTest.class.getField("SingleMemberDoubleField")); + checkSingleMemberBoolean(UnitTest.class.getField("SingleMemberBooleanField")); + checkSingleMemberString(UnitTest.class.getField("SingleMemberStringField")); + checkSingleMemberClass(UnitTest.class.getField("SingleMemberClassField")); + checkSingleMemberEnum(UnitTest.class.getField("SingleMemberEnumField")); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON FIELD + checkSingleMemberByteOvrdDef(UnitTest.class.getField("SingleMemberByteOvrdDefField")); + checkSingleMemberShortOvrdDef(UnitTest.class.getField("SingleMemberShortOvrdDefField")); + checkSingleMemberIntOvrdDef(UnitTest.class.getField("SingleMemberIntOvrdDefField")); + checkSingleMemberLongOvrdDef(UnitTest.class.getField("SingleMemberLongOvrdDefField")); + checkSingleMemberCharOvrdDef(UnitTest.class.getField("SingleMemberCharOvrdDefField")); + checkSingleMemberFloatOvrdDef(UnitTest.class.getField("SingleMemberFloatOvrdDefField")); + checkSingleMemberDoubleOvrdDef(UnitTest.class.getField("SingleMemberDoubleOvrdDefField")); + checkSingleMemberBooleanOvrdDef(UnitTest.class.getField("SingleMemberBooleanOvrdDefField")); + checkSingleMemberStringOvrdDef(UnitTest.class.getField("SingleMemberStringOvrdDefField")); + checkSingleMemberClassOvrdDef(UnitTest.class.getField("SingleMemberClassOvrdDefField")); + checkSingleMemberEnumOvrdDef(UnitTest.class.getField("SingleMemberEnumOvrdDefField")); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON FIELD + checkSingleMemberByteAcceptDef(UnitTest.class.getField("SingleMemberByteAcceptDefField")); + checkSingleMemberShortAcceptDef(UnitTest.class.getField("SingleMemberShortAcceptDefField")); + checkSingleMemberIntAcceptDef(UnitTest.class.getField("SingleMemberIntAcceptDefField")); + checkSingleMemberLongAcceptDef(UnitTest.class.getField("SingleMemberLongAcceptDefField")); + checkSingleMemberCharAcceptDef(UnitTest.class.getField("SingleMemberCharAcceptDefField")); + checkSingleMemberFloatAcceptDef(UnitTest.class.getField("SingleMemberFloatAcceptDefField")); + checkSingleMemberDoubleAcceptDef(UnitTest.class.getField("SingleMemberDoubleAcceptDefField")); + checkSingleMemberBooleanAcceptDef(UnitTest.class.getField("SingleMemberBooleanAcceptDefField")); + checkSingleMemberStringAcceptDef(UnitTest.class.getField("SingleMemberStringAcceptDefField")); + checkSingleMemberClassAcceptDef(UnitTest.class.getField("SingleMemberClassAcceptDefField")); + checkSingleMemberEnumAcceptDef(UnitTest.class.getField("SingleMemberEnumAcceptDefField")); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) ON FIELD + checkSingleMemberByteArrEmpty(UnitTest.class.getField("SingleMemberByteArrEmptyField")); + checkSingleMemberShortArrEmpty(UnitTest.class.getField("SingleMemberShortArrEmptyField")); + checkSingleMemberIntArrEmpty(UnitTest.class.getField("SingleMemberIntArrEmptyField")); + checkSingleMemberLongArrEmpty(UnitTest.class.getField("SingleMemberLongArrEmptyField")); + checkSingleMemberCharArrEmpty(UnitTest.class.getField("SingleMemberCharArrEmptyField")); + checkSingleMemberFloatArrEmpty(UnitTest.class.getField("SingleMemberFloatArrEmptyField")); + checkSingleMemberDoubleArrEmpty(UnitTest.class.getField("SingleMemberDoubleArrEmptyField")); + checkSingleMemberBooleanArrEmpty(UnitTest.class.getField("SingleMemberBooleanArrEmptyField")); + checkSingleMemberStringArrEmpty(UnitTest.class.getField("SingleMemberStringArrEmptyField")); + checkSingleMemberClassArrEmpty(UnitTest.class.getField("SingleMemberClassArrEmptyField")); + checkSingleMemberEnumArrEmpty(UnitTest.class.getField("SingleMemberEnumArrEmptyField")); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) ON FIELD + checkSingleMemberByteArrOne(UnitTest.class.getField("SingleMemberByteArrOneField")); + checkSingleMemberShortArrOne(UnitTest.class.getField("SingleMemberShortArrOneField")); + checkSingleMemberIntArrOne(UnitTest.class.getField("SingleMemberIntArrOneField")); + checkSingleMemberLongArrOne(UnitTest.class.getField("SingleMemberLongArrOneField")); + checkSingleMemberCharArrOne(UnitTest.class.getField("SingleMemberCharArrOneField")); + checkSingleMemberFloatArrOne(UnitTest.class.getField("SingleMemberFloatArrOneField")); + checkSingleMemberDoubleArrOne(UnitTest.class.getField("SingleMemberDoubleArrOneField")); + checkSingleMemberBooleanArrOne(UnitTest.class.getField("SingleMemberBooleanArrOneField")); + checkSingleMemberStringArrOne(UnitTest.class.getField("SingleMemberStringArrOneField")); + checkSingleMemberClassArrOne(UnitTest.class.getField("SingleMemberClassArrOneField")); + checkSingleMemberEnumArrOne(UnitTest.class.getField("SingleMemberEnumArrOneField")); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) ON FIELD + checkSingleMemberByteArrTwo(UnitTest.class.getField("SingleMemberByteArrTwoField")); + checkSingleMemberShortArrTwo(UnitTest.class.getField("SingleMemberShortArrTwoField")); + checkSingleMemberIntArrTwo(UnitTest.class.getField("SingleMemberIntArrTwoField")); + checkSingleMemberLongArrTwo(UnitTest.class.getField("SingleMemberLongArrTwoField")); + checkSingleMemberCharArrTwo(UnitTest.class.getField("SingleMemberCharArrTwoField")); + checkSingleMemberFloatArrTwo(UnitTest.class.getField("SingleMemberFloatArrTwoField")); + checkSingleMemberDoubleArrTwo(UnitTest.class.getField("SingleMemberDoubleArrTwoField")); + checkSingleMemberBooleanArrTwo(UnitTest.class.getField("SingleMemberBooleanArrTwoField")); + checkSingleMemberStringArrTwo(UnitTest.class.getField("SingleMemberStringArrTwoField")); + checkSingleMemberClassArrTwo(UnitTest.class.getField("SingleMemberClassArrTwoField")); + checkSingleMemberEnumArrTwo(UnitTest.class.getField("SingleMemberEnumArrTwoField")); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE)ON FIELD + checkSingleMemberByteArrOvrdDef(UnitTest.class.getField("SingleMemberByteArrOvrdDefField")); + checkSingleMemberShortArrOvrdDef(UnitTest.class.getField("SingleMemberShortArrOvrdDefField")); + checkSingleMemberIntArrOvrdDef(UnitTest.class.getField("SingleMemberIntArrOvrdDefField")); + checkSingleMemberLongArrOvrdDef(UnitTest.class.getField("SingleMemberLongArrOvrdDefField")); + checkSingleMemberCharArrOvrdDef(UnitTest.class.getField("SingleMemberCharArrOvrdDefField")); + checkSingleMemberFloatArrOvrdDef(UnitTest.class.getField("SingleMemberFloatArrOvrdDefField")); + checkSingleMemberDoubleArrOvrdDef(UnitTest.class.getField("SingleMemberDoubleArrOvrdDefField")); + checkSingleMemberBooleanArrOvrdDef(UnitTest.class.getField("SingleMemberBooleanArrOvrdDefField")); + checkSingleMemberStringArrOvrdDef(UnitTest.class.getField("SingleMemberStringArrOvrdDefField")); + checkSingleMemberClassArrOvrdDef(UnitTest.class.getField("SingleMemberClassArrOvrdDefField")); + checkSingleMemberEnumArrOvrdDef(UnitTest.class.getField("SingleMemberEnumArrOvrdDefField")); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT)ON FIELD + checkSingleMemberByteArrAcceptDef(UnitTest.class.getField("SingleMemberByteArrAcceptDefField")); + checkSingleMemberShortArrAcceptDef(UnitTest.class.getField("SingleMemberShortArrAcceptDefField")); + checkSingleMemberIntArrAcceptDef(UnitTest.class.getField("SingleMemberIntArrAcceptDefField")); + checkSingleMemberLongArrAcceptDef(UnitTest.class.getField("SingleMemberLongArrAcceptDefField")); + checkSingleMemberCharArrAcceptDef(UnitTest.class.getField("SingleMemberCharArrAcceptDefField")); + checkSingleMemberFloatArrAcceptDef(UnitTest.class.getField("SingleMemberFloatArrAcceptDefField")); + checkSingleMemberDoubleArrAcceptDef(UnitTest.class.getField("SingleMemberDoubleArrAcceptDefField")); + checkSingleMemberBooleanArrAcceptDef(UnitTest.class.getField("SingleMemberBooleanArrAcceptDefField")); + checkSingleMemberStringArrAcceptDef(UnitTest.class.getField("SingleMemberStringArrAcceptDefField")); + checkSingleMemberClassArrAcceptDef(UnitTest.class.getField("SingleMemberClassArrAcceptDefField")); + checkSingleMemberEnumArrAcceptDef(UnitTest.class.getField("SingleMemberEnumArrAcceptDefField")); + + // *** TESTS ON ANNOTATED ENUM CONSTS *** + + // MULTIMEMBER SCALAR TYPES ON ENUM CONST + checkScalarTypes(TestType.class.getField("scalarTypesField")); + checkScalarTypesAcceptDefault(TestType.class.getField("scalarTypesAcceptDefaultField")); + checkScalarTypesOverrideDefault(TestType.class.getField("scalarTypesOverrideDefaultField")); + + // MULTIMEMBER ARRAY TYPES ON ENUM CONST + checkArrayTypes0(TestType.class.getField("emptyArrayTypesField")); + checkArrayTypes1(TestType.class.getField("singleElementArrayTypesField")); + checkArrayTypes2(TestType.class.getField("twoElementArrayTypesField")); + checkArrayTypesAcceptDefault(TestType.class.getField("arrayTypesAcceptDefaultField")); + checkArrayTypesOverrideDefault(TestType.class.getField("arrayTypesOverrideDefaultField")); + + // MARKER TYPE ON CLASS + checkMarker(TestType.class.getField("marker")); + + // SINGLE-MEMBER SCALAR TYPES ON CLASS + checkSingleMemberByte(TestType.class.getField("SingleMemberByte")); + checkSingleMemberShort(TestType.class.getField("SingleMemberShort")); + checkSingleMemberInt(TestType.class.getField("SingleMemberInt")); + checkSingleMemberLong(TestType.class.getField("SingleMemberLong")); + checkSingleMemberChar(TestType.class.getField("SingleMemberChar")); + checkSingleMemberFloat(TestType.class.getField("SingleMemberFloat")); + checkSingleMemberDouble(TestType.class.getField("SingleMemberDouble")); + checkSingleMemberBoolean(TestType.class.getField("SingleMemberBoolean")); + checkSingleMemberString(TestType.class.getField("SingleMemberString")); + checkSingleMemberClass(TestType.class.getField("SingleMemberClass")); + checkSingleMemberEnum(TestType.class.getField("SingleMemberEnum")); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON CLASS + checkSingleMemberByteOvrdDef(TestType.class.getField("SingleMemberByteOvrdDef")); + checkSingleMemberShortOvrdDef(TestType.class.getField("SingleMemberShortOvrdDef")); + checkSingleMemberIntOvrdDef(TestType.class.getField("SingleMemberIntOvrdDef")); + checkSingleMemberLongOvrdDef(TestType.class.getField("SingleMemberLongOvrdDef")); + checkSingleMemberCharOvrdDef(TestType.class.getField("SingleMemberCharOvrdDef")); + checkSingleMemberFloatOvrdDef(TestType.class.getField("SingleMemberFloatOvrdDef")); + checkSingleMemberDoubleOvrdDef(TestType.class.getField("SingleMemberDoubleOvrdDef")); + checkSingleMemberBooleanOvrdDef(TestType.class.getField("SingleMemberBooleanOvrdDef")); + checkSingleMemberStringOvrdDef(TestType.class.getField("SingleMemberStringOvrdDef")); + checkSingleMemberClassOvrdDef(TestType.class.getField("SingleMemberClassOvrdDef")); + checkSingleMemberEnumOvrdDef(TestType.class.getField("SingleMemberEnumOvrdDef")); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON CLASS + checkSingleMemberByteAcceptDef(TestType.class.getField("SingleMemberByteAcceptDef")); + checkSingleMemberShortAcceptDef(TestType.class.getField("SingleMemberShortAcceptDef")); + checkSingleMemberIntAcceptDef(TestType.class.getField("SingleMemberIntAcceptDef")); + checkSingleMemberLongAcceptDef(TestType.class.getField("SingleMemberLongAcceptDef")); + checkSingleMemberCharAcceptDef(TestType.class.getField("SingleMemberCharAcceptDef")); + checkSingleMemberFloatAcceptDef(TestType.class.getField("SingleMemberFloatAcceptDef")); + checkSingleMemberDoubleAcceptDef(TestType.class.getField("SingleMemberDoubleAcceptDef")); + checkSingleMemberBooleanAcceptDef(TestType.class.getField("SingleMemberBooleanAcceptDef")); + checkSingleMemberStringAcceptDef(TestType.class.getField("SingleMemberStringAcceptDef")); + checkSingleMemberClassAcceptDef(TestType.class.getField("SingleMemberClassAcceptDef")); + checkSingleMemberEnumAcceptDef(TestType.class.getField("SingleMemberEnumAcceptDef")); + + // SINGLE-MEMBER ARRAY TYPES (TestType.class.getField("EMPTY ARRAY) ON CLASS + checkSingleMemberByteArrEmpty(TestType.class.getField("SingleMemberByteArrEmpty")); + checkSingleMemberShortArrEmpty(TestType.class.getField("SingleMemberShortArrEmpty")); + checkSingleMemberIntArrEmpty(TestType.class.getField("SingleMemberIntArrEmpty")); + checkSingleMemberLongArrEmpty(TestType.class.getField("SingleMemberLongArrEmpty")); + checkSingleMemberCharArrEmpty(TestType.class.getField("SingleMemberCharArrEmpty")); + checkSingleMemberFloatArrEmpty(TestType.class.getField("SingleMemberFloatArrEmpty")); + checkSingleMemberDoubleArrEmpty(TestType.class.getField("SingleMemberDoubleArrEmpty")); + checkSingleMemberBooleanArrEmpty(TestType.class.getField("SingleMemberBooleanArrEmpty")); + checkSingleMemberStringArrEmpty(TestType.class.getField("SingleMemberStringArrEmpty")); + checkSingleMemberClassArrEmpty(TestType.class.getField("SingleMemberClassArrEmpty")); + checkSingleMemberEnumArrEmpty(TestType.class.getField("SingleMemberEnumArrEmpty")); + + // SINGLE-MEMBER ARRAY TYPES (TestType.class.getField("ONE-ELEMENT ARRAY) ON CLASS + checkSingleMemberByteArrOne(TestType.class.getField("SingleMemberByteArrOne")); + checkSingleMemberShortArrOne(TestType.class.getField("SingleMemberShortArrOne")); + checkSingleMemberIntArrOne(TestType.class.getField("SingleMemberIntArrOne")); + checkSingleMemberLongArrOne(TestType.class.getField("SingleMemberLongArrOne")); + checkSingleMemberCharArrOne(TestType.class.getField("SingleMemberCharArrOne")); + checkSingleMemberFloatArrOne(TestType.class.getField("SingleMemberFloatArrOne")); + checkSingleMemberDoubleArrOne(TestType.class.getField("SingleMemberDoubleArrOne")); + checkSingleMemberBooleanArrOne(TestType.class.getField("SingleMemberBooleanArrOne")); + checkSingleMemberStringArrOne(TestType.class.getField("SingleMemberStringArrOne")); + checkSingleMemberClassArrOne(TestType.class.getField("SingleMemberClassArrOne")); + checkSingleMemberEnumArrOne(TestType.class.getField("SingleMemberEnumArrOne")); + + // SINGLE-MEMBER ARRAY TYPES (TestType.class.getField("TWO-ELEMENT ARRAY) ON CLASS + checkSingleMemberByteArrTwo(TestType.class.getField("SingleMemberByteArrTwo")); + checkSingleMemberShortArrTwo(TestType.class.getField("SingleMemberShortArrTwo")); + checkSingleMemberIntArrTwo(TestType.class.getField("SingleMemberIntArrTwo")); + checkSingleMemberLongArrTwo(TestType.class.getField("SingleMemberLongArrTwo")); + checkSingleMemberCharArrTwo(TestType.class.getField("SingleMemberCharArrTwo")); + checkSingleMemberFloatArrTwo(TestType.class.getField("SingleMemberFloatArrTwo")); + checkSingleMemberDoubleArrTwo(TestType.class.getField("SingleMemberDoubleArrTwo")); + checkSingleMemberBooleanArrTwo(TestType.class.getField("SingleMemberBooleanArrTwo")); + checkSingleMemberStringArrTwo(TestType.class.getField("SingleMemberStringArrTwo")); + checkSingleMemberClassArrTwo(TestType.class.getField("SingleMemberClassArrTwo")); + checkSingleMemberEnumArrTwo(TestType.class.getField("SingleMemberEnumArrTwo")); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (TestType.class.getField("OVERRIDE)ON CLASS + checkSingleMemberByteArrOvrdDef(TestType.class.getField("SingleMemberByteArrOvrdDef")); + checkSingleMemberShortArrOvrdDef(TestType.class.getField("SingleMemberShortArrOvrdDef")); + checkSingleMemberIntArrOvrdDef(TestType.class.getField("SingleMemberIntArrOvrdDef")); + checkSingleMemberLongArrOvrdDef(TestType.class.getField("SingleMemberLongArrOvrdDef")); + checkSingleMemberCharArrOvrdDef(TestType.class.getField("SingleMemberCharArrOvrdDef")); + checkSingleMemberFloatArrOvrdDef(TestType.class.getField("SingleMemberFloatArrOvrdDef")); + checkSingleMemberDoubleArrOvrdDef(TestType.class.getField("SingleMemberDoubleArrOvrdDef")); + checkSingleMemberBooleanArrOvrdDef(TestType.class.getField("SingleMemberBooleanArrOvrdDef")); + checkSingleMemberStringArrOvrdDef(TestType.class.getField("SingleMemberStringArrOvrdDef")); + checkSingleMemberClassArrOvrdDef(TestType.class.getField("SingleMemberClassArrOvrdDef")); + checkSingleMemberEnumArrOvrdDef(TestType.class.getField("SingleMemberEnumArrOvrdDef")); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (TestType.class.getField("ACCEPT)ON CLASS + checkSingleMemberByteArrAcceptDef(TestType.class.getField("SingleMemberByteArrAcceptDef")); + checkSingleMemberShortArrAcceptDef(TestType.class.getField("SingleMemberShortArrAcceptDef")); + checkSingleMemberIntArrAcceptDef(TestType.class.getField("SingleMemberIntArrAcceptDef")); + checkSingleMemberLongArrAcceptDef(TestType.class.getField("SingleMemberLongArrAcceptDef")); + checkSingleMemberCharArrAcceptDef(TestType.class.getField("SingleMemberCharArrAcceptDef")); + checkSingleMemberFloatArrAcceptDef(TestType.class.getField("SingleMemberFloatArrAcceptDef")); + checkSingleMemberDoubleArrAcceptDef(TestType.class.getField("SingleMemberDoubleArrAcceptDef")); + checkSingleMemberBooleanArrAcceptDef(TestType.class.getField("SingleMemberBooleanArrAcceptDef")); + checkSingleMemberStringArrAcceptDef(TestType.class.getField("SingleMemberStringArrAcceptDef")); + checkSingleMemberClassArrAcceptDef(TestType.class.getField("SingleMemberClassArrAcceptDef")); + checkSingleMemberEnumArrAcceptDef(TestType.class.getField("SingleMemberEnumArrAcceptDef")); + + // *** TESTS ON ANNOTATED CONSTRUCTORS *** + + // MULTIMEMBER SCALAR TYPES ON CONSTRUCTOR + checkScalarTypes(UnitTest.class.getConstructor(new Class[]{Iterator.class})); + checkScalarTypesOverrideDefault(UnitTest.class.getConstructor(new Class[]{Map.class})); + checkScalarTypesAcceptDefault(UnitTest.class.getConstructor(new Class[]{Set.class})); + + // MULTIMEMBER ARRAY TYPES ON CONSTRUCTOR + checkArrayTypes0(UnitTest.class.getConstructor(new Class[]{List.class})); + checkArrayTypes1(UnitTest.class.getConstructor(new Class[]{Collection.class})); + checkArrayTypes2(UnitTest.class.getConstructor(new Class[]{SortedSet.class})); + checkArrayTypesAcceptDefault(UnitTest.class.getConstructor(new Class[]{SortedMap.class})); + checkArrayTypesOverrideDefault(UnitTest.class.getConstructor(new Class[]{RandomAccess.class})); + + // MARKER TYPE ON CONSTRUCTOR + checkMarker(UnitTest.class.getConstructor(new Class[] { })); + + // SINGLE-MEMBER SCALAR TYPES ON CONSTRUCTOR + checkSingleMemberByte(UnitTest.class.getConstructor(new Class[] { byte.class })); + checkSingleMemberShort(UnitTest.class.getConstructor(new Class[] { short.class })); + checkSingleMemberInt(UnitTest.class.getConstructor(new Class[] { int.class })); + checkSingleMemberLong(UnitTest.class.getConstructor(new Class[] { long.class })); + checkSingleMemberChar(UnitTest.class.getConstructor(new Class[] { char.class })); + checkSingleMemberFloat(UnitTest.class.getConstructor(new Class[] { float.class })); + checkSingleMemberDouble(UnitTest.class.getConstructor(new Class[] { double.class })); + checkSingleMemberBoolean(UnitTest.class.getConstructor(new Class[] { boolean.class })); + checkSingleMemberString(UnitTest.class.getConstructor(new Class[] { String.class })); + checkSingleMemberClass(UnitTest.class.getConstructor(new Class[] { Class.class })); + checkSingleMemberEnum(UnitTest.class.getConstructor(new Class[] { Enum.class })); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON CONSTRUCTOR + checkSingleMemberByteOvrdDef(UnitTest.class.getConstructor(new Class[] { byte.class, Set.class })); + checkSingleMemberShortOvrdDef(UnitTest.class.getConstructor(new Class[] { short.class, Set.class })); + checkSingleMemberIntOvrdDef(UnitTest.class.getConstructor(new Class[] { int.class, Set.class })); + checkSingleMemberLongOvrdDef(UnitTest.class.getConstructor(new Class[] { long.class, Set.class })); + checkSingleMemberCharOvrdDef(UnitTest.class.getConstructor(new Class[] { char.class, Set.class })); + checkSingleMemberFloatOvrdDef(UnitTest.class.getConstructor(new Class[] { float.class, Set.class })); + checkSingleMemberDoubleOvrdDef(UnitTest.class.getConstructor(new Class[] { double.class, Set.class })); + checkSingleMemberBooleanOvrdDef(UnitTest.class.getConstructor(new Class[] { boolean.class, Set.class })); + checkSingleMemberStringOvrdDef(UnitTest.class.getConstructor(new Class[] { String.class, Set.class })); + checkSingleMemberClassOvrdDef(UnitTest.class.getConstructor(new Class[] { Class.class, Set.class })); + checkSingleMemberEnumOvrdDef(UnitTest.class.getConstructor(new Class[] { Enum.class, Set.class })); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON CONSTRUCTOR + checkSingleMemberByteAcceptDef(UnitTest.class.getConstructor(new Class[] { byte.class, Map.class })); + checkSingleMemberShortAcceptDef(UnitTest.class.getConstructor(new Class[] { short.class, Map.class })); + checkSingleMemberIntAcceptDef(UnitTest.class.getConstructor(new Class[] { int.class, Map.class })); + checkSingleMemberLongAcceptDef(UnitTest.class.getConstructor(new Class[] { long.class, Map.class })); + checkSingleMemberCharAcceptDef(UnitTest.class.getConstructor(new Class[] { char.class, Map.class })); + checkSingleMemberFloatAcceptDef(UnitTest.class.getConstructor(new Class[] { float.class, Map.class })); + checkSingleMemberDoubleAcceptDef(UnitTest.class.getConstructor(new Class[] { double.class, Map.class })); + checkSingleMemberBooleanAcceptDef(UnitTest.class.getConstructor(new Class[] { boolean.class, Map.class })); + checkSingleMemberStringAcceptDef(UnitTest.class.getConstructor(new Class[] { String.class, Map.class })); + checkSingleMemberClassAcceptDef(UnitTest.class.getConstructor(new Class[] { Class.class, Map.class })); + checkSingleMemberEnumAcceptDef(UnitTest.class.getConstructor(new Class[] { Enum.class, Map.class })); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) ON CONSTRUCTOR + checkSingleMemberByteArrEmpty(UnitTest.class.getConstructor(new Class[] { byte[].class })); + checkSingleMemberShortArrEmpty(UnitTest.class.getConstructor(new Class[] { short[].class })); + checkSingleMemberIntArrEmpty(UnitTest.class.getConstructor(new Class[] { int[].class })); + checkSingleMemberLongArrEmpty(UnitTest.class.getConstructor(new Class[] { long[].class })); + checkSingleMemberCharArrEmpty(UnitTest.class.getConstructor(new Class[] { char[].class })); + checkSingleMemberFloatArrEmpty(UnitTest.class.getConstructor(new Class[] { float[].class })); + checkSingleMemberDoubleArrEmpty(UnitTest.class.getConstructor(new Class[] { double[].class })); + checkSingleMemberBooleanArrEmpty(UnitTest.class.getConstructor(new Class[] { boolean[].class })); + checkSingleMemberStringArrEmpty(UnitTest.class.getConstructor(new Class[] { String[].class })); + checkSingleMemberClassArrEmpty(UnitTest.class.getConstructor(new Class[] { Class[].class })); + checkSingleMemberEnumArrEmpty(UnitTest.class.getConstructor(new Class[] { Enum[].class })); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) ON CONSTRUCTOR + checkSingleMemberByteArrOne(UnitTest.class.getConstructor(new Class[] { byte[].class, Set.class })); + checkSingleMemberShortArrOne(UnitTest.class.getConstructor(new Class[] { short[].class, Set.class })); + checkSingleMemberIntArrOne(UnitTest.class.getConstructor(new Class[] { int[].class, Set.class })); + checkSingleMemberLongArrOne(UnitTest.class.getConstructor(new Class[] { long[].class, Set.class })); + checkSingleMemberCharArrOne(UnitTest.class.getConstructor(new Class[] { char[].class, Set.class })); + checkSingleMemberFloatArrOne(UnitTest.class.getConstructor(new Class[] { float[].class, Set.class })); + checkSingleMemberDoubleArrOne(UnitTest.class.getConstructor(new Class[] { double[].class, Set.class })); + checkSingleMemberBooleanArrOne(UnitTest.class.getConstructor(new Class[] { boolean[].class, Set.class })); + checkSingleMemberStringArrOne(UnitTest.class.getConstructor(new Class[] { String[].class, Set.class })); + checkSingleMemberClassArrOne(UnitTest.class.getConstructor(new Class[] { Class[].class, Set.class })); + checkSingleMemberEnumArrOne(UnitTest.class.getConstructor(new Class[] { Enum[].class, Set.class })); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) ON CONSTRUCTOR + checkSingleMemberByteArrTwo(UnitTest.class.getConstructor(new Class[] { byte[].class, Map.class })); + checkSingleMemberShortArrTwo(UnitTest.class.getConstructor(new Class[] { short[].class, Map.class })); + checkSingleMemberIntArrTwo(UnitTest.class.getConstructor(new Class[] { int[].class, Map.class })); + checkSingleMemberLongArrTwo(UnitTest.class.getConstructor(new Class[] { long[].class, Map.class })); + checkSingleMemberCharArrTwo(UnitTest.class.getConstructor(new Class[] { char[].class, Map.class })); + checkSingleMemberFloatArrTwo(UnitTest.class.getConstructor(new Class[] { float[].class, Map.class })); + checkSingleMemberDoubleArrTwo(UnitTest.class.getConstructor(new Class[] { double[].class, Map.class })); + checkSingleMemberBooleanArrTwo(UnitTest.class.getConstructor(new Class[] { boolean[].class, Map.class })); + checkSingleMemberStringArrTwo(UnitTest.class.getConstructor(new Class[] { String[].class, Map.class })); + checkSingleMemberClassArrTwo(UnitTest.class.getConstructor(new Class[] { Class[].class, Map.class })); + checkSingleMemberEnumArrTwo(UnitTest.class.getConstructor(new Class[] { Enum[].class, Map.class })); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE)ON CONSTRUCTOR + checkSingleMemberByteArrOvrdDef(UnitTest.class.getConstructor(new Class[] { byte[].class, List.class })); + checkSingleMemberShortArrOvrdDef(UnitTest.class.getConstructor(new Class[] { short[].class, List.class })); + checkSingleMemberIntArrOvrdDef(UnitTest.class.getConstructor(new Class[] { int[].class, List.class })); + checkSingleMemberLongArrOvrdDef(UnitTest.class.getConstructor(new Class[] { long[].class, List.class })); + checkSingleMemberCharArrOvrdDef(UnitTest.class.getConstructor(new Class[] { char[].class, List.class })); + checkSingleMemberFloatArrOvrdDef(UnitTest.class.getConstructor(new Class[] { float[].class, List.class })); + checkSingleMemberDoubleArrOvrdDef(UnitTest.class.getConstructor(new Class[] { double[].class, List.class })); + checkSingleMemberBooleanArrOvrdDef(UnitTest.class.getConstructor(new Class[] { boolean[].class, List.class })); + checkSingleMemberStringArrOvrdDef(UnitTest.class.getConstructor(new Class[] { String[].class, List.class })); + checkSingleMemberClassArrOvrdDef(UnitTest.class.getConstructor(new Class[] { Class[].class, List.class })); + checkSingleMemberEnumArrOvrdDef(UnitTest.class.getConstructor(new Class[] { Enum[].class, List.class })); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT)ON CONSTRUCTOR + checkSingleMemberByteArrAcceptDef(UnitTest.class.getConstructor(new Class[] { byte[].class, Collection.class })); + checkSingleMemberShortArrAcceptDef(UnitTest.class.getConstructor(new Class[] { short[].class, Collection.class })); + checkSingleMemberIntArrAcceptDef(UnitTest.class.getConstructor(new Class[] { int[].class, Collection.class })); + checkSingleMemberLongArrAcceptDef(UnitTest.class.getConstructor(new Class[] { long[].class, Collection.class })); + checkSingleMemberCharArrAcceptDef(UnitTest.class.getConstructor(new Class[] { char[].class, Collection.class })); + checkSingleMemberFloatArrAcceptDef(UnitTest.class.getConstructor(new Class[] { float[].class, Collection.class })); + checkSingleMemberDoubleArrAcceptDef(UnitTest.class.getConstructor(new Class[] { double[].class, Collection.class })); + checkSingleMemberBooleanArrAcceptDef(UnitTest.class.getConstructor(new Class[] { boolean[].class, Collection.class })); + checkSingleMemberStringArrAcceptDef(UnitTest.class.getConstructor(new Class[] { String[].class, Collection.class })); + checkSingleMemberClassArrAcceptDef(UnitTest.class.getConstructor(new Class[] { Class[].class, Collection.class })); + checkSingleMemberEnumArrAcceptDef(UnitTest.class.getConstructor(new Class[] { Enum[].class, Collection.class })); + + // *** TESTS ON ANNOTATED PARAMETERS *** + + // MULTIMEMBER SCALAR TYPES ON PARAM + checkScalarTypesParam(UnitTest.class.getMethod("scalarTypesParam", Y)); + checkScalarTypesOverrideDefaultParam(UnitTest.class.getMethod("scalarTypesOverrideDefaultParam", Y)); + checkScalarTypesAcceptDefaultParam(UnitTest.class.getMethod("scalarTypesAcceptDefaultParam", Y)); + + // MULTIMEMBER ARRAY TYPES ON PARAM + checkArrayTypes0Param(UnitTest.class.getMethod("emptyArrayTypesParam", Y)); + checkArrayTypes1Param(UnitTest.class.getMethod("singleElementArrayTypesParam", Y)); + checkArrayTypes2Param(UnitTest.class.getMethod("twoElementArrayTypesParam", Y)); + checkArrayTypesAcceptDefaultParam(UnitTest.class.getMethod("arrayTypesAcceptDefaultParam", Y)); + checkArrayTypesOverrideDefaultParam(UnitTest.class.getMethod("arrayTypesOverrideDefaultParam", Y)); + + // MARKER TYPE ON PARAMETER + checkMarkerParam(UnitTest.class.getMethod("markerParam", Y)); + + // SINGLE-MEMBER SCALAR TYPES ON PARAMETER + checkSingleMemberByteParam(UnitTest.class.getMethod("SingleMemberByteParam", Y)); + checkSingleMemberShortParam(UnitTest.class.getMethod("SingleMemberShortParam", Y)); + checkSingleMemberIntParam(UnitTest.class.getMethod("SingleMemberIntParam", Y)); + checkSingleMemberLongParam(UnitTest.class.getMethod("SingleMemberLongParam", Y)); + checkSingleMemberCharParam(UnitTest.class.getMethod("SingleMemberCharParam", Y)); + checkSingleMemberFloatParam(UnitTest.class.getMethod("SingleMemberFloatParam", Y)); + checkSingleMemberDoubleParam(UnitTest.class.getMethod("SingleMemberDoubleParam", Y)); + checkSingleMemberBooleanParam(UnitTest.class.getMethod("SingleMemberBooleanParam", Y)); + checkSingleMemberStringParam(UnitTest.class.getMethod("SingleMemberStringParam", Y)); + checkSingleMemberClassParam(UnitTest.class.getMethod("SingleMemberClassParam", Y)); + checkSingleMemberEnumParam(UnitTest.class.getMethod("SingleMemberEnumParam", Y)); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON PARAMETER + checkSingleMemberByteOvrdDefParam(UnitTest.class.getMethod("SingleMemberByteOvrdDefParam", Y)); + checkSingleMemberShortOvrdDefParam(UnitTest.class.getMethod("SingleMemberShortOvrdDefParam", Y)); + checkSingleMemberIntOvrdDefParam(UnitTest.class.getMethod("SingleMemberIntOvrdDefParam", Y)); + checkSingleMemberLongOvrdDefParam(UnitTest.class.getMethod("SingleMemberLongOvrdDefParam", Y)); + checkSingleMemberCharOvrdDefParam(UnitTest.class.getMethod("SingleMemberCharOvrdDefParam", Y)); + checkSingleMemberFloatOvrdDefParam(UnitTest.class.getMethod("SingleMemberFloatOvrdDefParam", Y)); + checkSingleMemberDoubleOvrdDefParam(UnitTest.class.getMethod("SingleMemberDoubleOvrdDefParam", Y)); + checkSingleMemberBooleanOvrdDefParam(UnitTest.class.getMethod("SingleMemberBooleanOvrdDefParam", Y)); + checkSingleMemberStringOvrdDefParam(UnitTest.class.getMethod("SingleMemberStringOvrdDefParam", Y)); + checkSingleMemberClassOvrdDefParam(UnitTest.class.getMethod("SingleMemberClassOvrdDefParam", Y)); + checkSingleMemberEnumOvrdDefParam(UnitTest.class.getMethod("SingleMemberEnumOvrdDefParam", Y)); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON PARAMETER + checkSingleMemberByteAcceptDefParam(UnitTest.class.getMethod("SingleMemberByteAcceptDefParam", Y)); + checkSingleMemberShortAcceptDefParam(UnitTest.class.getMethod("SingleMemberShortAcceptDefParam", Y)); + checkSingleMemberIntAcceptDefParam(UnitTest.class.getMethod("SingleMemberIntAcceptDefParam", Y)); + checkSingleMemberLongAcceptDefParam(UnitTest.class.getMethod("SingleMemberLongAcceptDefParam", Y)); + checkSingleMemberCharAcceptDefParam(UnitTest.class.getMethod("SingleMemberCharAcceptDefParam", Y)); + checkSingleMemberFloatAcceptDefParam(UnitTest.class.getMethod("SingleMemberFloatAcceptDefParam", Y)); + checkSingleMemberDoubleAcceptDefParam(UnitTest.class.getMethod("SingleMemberDoubleAcceptDefParam", Y)); + checkSingleMemberBooleanAcceptDefParam(UnitTest.class.getMethod("SingleMemberBooleanAcceptDefParam", Y)); + checkSingleMemberStringAcceptDefParam(UnitTest.class.getMethod("SingleMemberStringAcceptDefParam", Y)); + checkSingleMemberClassAcceptDefParam(UnitTest.class.getMethod("SingleMemberClassAcceptDefParam", Y)); + checkSingleMemberEnumAcceptDefParam(UnitTest.class.getMethod("SingleMemberEnumAcceptDefParam", Y)); + + // SINGLE-MEMBER ARRAY TYPES Param(UnitTest.class.getMethod("EMPTY ARRAY) ON PARAMETER + checkSingleMemberByteArrEmptyParam(UnitTest.class.getMethod("SingleMemberByteArrEmptyParam", Y)); + checkSingleMemberShortArrEmptyParam(UnitTest.class.getMethod("SingleMemberShortArrEmptyParam", Y)); + checkSingleMemberIntArrEmptyParam(UnitTest.class.getMethod("SingleMemberIntArrEmptyParam", Y)); + checkSingleMemberLongArrEmptyParam(UnitTest.class.getMethod("SingleMemberLongArrEmptyParam", Y)); + checkSingleMemberCharArrEmptyParam(UnitTest.class.getMethod("SingleMemberCharArrEmptyParam", Y)); + checkSingleMemberFloatArrEmptyParam(UnitTest.class.getMethod("SingleMemberFloatArrEmptyParam", Y)); + checkSingleMemberDoubleArrEmptyParam(UnitTest.class.getMethod("SingleMemberDoubleArrEmptyParam", Y)); + checkSingleMemberBooleanArrEmptyParam(UnitTest.class.getMethod("SingleMemberBooleanArrEmptyParam", Y)); + checkSingleMemberStringArrEmptyParam(UnitTest.class.getMethod("SingleMemberStringArrEmptyParam", Y)); + checkSingleMemberClassArrEmptyParam(UnitTest.class.getMethod("SingleMemberClassArrEmptyParam", Y)); + checkSingleMemberEnumArrEmptyParam(UnitTest.class.getMethod("SingleMemberEnumArrEmptyParam", Y)); + + // SINGLE-MEMBER ARRAY TYPES Param(UnitTest.class.getMethod("ONE-ELEMENT ARRAY) ON PARAMETER + checkSingleMemberByteArrOneParam(UnitTest.class.getMethod("SingleMemberByteArrOneParam", Y)); + checkSingleMemberShortArrOneParam(UnitTest.class.getMethod("SingleMemberShortArrOneParam", Y)); + checkSingleMemberIntArrOneParam(UnitTest.class.getMethod("SingleMemberIntArrOneParam", Y)); + checkSingleMemberLongArrOneParam(UnitTest.class.getMethod("SingleMemberLongArrOneParam", Y)); + checkSingleMemberCharArrOneParam(UnitTest.class.getMethod("SingleMemberCharArrOneParam", Y)); + checkSingleMemberFloatArrOneParam(UnitTest.class.getMethod("SingleMemberFloatArrOneParam", Y)); + checkSingleMemberDoubleArrOneParam(UnitTest.class.getMethod("SingleMemberDoubleArrOneParam", Y)); + checkSingleMemberBooleanArrOneParam(UnitTest.class.getMethod("SingleMemberBooleanArrOneParam", Y)); + checkSingleMemberStringArrOneParam(UnitTest.class.getMethod("SingleMemberStringArrOneParam", Y)); + checkSingleMemberClassArrOneParam(UnitTest.class.getMethod("SingleMemberClassArrOneParam", Y)); + checkSingleMemberEnumArrOneParam(UnitTest.class.getMethod("SingleMemberEnumArrOneParam", Y)); + + // SINGLE-MEMBER ARRAY TYPES Param(UnitTest.class.getMethod("TWO-ELEMENT ARRAY) ON PARAMETER + checkSingleMemberByteArrTwoParam(UnitTest.class.getMethod("SingleMemberByteArrTwoParam", Y)); + checkSingleMemberShortArrTwoParam(UnitTest.class.getMethod("SingleMemberShortArrTwoParam", Y)); + checkSingleMemberIntArrTwoParam(UnitTest.class.getMethod("SingleMemberIntArrTwoParam", Y)); + checkSingleMemberLongArrTwoParam(UnitTest.class.getMethod("SingleMemberLongArrTwoParam", Y)); + checkSingleMemberCharArrTwoParam(UnitTest.class.getMethod("SingleMemberCharArrTwoParam", Y)); + checkSingleMemberFloatArrTwoParam(UnitTest.class.getMethod("SingleMemberFloatArrTwoParam", Y)); + checkSingleMemberDoubleArrTwoParam(UnitTest.class.getMethod("SingleMemberDoubleArrTwoParam", Y)); + checkSingleMemberBooleanArrTwoParam(UnitTest.class.getMethod("SingleMemberBooleanArrTwoParam", Y)); + checkSingleMemberStringArrTwoParam(UnitTest.class.getMethod("SingleMemberStringArrTwoParam", Y)); + checkSingleMemberClassArrTwoParam(UnitTest.class.getMethod("SingleMemberClassArrTwoParam", Y)); + checkSingleMemberEnumArrTwoParam(UnitTest.class.getMethod("SingleMemberEnumArrTwoParam", Y)); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT Param(UnitTest.class.getMethod("OVERRIDE)ON PARAMETER + checkSingleMemberByteArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberByteArrOvrdDefParam", Y)); + checkSingleMemberShortArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberShortArrOvrdDefParam", Y)); + checkSingleMemberIntArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberIntArrOvrdDefParam", Y)); + checkSingleMemberLongArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberLongArrOvrdDefParam", Y)); + checkSingleMemberCharArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberCharArrOvrdDefParam", Y)); + checkSingleMemberFloatArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberFloatArrOvrdDefParam", Y)); + checkSingleMemberDoubleArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberDoubleArrOvrdDefParam", Y)); + checkSingleMemberBooleanArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberBooleanArrOvrdDefParam", Y)); + checkSingleMemberStringArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberStringArrOvrdDefParam", Y)); + checkSingleMemberClassArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberClassArrOvrdDefParam", Y)); + checkSingleMemberEnumArrOvrdDefParam(UnitTest.class.getMethod("SingleMemberEnumArrOvrdDefParam", Y)); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT Param(UnitTest.class.getMethod("ACCEPT)ON PARAMETER + checkSingleMemberByteArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberByteArrAcceptDefParam", Y)); + checkSingleMemberShortArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberShortArrAcceptDefParam", Y)); + checkSingleMemberIntArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberIntArrAcceptDefParam", Y)); + checkSingleMemberLongArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberLongArrAcceptDefParam", Y)); + checkSingleMemberCharArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberCharArrAcceptDefParam", Y)); + checkSingleMemberFloatArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberFloatArrAcceptDefParam", Y)); + checkSingleMemberDoubleArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberDoubleArrAcceptDefParam", Y)); + checkSingleMemberBooleanArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberBooleanArrAcceptDefParam", Y)); + checkSingleMemberStringArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberStringArrAcceptDefParam", Y)); + checkSingleMemberClassArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberClassArrAcceptDefParam", Y)); + checkSingleMemberEnumArrAcceptDefParam(UnitTest.class.getMethod("SingleMemberEnumArrAcceptDefParam", Y)); + + // *** TESTS ON ANNOTATED CLASSES *** + + // MULTIMEMBER SCALAR TYPES ON CLASS + checkScalarTypes(scalarTypesClass.class); + checkScalarTypesOverrideDefault(scalarTypesOverrideDefaultClass.class); + checkScalarTypesAcceptDefault(scalarTypesAcceptDefaultClass.class); + + // MULTIMEMBER ARRAY TYPES ON CLASS + checkArrayTypes0(emptyArrayTypesClass.class); + checkArrayTypes1(singleElementArrayTypesClass.class); + checkArrayTypes2(twoElementArrayTypesClass.class); + checkArrayTypesOverrideDefault(arrayTypesOverrideDefaultClass.class); + checkArrayTypesAcceptDefault(arrayTypesAcceptDefaultClass.class); + + // MARKER TYPE ON CLASS + checkMarker(markerClass.class); + + // SINGLE-MEMBER SCALAR TYPES ON CLASS + checkSingleMemberByte(SingleMemberByteClass.class); + checkSingleMemberShort(SingleMemberShortClass.class); + checkSingleMemberInt(SingleMemberIntClass.class); + checkSingleMemberLong(SingleMemberLongClass.class); + checkSingleMemberChar(SingleMemberCharClass.class); + checkSingleMemberFloat(SingleMemberFloatClass.class); + checkSingleMemberDouble(SingleMemberDoubleClass.class); + checkSingleMemberBoolean(SingleMemberBooleanClass.class); + checkSingleMemberString(SingleMemberStringClass.class); + checkSingleMemberClass(SingleMemberClassClass.class); + checkSingleMemberEnum(SingleMemberEnumClass.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE ON CLASS + checkSingleMemberByteOvrdDef(SingleMemberByteOvrdDefClass.class); + checkSingleMemberShortOvrdDef(SingleMemberShortOvrdDefClass.class); + checkSingleMemberIntOvrdDef(SingleMemberIntOvrdDefClass.class); + checkSingleMemberLongOvrdDef(SingleMemberLongOvrdDefClass.class); + checkSingleMemberCharOvrdDef(SingleMemberCharOvrdDefClass.class); + checkSingleMemberFloatOvrdDef(SingleMemberFloatOvrdDefClass.class); + checkSingleMemberDoubleOvrdDef(SingleMemberDoubleOvrdDefClass.class); + checkSingleMemberBooleanOvrdDef(SingleMemberBooleanOvrdDefClass.class); + checkSingleMemberStringOvrdDef(SingleMemberStringOvrdDefClass.class); + checkSingleMemberClassOvrdDef(SingleMemberClassOvrdDefClass.class); + checkSingleMemberEnumOvrdDef(SingleMemberEnumOvrdDefClass.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT ON CLASS + checkSingleMemberByteAcceptDef(SingleMemberByteAcceptDefClass.class); + checkSingleMemberShortAcceptDef(SingleMemberShortAcceptDefClass.class); + checkSingleMemberIntAcceptDef(SingleMemberIntAcceptDefClass.class); + checkSingleMemberLongAcceptDef(SingleMemberLongAcceptDefClass.class); + checkSingleMemberCharAcceptDef(SingleMemberCharAcceptDefClass.class); + checkSingleMemberFloatAcceptDef(SingleMemberFloatAcceptDefClass.class); + checkSingleMemberDoubleAcceptDef(SingleMemberDoubleAcceptDefClass.class); + checkSingleMemberBooleanAcceptDef(SingleMemberBooleanAcceptDefClass.class); + checkSingleMemberStringAcceptDef(SingleMemberStringAcceptDefClass.class); + checkSingleMemberClassAcceptDef(SingleMemberClassAcceptDefClass.class); + checkSingleMemberEnumAcceptDef(SingleMemberEnumAcceptDefClass.class); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) ON CLASS + checkSingleMemberByteArrEmpty(SingleMemberByteArrEmptyClass.class); + checkSingleMemberShortArrEmpty(SingleMemberShortArrEmptyClass.class); + checkSingleMemberIntArrEmpty(SingleMemberIntArrEmptyClass.class); + checkSingleMemberLongArrEmpty(SingleMemberLongArrEmptyClass.class); + checkSingleMemberCharArrEmpty(SingleMemberCharArrEmptyClass.class); + checkSingleMemberFloatArrEmpty(SingleMemberFloatArrEmptyClass.class); + checkSingleMemberDoubleArrEmpty(SingleMemberDoubleArrEmptyClass.class); + checkSingleMemberBooleanArrEmpty(SingleMemberBooleanArrEmptyClass.class); + checkSingleMemberStringArrEmpty(SingleMemberStringArrEmptyClass.class); + checkSingleMemberClassArrEmpty(SingleMemberClassArrEmptyClass.class); + checkSingleMemberEnumArrEmpty(SingleMemberEnumArrEmptyClass.class); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) ON CLASS + checkSingleMemberByteArrOne(SingleMemberByteArrOneClass.class); + checkSingleMemberShortArrOne(SingleMemberShortArrOneClass.class); + checkSingleMemberIntArrOne(SingleMemberIntArrOneClass.class); + checkSingleMemberLongArrOne(SingleMemberLongArrOneClass.class); + checkSingleMemberCharArrOne(SingleMemberCharArrOneClass.class); + checkSingleMemberFloatArrOne(SingleMemberFloatArrOneClass.class); + checkSingleMemberDoubleArrOne(SingleMemberDoubleArrOneClass.class); + checkSingleMemberBooleanArrOne(SingleMemberBooleanArrOneClass.class); + checkSingleMemberStringArrOne(SingleMemberStringArrOneClass.class); + checkSingleMemberClassArrOne(SingleMemberClassArrOneClass.class); + checkSingleMemberEnumArrOne(SingleMemberEnumArrOneClass.class); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) ON CLASS + checkSingleMemberByteArrTwo(SingleMemberByteArrTwoClass.class); + checkSingleMemberShortArrTwo(SingleMemberShortArrTwoClass.class); + checkSingleMemberIntArrTwo(SingleMemberIntArrTwoClass.class); + checkSingleMemberLongArrTwo(SingleMemberLongArrTwoClass.class); + checkSingleMemberCharArrTwo(SingleMemberCharArrTwoClass.class); + checkSingleMemberFloatArrTwo(SingleMemberFloatArrTwoClass.class); + checkSingleMemberDoubleArrTwo(SingleMemberDoubleArrTwoClass.class); + checkSingleMemberBooleanArrTwo(SingleMemberBooleanArrTwoClass.class); + checkSingleMemberStringArrTwo(SingleMemberStringArrTwoClass.class); + checkSingleMemberClassArrTwo(SingleMemberClassArrTwoClass.class); + checkSingleMemberEnumArrTwo(SingleMemberEnumArrTwoClass.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE)ON CLASS + checkSingleMemberByteArrOvrdDef(SingleMemberByteArrOvrdDefClass.class); + checkSingleMemberShortArrOvrdDef(SingleMemberShortArrOvrdDefClass.class); + checkSingleMemberIntArrOvrdDef(SingleMemberIntArrOvrdDefClass.class); + checkSingleMemberLongArrOvrdDef(SingleMemberLongArrOvrdDefClass.class); + checkSingleMemberCharArrOvrdDef(SingleMemberCharArrOvrdDefClass.class); + checkSingleMemberFloatArrOvrdDef(SingleMemberFloatArrOvrdDefClass.class); + checkSingleMemberDoubleArrOvrdDef(SingleMemberDoubleArrOvrdDefClass.class); + checkSingleMemberBooleanArrOvrdDef(SingleMemberBooleanArrOvrdDefClass.class); + checkSingleMemberStringArrOvrdDef(SingleMemberStringArrOvrdDefClass.class); + checkSingleMemberClassArrOvrdDef(SingleMemberClassArrOvrdDefClass.class); + checkSingleMemberEnumArrOvrdDef(SingleMemberEnumArrOvrdDefClass.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT)ON CLASS + checkSingleMemberByteArrAcceptDef(SingleMemberByteArrAcceptDefClass.class); + checkSingleMemberShortArrAcceptDef(SingleMemberShortArrAcceptDefClass.class); + checkSingleMemberIntArrAcceptDef(SingleMemberIntArrAcceptDefClass.class); + checkSingleMemberLongArrAcceptDef(SingleMemberLongArrAcceptDefClass.class); + checkSingleMemberCharArrAcceptDef(SingleMemberCharArrAcceptDefClass.class); + checkSingleMemberFloatArrAcceptDef(SingleMemberFloatArrAcceptDefClass.class); + checkSingleMemberDoubleArrAcceptDef(SingleMemberDoubleArrAcceptDefClass.class); + checkSingleMemberBooleanArrAcceptDef(SingleMemberBooleanArrAcceptDefClass.class); + checkSingleMemberStringArrAcceptDef(SingleMemberStringArrAcceptDefClass.class); + checkSingleMemberClassArrAcceptDef(SingleMemberClassArrAcceptDefClass.class); + checkSingleMemberEnumArrAcceptDef(SingleMemberEnumArrAcceptDefClass.class); + + // *** TESTS FOR EQUALS AND HASHCODE - POSITIVE + + // MULTIMEMBER SCALAR TYPES + checkEquals(scalarTypesClass.class, UnitTest.class.getField("scalarTypesField"), + ScalarTypes.class); + checkEquals(scalarTypesOverrideDefaultClass.class, UnitTest.class.getField("scalarTypesOverrideDefaultField"), + ScalarTypesWithDefault.class); + checkEquals(scalarTypesAcceptDefaultClass.class, UnitTest.class.getField("scalarTypesAcceptDefaultField"), + ScalarTypesWithDefault.class); + + // MULTIMEMBER ARRAY TYPES + checkEquals(emptyArrayTypesClass.class, UnitTest.class.getField("emptyArrayTypesField"), + ArrayTypes.class); + checkEquals(singleElementArrayTypesClass.class, UnitTest.class.getField("singleElementArrayTypesField"), + ArrayTypes.class); + checkEquals(twoElementArrayTypesClass.class, UnitTest.class.getField("twoElementArrayTypesField"), + ArrayTypes.class); + checkEquals(arrayTypesOverrideDefaultClass.class, UnitTest.class.getField("arrayTypesOverrideDefaultField"), + ArrayTypesWithDefault.class); + checkEquals(arrayTypesAcceptDefaultClass.class, UnitTest.class.getField("arrayTypesAcceptDefaultField"), + ArrayTypesWithDefault.class); + + // MARKER TYPE + checkEquals(markerClass.class, UnitTest.class.getField("markerField"), + Marker.class); + + // SINGLE-MEMBER SCALAR TYPES + checkEquals(SingleMemberByteClass.class, UnitTest.class.getField("SingleMemberByteField"), + SingleMemberByte.class); + checkEquals(SingleMemberShortClass.class, UnitTest.class.getField("SingleMemberShortField"), + SingleMemberShort.class); + checkEquals(SingleMemberIntClass.class, UnitTest.class.getField("SingleMemberIntField"), + SingleMemberInt.class); + checkEquals(SingleMemberLongClass.class, UnitTest.class.getField("SingleMemberLongField"), + SingleMemberLong.class); + checkEquals(SingleMemberCharClass.class, UnitTest.class.getField("SingleMemberCharField"), + SingleMemberChar.class); + checkEquals(SingleMemberFloatClass.class, UnitTest.class.getField("SingleMemberFloatField"), + SingleMemberFloat.class); + checkEquals(SingleMemberDoubleClass.class, UnitTest.class.getField("SingleMemberDoubleField"), + SingleMemberDouble.class); + checkEquals(SingleMemberBooleanClass.class, UnitTest.class.getField("SingleMemberBooleanField"), + SingleMemberBoolean.class); + checkEquals(SingleMemberStringClass.class, UnitTest.class.getField("SingleMemberStringField"), + SingleMemberString.class); + checkEquals(SingleMemberClassClass.class, UnitTest.class.getField("SingleMemberClassField"), + SingleMemberClass.class); + checkEquals(SingleMemberEnumClass.class, UnitTest.class.getField("SingleMemberEnumField"), + SingleMemberEnum.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE + checkEquals(SingleMemberByteOvrdDefClass.class, UnitTest.class.getField("SingleMemberByteOvrdDefField"), + SingleMemberByteWithDef.class); + checkEquals(SingleMemberShortOvrdDefClass.class, UnitTest.class.getField("SingleMemberShortOvrdDefField"), + SingleMemberShortWithDef.class); + checkEquals(SingleMemberIntOvrdDefClass.class, UnitTest.class.getField("SingleMemberIntOvrdDefField"), + SingleMemberIntWithDef.class); + checkEquals(SingleMemberLongOvrdDefClass.class, UnitTest.class.getField("SingleMemberLongOvrdDefField"), + SingleMemberLongWithDef.class); + checkEquals(SingleMemberCharOvrdDefClass.class, UnitTest.class.getField("SingleMemberCharOvrdDefField"), + SingleMemberCharWithDef.class); + checkEquals(SingleMemberFloatOvrdDefClass.class, UnitTest.class.getField("SingleMemberFloatOvrdDefField"), + SingleMemberFloatWithDef.class); + checkEquals(SingleMemberDoubleOvrdDefClass.class, UnitTest.class.getField("SingleMemberDoubleOvrdDefField"), + SingleMemberDoubleWithDef.class); + checkEquals(SingleMemberBooleanOvrdDefClass.class, UnitTest.class.getField("SingleMemberBooleanOvrdDefField"), + SingleMemberBooleanWithDef.class); + checkEquals(SingleMemberStringOvrdDefClass.class, UnitTest.class.getField("SingleMemberStringOvrdDefField"), + SingleMemberStringWithDef.class); + checkEquals(SingleMemberClassOvrdDefClass.class, UnitTest.class.getField("SingleMemberClassOvrdDefField"), + SingleMemberClassWithDef.class); + checkEquals(SingleMemberEnumOvrdDefClass.class, UnitTest.class.getField("SingleMemberEnumOvrdDefField"), + SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT + checkEquals(SingleMemberByteAcceptDefClass.class, UnitTest.class.getField("SingleMemberByteAcceptDefField"), + SingleMemberByteWithDef.class); + checkEquals(SingleMemberShortAcceptDefClass.class, UnitTest.class.getField("SingleMemberShortAcceptDefField"), + SingleMemberShortWithDef.class); + checkEquals(SingleMemberIntAcceptDefClass.class, UnitTest.class.getField("SingleMemberIntAcceptDefField"), + SingleMemberIntWithDef.class); + checkEquals(SingleMemberLongAcceptDefClass.class, UnitTest.class.getField("SingleMemberLongAcceptDefField"), + SingleMemberLongWithDef.class); + checkEquals(SingleMemberCharAcceptDefClass.class, UnitTest.class.getField("SingleMemberCharAcceptDefField"), + SingleMemberCharWithDef.class); + checkEquals(SingleMemberFloatAcceptDefClass.class, UnitTest.class.getField("SingleMemberFloatAcceptDefField"), + SingleMemberFloatWithDef.class); + checkEquals(SingleMemberDoubleAcceptDefClass.class, UnitTest.class.getField("SingleMemberDoubleAcceptDefField"), + SingleMemberDoubleWithDef.class); + checkEquals(SingleMemberBooleanAcceptDefClass.class, UnitTest.class.getField("SingleMemberBooleanAcceptDefField"), + SingleMemberBooleanWithDef.class); + checkEquals(SingleMemberStringAcceptDefClass.class, UnitTest.class.getField("SingleMemberStringAcceptDefField"), + SingleMemberStringWithDef.class); + checkEquals(SingleMemberClassAcceptDefClass.class, UnitTest.class.getField("SingleMemberClassAcceptDefField"), + SingleMemberClassWithDef.class); + checkEquals(SingleMemberEnumAcceptDefClass.class, UnitTest.class.getField("SingleMemberEnumAcceptDefField"), + SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) + checkEquals(SingleMemberByteArrEmptyClass.class, UnitTest.class.getField("SingleMemberByteArrEmptyField"), + SingleMemberByteArray.class); + checkEquals(SingleMemberShortArrEmptyClass.class, UnitTest.class.getField("SingleMemberShortArrEmptyField"), + SingleMemberShortArray.class); + checkEquals(SingleMemberIntArrEmptyClass.class, UnitTest.class.getField("SingleMemberIntArrEmptyField"), + SingleMemberIntArray.class); + checkEquals(SingleMemberLongArrEmptyClass.class, UnitTest.class.getField("SingleMemberLongArrEmptyField"), + SingleMemberLongArray.class); + checkEquals(SingleMemberCharArrEmptyClass.class, UnitTest.class.getField("SingleMemberCharArrEmptyField"), + SingleMemberCharArray.class); + checkEquals(SingleMemberFloatArrEmptyClass.class, UnitTest.class.getField("SingleMemberFloatArrEmptyField"), + SingleMemberFloatArray.class); + checkEquals(SingleMemberDoubleArrEmptyClass.class, UnitTest.class.getField("SingleMemberDoubleArrEmptyField"), + SingleMemberDoubleArray.class); + checkEquals(SingleMemberBooleanArrEmptyClass.class, UnitTest.class.getField("SingleMemberBooleanArrEmptyField"), + SingleMemberBooleanArray.class); + checkEquals(SingleMemberStringArrEmptyClass.class, UnitTest.class.getField("SingleMemberStringArrEmptyField"), + SingleMemberStringArray.class); + checkEquals(SingleMemberClassArrEmptyClass.class, UnitTest.class.getField("SingleMemberClassArrEmptyField"), + SingleMemberClassArray.class); + checkEquals(SingleMemberEnumArrEmptyClass.class, UnitTest.class.getField("SingleMemberEnumArrEmptyField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) + checkEquals(SingleMemberByteArrOneClass.class, UnitTest.class.getField("SingleMemberByteArrOneField"), + SingleMemberByteArray.class); + checkEquals(SingleMemberShortArrOneClass.class, UnitTest.class.getField("SingleMemberShortArrOneField"), + SingleMemberShortArray.class); + checkEquals(SingleMemberIntArrOneClass.class, UnitTest.class.getField("SingleMemberIntArrOneField"), + SingleMemberIntArray.class); + checkEquals(SingleMemberLongArrOneClass.class, UnitTest.class.getField("SingleMemberLongArrOneField"), + SingleMemberLongArray.class); + checkEquals(SingleMemberCharArrOneClass.class, UnitTest.class.getField("SingleMemberCharArrOneField"), + SingleMemberCharArray.class); + checkEquals(SingleMemberFloatArrOneClass.class, UnitTest.class.getField("SingleMemberFloatArrOneField"), + SingleMemberFloatArray.class); + checkEquals(SingleMemberDoubleArrOneClass.class, UnitTest.class.getField("SingleMemberDoubleArrOneField"), + SingleMemberDoubleArray.class); + checkEquals(SingleMemberBooleanArrOneClass.class, UnitTest.class.getField("SingleMemberBooleanArrOneField"), + SingleMemberBooleanArray.class); + checkEquals(SingleMemberStringArrOneClass.class, UnitTest.class.getField("SingleMemberStringArrOneField"), + SingleMemberStringArray.class); + checkEquals(SingleMemberClassArrOneClass.class, UnitTest.class.getField("SingleMemberClassArrOneField"), + SingleMemberClassArray.class); + checkEquals(SingleMemberEnumArrOneClass.class, UnitTest.class.getField("SingleMemberEnumArrOneField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) + checkEquals(SingleMemberByteArrTwoClass.class, UnitTest.class.getField("SingleMemberByteArrTwoField"), + SingleMemberByteArray.class); + checkEquals(SingleMemberShortArrTwoClass.class, UnitTest.class.getField("SingleMemberShortArrTwoField"), + SingleMemberShortArray.class); + checkEquals(SingleMemberIntArrTwoClass.class, UnitTest.class.getField("SingleMemberIntArrTwoField"), + SingleMemberIntArray.class); + checkEquals(SingleMemberLongArrTwoClass.class, UnitTest.class.getField("SingleMemberLongArrTwoField"), + SingleMemberLongArray.class); + checkEquals(SingleMemberCharArrTwoClass.class, UnitTest.class.getField("SingleMemberCharArrTwoField"), + SingleMemberCharArray.class); + checkEquals(SingleMemberFloatArrTwoClass.class, UnitTest.class.getField("SingleMemberFloatArrTwoField"), + SingleMemberFloatArray.class); + checkEquals(SingleMemberDoubleArrTwoClass.class, UnitTest.class.getField("SingleMemberDoubleArrTwoField"), + SingleMemberDoubleArray.class); + checkEquals(SingleMemberBooleanArrTwoClass.class, UnitTest.class.getField("SingleMemberBooleanArrTwoField"), + SingleMemberBooleanArray.class); + checkEquals(SingleMemberStringArrTwoClass.class, UnitTest.class.getField("SingleMemberStringArrTwoField"), + SingleMemberStringArray.class); + checkEquals(SingleMemberClassArrTwoClass.class, UnitTest.class.getField("SingleMemberClassArrTwoField"), + SingleMemberClassArray.class); + checkEquals(SingleMemberEnumArrTwoClass.class, UnitTest.class.getField("SingleMemberEnumArrTwoField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE) + checkEquals(SingleMemberByteArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberByteArrOvrdDefField"), + SingleMemberByteArrayDef.class); + checkEquals(SingleMemberShortArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberShortArrOvrdDefField"), + SingleMemberShortArrayDef.class); + checkEquals(SingleMemberIntArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberIntArrOvrdDefField"), + SingleMemberIntArrayDef.class); + checkEquals(SingleMemberLongArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberLongArrOvrdDefField"), + SingleMemberLongArrayDef.class); + checkEquals(SingleMemberCharArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberCharArrOvrdDefField"), + SingleMemberCharArrayDef.class); + checkEquals(SingleMemberFloatArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberFloatArrOvrdDefField"), + SingleMemberFloatArrayDef.class); + checkEquals(SingleMemberDoubleArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberDoubleArrOvrdDefField"), + SingleMemberDoubleArrayDef.class); + checkEquals(SingleMemberBooleanArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberBooleanArrOvrdDefField"), + SingleMemberBooleanArrayDef.class); + checkEquals(SingleMemberStringArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberStringArrOvrdDefField"), + SingleMemberStringArrayDef.class); + checkEquals(SingleMemberClassArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberClassArrOvrdDefField"), + SingleMemberClassArrayDef.class); + checkEquals(SingleMemberEnumArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberEnumArrOvrdDefField"), + SingleMemberEnumArrayDef.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT) + checkEquals(SingleMemberByteArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberByteArrAcceptDefField"), + SingleMemberByteArrayDef.class); + checkEquals(SingleMemberShortArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberShortArrAcceptDefField"), + SingleMemberShortArrayDef.class); + checkEquals(SingleMemberIntArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberIntArrAcceptDefField"), + SingleMemberIntArrayDef.class); + checkEquals(SingleMemberLongArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberLongArrAcceptDefField"), + SingleMemberLongArrayDef.class); + checkEquals(SingleMemberCharArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberCharArrAcceptDefField"), + SingleMemberCharArrayDef.class); + checkEquals(SingleMemberFloatArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberFloatArrAcceptDefField"), + SingleMemberFloatArrayDef.class); + checkEquals(SingleMemberDoubleArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberDoubleArrAcceptDefField"), + SingleMemberDoubleArrayDef.class); + checkEquals(SingleMemberBooleanArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberBooleanArrAcceptDefField"), + SingleMemberBooleanArrayDef.class); + checkEquals(SingleMemberStringArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberStringArrAcceptDefField"), + SingleMemberStringArrayDef.class); + checkEquals(SingleMemberClassArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberClassArrAcceptDefField"), + SingleMemberClassArrayDef.class); + checkEquals(SingleMemberEnumArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberEnumArrAcceptDefField"), + SingleMemberEnumArrayDef.class); + + // *** TESTS FOR EQUALS AND HASHCODE - NEGATIVE + + // MULTIMEMBER SCALAR TYPES + checkUnequals(scalarTypesOverrideDefaultClass.class, UnitTest.class.getField("scalarTypesAcceptDefaultField"), + ScalarTypesWithDefault.class); + checkUnequals(scalarTypesAcceptDefaultClass.class, UnitTest.class.getField("scalarTypesOverrideDefaultField"), + ScalarTypesWithDefault.class); + + // MULTIMEMBER ARRAY TYPES + checkUnequals(emptyArrayTypesClass.class, UnitTest.class.getField("singleElementArrayTypesField"), + ArrayTypes.class); + checkUnequals(singleElementArrayTypesClass.class, UnitTest.class.getField("twoElementArrayTypesField"), + ArrayTypes.class); + checkUnequals(twoElementArrayTypesClass.class, UnitTest.class.getField("singleElementArrayTypesField"), + ArrayTypes.class); + checkUnequals(arrayTypesOverrideDefaultClass.class, UnitTest.class.getField("arrayTypesAcceptDefaultField"), + ArrayTypesWithDefault.class); + checkUnequals(arrayTypesAcceptDefaultClass.class, UnitTest.class.getField("arrayTypesOverrideDefaultField"), + ArrayTypesWithDefault.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE + checkUnequals(SingleMemberByteOvrdDefClass.class, UnitTest.class.getField("SingleMemberByteAcceptDefField"), + SingleMemberByteWithDef.class); + checkUnequals(SingleMemberShortOvrdDefClass.class, UnitTest.class.getField("SingleMemberShortAcceptDefField"), + SingleMemberShortWithDef.class); + checkUnequals(SingleMemberIntOvrdDefClass.class, UnitTest.class.getField("SingleMemberIntAcceptDefField"), + SingleMemberIntWithDef.class); + checkUnequals(SingleMemberLongOvrdDefClass.class, UnitTest.class.getField("SingleMemberLongAcceptDefField"), + SingleMemberLongWithDef.class); + checkUnequals(SingleMemberCharOvrdDefClass.class, UnitTest.class.getField("SingleMemberCharAcceptDefField"), + SingleMemberCharWithDef.class); + checkUnequals(SingleMemberFloatOvrdDefClass.class, UnitTest.class.getField("SingleMemberFloatAcceptDefField"), + SingleMemberFloatWithDef.class); + checkUnequals(SingleMemberDoubleOvrdDefClass.class, UnitTest.class.getField("SingleMemberDoubleAcceptDefField"), + SingleMemberDoubleWithDef.class); + checkUnequals(SingleMemberBooleanOvrdDefClass.class, UnitTest.class.getField("SingleMemberBooleanAcceptDefField"), + SingleMemberBooleanWithDef.class); + checkUnequals(SingleMemberStringOvrdDefClass.class, UnitTest.class.getField("SingleMemberStringAcceptDefField"), + SingleMemberStringWithDef.class); + checkUnequals(SingleMemberClassOvrdDefClass.class, UnitTest.class.getField("SingleMemberClassAcceptDefField"), + SingleMemberClassWithDef.class); + checkUnequals(SingleMemberEnumOvrdDefClass.class, UnitTest.class.getField("SingleMemberEnumAcceptDefField"), + SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT + checkUnequals(SingleMemberByteAcceptDefClass.class, UnitTest.class.getField("SingleMemberByteOvrdDefField"), + SingleMemberByteWithDef.class); + checkUnequals(SingleMemberShortAcceptDefClass.class, UnitTest.class.getField("SingleMemberShortOvrdDefField"), + SingleMemberShortWithDef.class); + checkUnequals(SingleMemberIntAcceptDefClass.class, UnitTest.class.getField("SingleMemberIntOvrdDefField"), + SingleMemberIntWithDef.class); + checkUnequals(SingleMemberLongAcceptDefClass.class, UnitTest.class.getField("SingleMemberLongOvrdDefField"), + SingleMemberLongWithDef.class); + checkUnequals(SingleMemberCharAcceptDefClass.class, UnitTest.class.getField("SingleMemberCharOvrdDefField"), + SingleMemberCharWithDef.class); + checkUnequals(SingleMemberFloatAcceptDefClass.class, UnitTest.class.getField("SingleMemberFloatOvrdDefField"), + SingleMemberFloatWithDef.class); + checkUnequals(SingleMemberDoubleAcceptDefClass.class, UnitTest.class.getField("SingleMemberDoubleOvrdDefField"), + SingleMemberDoubleWithDef.class); + checkUnequals(SingleMemberBooleanAcceptDefClass.class, UnitTest.class.getField("SingleMemberBooleanOvrdDefField"), + SingleMemberBooleanWithDef.class); + checkUnequals(SingleMemberStringAcceptDefClass.class, UnitTest.class.getField("SingleMemberStringOvrdDefField"), + SingleMemberStringWithDef.class); + checkUnequals(SingleMemberClassAcceptDefClass.class, UnitTest.class.getField("SingleMemberClassOvrdDefField"), + SingleMemberClassWithDef.class); + checkUnequals(SingleMemberEnumAcceptDefClass.class, UnitTest.class.getField("SingleMemberEnumOvrdDefField"), + SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) + checkUnequals(SingleMemberByteArrEmptyClass.class, UnitTest.class.getField("SingleMemberByteArrOneField"), + SingleMemberByteArray.class); + checkUnequals(SingleMemberShortArrEmptyClass.class, UnitTest.class.getField("SingleMemberShortArrOneField"), + SingleMemberShortArray.class); + checkUnequals(SingleMemberIntArrEmptyClass.class, UnitTest.class.getField("SingleMemberIntArrOneField"), + SingleMemberIntArray.class); + checkUnequals(SingleMemberLongArrEmptyClass.class, UnitTest.class.getField("SingleMemberLongArrOneField"), + SingleMemberLongArray.class); + checkUnequals(SingleMemberCharArrEmptyClass.class, UnitTest.class.getField("SingleMemberCharArrOneField"), + SingleMemberCharArray.class); + checkUnequals(SingleMemberFloatArrEmptyClass.class, UnitTest.class.getField("SingleMemberFloatArrOneField"), + SingleMemberFloatArray.class); + checkUnequals(SingleMemberDoubleArrEmptyClass.class, UnitTest.class.getField("SingleMemberDoubleArrOneField"), + SingleMemberDoubleArray.class); + checkUnequals(SingleMemberBooleanArrEmptyClass.class, UnitTest.class.getField("SingleMemberBooleanArrOneField"), + SingleMemberBooleanArray.class); + checkUnequals(SingleMemberStringArrEmptyClass.class, UnitTest.class.getField("SingleMemberStringArrOneField"), + SingleMemberStringArray.class); + checkUnequals(SingleMemberClassArrEmptyClass.class, UnitTest.class.getField("SingleMemberClassArrOneField"), + SingleMemberClassArray.class); + checkUnequals(SingleMemberEnumArrEmptyClass.class, UnitTest.class.getField("SingleMemberEnumArrOneField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) + checkUnequals(SingleMemberByteArrOneClass.class, UnitTest.class.getField("SingleMemberByteArrTwoField"), + SingleMemberByteArray.class); + checkUnequals(SingleMemberShortArrOneClass.class, UnitTest.class.getField("SingleMemberShortArrTwoField"), + SingleMemberShortArray.class); + checkUnequals(SingleMemberIntArrOneClass.class, UnitTest.class.getField("SingleMemberIntArrTwoField"), + SingleMemberIntArray.class); + checkUnequals(SingleMemberLongArrOneClass.class, UnitTest.class.getField("SingleMemberLongArrTwoField"), + SingleMemberLongArray.class); + checkUnequals(SingleMemberCharArrOneClass.class, UnitTest.class.getField("SingleMemberCharArrTwoField"), + SingleMemberCharArray.class); + checkUnequals(SingleMemberFloatArrOneClass.class, UnitTest.class.getField("SingleMemberFloatArrTwoField"), + SingleMemberFloatArray.class); + checkUnequals(SingleMemberDoubleArrOneClass.class, UnitTest.class.getField("SingleMemberDoubleArrTwoField"), + SingleMemberDoubleArray.class); + checkUnequals(SingleMemberBooleanArrOneClass.class, UnitTest.class.getField("SingleMemberBooleanArrTwoField"), + SingleMemberBooleanArray.class); + checkUnequals(SingleMemberStringArrOneClass.class, UnitTest.class.getField("SingleMemberStringArrTwoField"), + SingleMemberStringArray.class); + checkUnequals(SingleMemberClassArrOneClass.class, UnitTest.class.getField("SingleMemberClassArrTwoField"), + SingleMemberClassArray.class); + checkUnequals(SingleMemberEnumArrOneClass.class, UnitTest.class.getField("SingleMemberEnumArrTwoField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) + checkUnequals(SingleMemberByteArrTwoClass.class, UnitTest.class.getField("SingleMemberByteArrOneField"), + SingleMemberByteArray.class); + checkUnequals(SingleMemberShortArrTwoClass.class, UnitTest.class.getField("SingleMemberShortArrOneField"), + SingleMemberShortArray.class); + checkUnequals(SingleMemberIntArrTwoClass.class, UnitTest.class.getField("SingleMemberIntArrOneField"), + SingleMemberIntArray.class); + checkUnequals(SingleMemberLongArrTwoClass.class, UnitTest.class.getField("SingleMemberLongArrOneField"), + SingleMemberLongArray.class); + checkUnequals(SingleMemberCharArrTwoClass.class, UnitTest.class.getField("SingleMemberCharArrOneField"), + SingleMemberCharArray.class); + checkUnequals(SingleMemberFloatArrTwoClass.class, UnitTest.class.getField("SingleMemberFloatArrOneField"), + SingleMemberFloatArray.class); + checkUnequals(SingleMemberDoubleArrTwoClass.class, UnitTest.class.getField("SingleMemberDoubleArrOneField"), + SingleMemberDoubleArray.class); + checkUnequals(SingleMemberBooleanArrTwoClass.class, UnitTest.class.getField("SingleMemberBooleanArrOneField"), + SingleMemberBooleanArray.class); + checkUnequals(SingleMemberStringArrTwoClass.class, UnitTest.class.getField("SingleMemberStringArrOneField"), + SingleMemberStringArray.class); + checkUnequals(SingleMemberClassArrTwoClass.class, UnitTest.class.getField("SingleMemberClassArrOneField"), + SingleMemberClassArray.class); + checkUnequals(SingleMemberEnumArrTwoClass.class, UnitTest.class.getField("SingleMemberEnumArrOneField"), + SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE) + checkUnequals(SingleMemberByteArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberByteArrAcceptDefField"), + SingleMemberByteArrayDef.class); + checkUnequals(SingleMemberShortArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberShortArrAcceptDefField"), + SingleMemberShortArrayDef.class); + checkUnequals(SingleMemberIntArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberIntArrAcceptDefField"), + SingleMemberIntArrayDef.class); + checkUnequals(SingleMemberLongArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberLongArrAcceptDefField"), + SingleMemberLongArrayDef.class); + checkUnequals(SingleMemberCharArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberCharArrAcceptDefField"), + SingleMemberCharArrayDef.class); + checkUnequals(SingleMemberFloatArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberFloatArrAcceptDefField"), + SingleMemberFloatArrayDef.class); + checkUnequals(SingleMemberDoubleArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberDoubleArrAcceptDefField"), + SingleMemberDoubleArrayDef.class); + checkUnequals(SingleMemberBooleanArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberBooleanArrAcceptDefField"), + SingleMemberBooleanArrayDef.class); + checkUnequals(SingleMemberStringArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberStringArrAcceptDefField"), + SingleMemberStringArrayDef.class); + checkUnequals(SingleMemberClassArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberClassArrAcceptDefField"), + SingleMemberClassArrayDef.class); + checkUnequals(SingleMemberEnumArrOvrdDefClass.class, UnitTest.class.getField("SingleMemberEnumArrAcceptDefField"), + SingleMemberEnumArrayDef.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT) + checkUnequals(SingleMemberByteArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberByteArrOvrdDefField"), + SingleMemberByteArrayDef.class); + checkUnequals(SingleMemberShortArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberShortArrOvrdDefField"), + SingleMemberShortArrayDef.class); + checkUnequals(SingleMemberIntArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberIntArrOvrdDefField"), + SingleMemberIntArrayDef.class); + checkUnequals(SingleMemberLongArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberLongArrOvrdDefField"), + SingleMemberLongArrayDef.class); + checkUnequals(SingleMemberCharArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberCharArrOvrdDefField"), + SingleMemberCharArrayDef.class); + checkUnequals(SingleMemberFloatArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberFloatArrOvrdDefField"), + SingleMemberFloatArrayDef.class); + checkUnequals(SingleMemberDoubleArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberDoubleArrOvrdDefField"), + SingleMemberDoubleArrayDef.class); + checkUnequals(SingleMemberBooleanArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberBooleanArrOvrdDefField"), + SingleMemberBooleanArrayDef.class); + checkUnequals(SingleMemberStringArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberStringArrOvrdDefField"), + SingleMemberStringArrayDef.class); + checkUnequals(SingleMemberClassArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberClassArrOvrdDefField"), + SingleMemberClassArrayDef.class); + checkUnequals(SingleMemberEnumArrAcceptDefClass.class, UnitTest.class.getField("SingleMemberEnumArrOvrdDefField"), + SingleMemberEnumArrayDef.class); + + // *** TESTS FOR SERIALIZATION AND DESERIALIZATION + + // MULTIMEMBER SCALAR TYPES + checkSerialization(scalarTypesClass.class, ScalarTypes.class); + checkSerialization(scalarTypesOverrideDefaultClass.class, ScalarTypesWithDefault.class); + checkSerialization(scalarTypesAcceptDefaultClass.class, ScalarTypesWithDefault.class); + + // MULTIMEMBER ARRAY TYPES + checkSerialization(emptyArrayTypesClass.class, ArrayTypes.class); + checkSerialization(singleElementArrayTypesClass.class, ArrayTypes.class); + checkSerialization(twoElementArrayTypesClass.class, ArrayTypes.class); + checkSerialization(arrayTypesOverrideDefaultClass.class, ArrayTypesWithDefault.class); + checkSerialization(arrayTypesAcceptDefaultClass.class, ArrayTypesWithDefault.class); + + // MARKER TYPE + checkSerialization(markerClass.class, Marker.class); + + // SINGLE-MEMBER SCALAR TYPES + checkSerialization(SingleMemberByteClass.class, SingleMemberByte.class); + checkSerialization(SingleMemberShortClass.class, SingleMemberShort.class); + checkSerialization(SingleMemberIntClass.class, SingleMemberInt.class); + checkSerialization(SingleMemberLongClass.class, SingleMemberLong.class); + checkSerialization(SingleMemberCharClass.class, SingleMemberChar.class); + checkSerialization(SingleMemberFloatClass.class, SingleMemberFloat.class); + checkSerialization(SingleMemberDoubleClass.class, SingleMemberDouble.class); + checkSerialization(SingleMemberBooleanClass.class, SingleMemberBoolean.class); + checkSerialization(SingleMemberStringClass.class, SingleMemberString.class); + checkSerialization(SingleMemberClassClass.class, SingleMemberClass.class); + checkSerialization(SingleMemberEnumClass.class, SingleMemberEnum.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-OVERRIDE + checkSerialization(SingleMemberByteOvrdDefClass.class, SingleMemberByteWithDef.class); + checkSerialization(SingleMemberShortOvrdDefClass.class, SingleMemberShortWithDef.class); + checkSerialization(SingleMemberIntOvrdDefClass.class, SingleMemberIntWithDef.class); + checkSerialization(SingleMemberLongOvrdDefClass.class, SingleMemberLongWithDef.class); + checkSerialization(SingleMemberCharOvrdDefClass.class, SingleMemberCharWithDef.class); + checkSerialization(SingleMemberFloatOvrdDefClass.class, SingleMemberFloatWithDef.class); + checkSerialization(SingleMemberDoubleOvrdDefClass.class, SingleMemberDoubleWithDef.class); + checkSerialization(SingleMemberBooleanOvrdDefClass.class, SingleMemberBooleanWithDef.class); + checkSerialization(SingleMemberStringOvrdDefClass.class, SingleMemberStringWithDef.class); + checkSerialization(SingleMemberClassOvrdDefClass.class, SingleMemberClassWithDef.class); + checkSerialization(SingleMemberEnumOvrdDefClass.class, SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER SCALAR TYPES WITH DEFAULT-ACCEPT + checkSerialization(SingleMemberByteAcceptDefClass.class, SingleMemberByteWithDef.class); + checkSerialization(SingleMemberShortAcceptDefClass.class, SingleMemberShortWithDef.class); + checkSerialization(SingleMemberIntAcceptDefClass.class, SingleMemberIntWithDef.class); + checkSerialization(SingleMemberLongAcceptDefClass.class, SingleMemberLongWithDef.class); + checkSerialization(SingleMemberCharAcceptDefClass.class, SingleMemberCharWithDef.class); + checkSerialization(SingleMemberFloatAcceptDefClass.class, SingleMemberFloatWithDef.class); + checkSerialization(SingleMemberDoubleAcceptDefClass.class, SingleMemberDoubleWithDef.class); + checkSerialization(SingleMemberBooleanAcceptDefClass.class, SingleMemberBooleanWithDef.class); + checkSerialization(SingleMemberStringAcceptDefClass.class, SingleMemberStringWithDef.class); + checkSerialization(SingleMemberClassAcceptDefClass.class, SingleMemberClassWithDef.class); + checkSerialization(SingleMemberEnumAcceptDefClass.class, SingleMemberEnumWithDef.class); + + // SINGLE-MEMBER ARRAY TYPES (EMPTY ARRAY) + checkSerialization(SingleMemberByteArrEmptyClass.class, SingleMemberByteArray.class); + checkSerialization(SingleMemberShortArrEmptyClass.class, SingleMemberShortArray.class); + checkSerialization(SingleMemberIntArrEmptyClass.class, SingleMemberIntArray.class); + checkSerialization(SingleMemberLongArrEmptyClass.class, SingleMemberLongArray.class); + checkSerialization(SingleMemberCharArrEmptyClass.class, SingleMemberCharArray.class); + checkSerialization(SingleMemberFloatArrEmptyClass.class, SingleMemberFloatArray.class); + checkSerialization(SingleMemberDoubleArrEmptyClass.class, SingleMemberDoubleArray.class); + checkSerialization(SingleMemberBooleanArrEmptyClass.class, SingleMemberBooleanArray.class); + checkSerialization(SingleMemberStringArrEmptyClass.class, SingleMemberStringArray.class); + checkSerialization(SingleMemberClassArrEmptyClass.class, SingleMemberClassArray.class); + checkSerialization(SingleMemberEnumArrEmptyClass.class, SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (ONE-ELEMENT ARRAY) + checkSerialization(SingleMemberByteArrOneClass.class, SingleMemberByteArray.class); + checkSerialization(SingleMemberShortArrOneClass.class, SingleMemberShortArray.class); + checkSerialization(SingleMemberIntArrOneClass.class, SingleMemberIntArray.class); + checkSerialization(SingleMemberLongArrOneClass.class, SingleMemberLongArray.class); + checkSerialization(SingleMemberCharArrOneClass.class, SingleMemberCharArray.class); + checkSerialization(SingleMemberFloatArrOneClass.class, SingleMemberFloatArray.class); + checkSerialization(SingleMemberDoubleArrOneClass.class, SingleMemberDoubleArray.class); + checkSerialization(SingleMemberBooleanArrOneClass.class, SingleMemberBooleanArray.class); + checkSerialization(SingleMemberStringArrOneClass.class, SingleMemberStringArray.class); + checkSerialization(SingleMemberClassArrOneClass.class, SingleMemberClassArray.class); + checkSerialization(SingleMemberEnumArrOneClass.class, SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES (TWO-ELEMENT ARRAY) + checkSerialization(SingleMemberByteArrTwoClass.class, SingleMemberByteArray.class); + checkSerialization(SingleMemberShortArrTwoClass.class, SingleMemberShortArray.class); + checkSerialization(SingleMemberIntArrTwoClass.class, SingleMemberIntArray.class); + checkSerialization(SingleMemberLongArrTwoClass.class, SingleMemberLongArray.class); + checkSerialization(SingleMemberCharArrTwoClass.class, SingleMemberCharArray.class); + checkSerialization(SingleMemberFloatArrTwoClass.class, SingleMemberFloatArray.class); + checkSerialization(SingleMemberDoubleArrTwoClass.class, SingleMemberDoubleArray.class); + checkSerialization(SingleMemberBooleanArrTwoClass.class, SingleMemberBooleanArray.class); + checkSerialization(SingleMemberStringArrTwoClass.class, SingleMemberStringArray.class); + checkSerialization(SingleMemberClassArrTwoClass.class, SingleMemberClassArray.class); + checkSerialization(SingleMemberEnumArrTwoClass.class, SingleMemberEnumArray.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (OVERRIDE) + checkSerialization(SingleMemberByteArrOvrdDefClass.class, SingleMemberByteArrayDef.class); + checkSerialization(SingleMemberShortArrOvrdDefClass.class, SingleMemberShortArrayDef.class); + checkSerialization(SingleMemberIntArrOvrdDefClass.class, SingleMemberIntArrayDef.class); + checkSerialization(SingleMemberLongArrOvrdDefClass.class, SingleMemberLongArrayDef.class); + checkSerialization(SingleMemberCharArrOvrdDefClass.class, SingleMemberCharArrayDef.class); + checkSerialization(SingleMemberFloatArrOvrdDefClass.class, SingleMemberFloatArrayDef.class); + checkSerialization(SingleMemberDoubleArrOvrdDefClass.class, SingleMemberDoubleArrayDef.class); + checkSerialization(SingleMemberBooleanArrOvrdDefClass.class, SingleMemberBooleanArrayDef.class); + checkSerialization(SingleMemberStringArrOvrdDefClass.class, SingleMemberStringArrayDef.class); + checkSerialization(SingleMemberClassArrOvrdDefClass.class, SingleMemberClassArrayDef.class); + checkSerialization(SingleMemberEnumArrOvrdDefClass.class, SingleMemberEnumArrayDef.class); + + // SINGLE-MEMBER ARRAY TYPES WITH DEFAULT (ACCEPT) + checkSerialization(SingleMemberByteArrAcceptDefClass.class, SingleMemberByteArrayDef.class); + checkSerialization(SingleMemberShortArrAcceptDefClass.class, SingleMemberShortArrayDef.class); + checkSerialization(SingleMemberIntArrAcceptDefClass.class, SingleMemberIntArrayDef.class); + checkSerialization(SingleMemberLongArrAcceptDefClass.class, SingleMemberLongArrayDef.class); + checkSerialization(SingleMemberCharArrAcceptDefClass.class, SingleMemberCharArrayDef.class); + checkSerialization(SingleMemberFloatArrAcceptDefClass.class, SingleMemberFloatArrayDef.class); + checkSerialization(SingleMemberDoubleArrAcceptDefClass.class, SingleMemberDoubleArrayDef.class); + checkSerialization(SingleMemberBooleanArrAcceptDefClass.class, SingleMemberBooleanArrayDef.class); + checkSerialization(SingleMemberStringArrAcceptDefClass.class, SingleMemberStringArrayDef.class); + checkSerialization(SingleMemberClassArrAcceptDefClass.class, SingleMemberClassArrayDef.class); + checkSerialization(SingleMemberEnumArrAcceptDefClass.class, SingleMemberEnumArrayDef.class); + + // *** TESTS FOR ANNOTATION INHERITANCE AND ENUMERATING DECLARED ANNOTATIONS + + // Inheritance tests + checkInheritence(Grandpa.class, true, true); + checkInheritence(Dad.class, true, false); + checkInheritence(Son.class, true, true); + + // Declared annotations tests + checkDeclaredAnnotations(Grandpa.class, true, true); + checkDeclaredAnnotations(Dad.class, false, false); + checkDeclaredAnnotations(Son.class, false, true); + + // Generate summary + System.out.println("\n" + numTests + " tests completed"); + if (failCount != 0) + throw new Exception("Failure count: " + failCount); + else + System.out.println("Success."); + } + + static int failCount = 0; + + private static void fail(String test) { + System.out.println("Failure: " + test); + failCount++; + } + + // ANNOTATION-VERIFICATION METHODS + + // Scalar multi-member + + static void checkScalarTypes(AnnotatedElement e) { + try { + checkScalarTypes(e.getAnnotation(ScalarTypes.class), e); + } catch(Throwable t) { + fail("ScalarTypes " + e + ": " + t); + t.printStackTrace(); + } + } + + static void checkScalarTypes(ScalarTypes st, AnnotatedElement e) throws Exception { + numTests++; + if (!(st.b() == 1 && + st.s() == 2 && + st.i() == 3 && + st.l() == 4L && + st.c() == '5' && + st.f() == 6.0f && + st.d() == 7.0 && + st.bool() == true && + st.str().equals("custom") && + st.cls() == Map.class && + st.e() == Stooge.MOE && + st.a().x() == 1 && st.a().y() == 2)) + fail("ScalarTypes" + e); + } + + static void checkScalarTypesOverrideDefault(AnnotatedElement e) { + try { + checkScalarTypesOverrideDefault(e.getAnnotation(ScalarTypesWithDefault.class), e); + } catch(Throwable t) { + fail("ScalarTypesOverrideDefaults" + e + ": " + t); + } + } + + static void checkScalarTypesOverrideDefault(ScalarTypesWithDefault st, AnnotatedElement e) { + numTests++; + if (!(st.b() == 1 && + st.s() == 2 && + st.i() == 3 && + st.l() == 4L && + st.c() == '5' && + st.f() == 6.0f && + st.d() == 7.0 && + st.bool() == true && + st.str().equals("custom") && + st.cls() == Map.class && + st.e() == Stooge.MOE)) + fail("ScalarTypesOverrideDefaults" + e); + } + + static void checkScalarTypesAcceptDefault(AnnotatedElement e) { + try { + checkScalarTypesAcceptDefault(e.getAnnotation(ScalarTypesWithDefault.class), e); + } catch(Throwable t) { + fail("ScalarTypesAcceptDefaults" + e + ": " + t); + } + } + + static void checkScalarTypesAcceptDefault(ScalarTypesWithDefault st, AnnotatedElement e) { + numTests++; + if (!(st.b() == 11 && + st.s() == 12 && + st.i() == 13 && + st.l() == 14L && + st.c() == 'V' && + st.f() == 16.0f && + st.d() == 17.0 && + st.bool() == false && + st.str().equals("default") && + st.cls() == Class.class && + st.e() == Stooge.LARRY && + st.a().x() == 11 && st.a().y() == 12)) + fail("ScalarTypesAcceptDefaults" + e); + } + + // Array multi-member + + static void checkArrayTypes0(AnnotatedElement e) { + try { + checkArrayTypes0(e.getAnnotation(ArrayTypes.class), e); + } catch(Throwable t) { + fail("ArrayTypes(Empty)" + e + ": " + t); + } + } + + static void checkArrayTypes0(ArrayTypes at, AnnotatedElement e) { + numTests++; + if (!(at.b().length == 0 && + at.s().length == 0 && + at.i().length == 0 && + at.l().length == 0 && + at.c().length == 0 && + at.f().length == 0 && + at.d().length == 0 && + at.bool().length == 0 && + at.str().length == 0 && + at.cls().length == 0 && + at.e().length == 0 && + at.a().length == 0)) { + fail("ArrayTypes(Empty)" + e); + } + } + + static void checkArrayTypes1(AnnotatedElement e) { + try { + checkArrayTypes1(e.getAnnotation(ArrayTypes.class), e); + } catch(Throwable t) { + fail("ArrayTypes(One element)" + e + ": " + t); + } + } + + static void checkArrayTypes1(ArrayTypes at, AnnotatedElement e) { + numTests++; + if (!(at.b()[0] == 1 && + at.s()[0] == 2 && + at.i()[0] == 3 && + at.l()[0] == 4L && + at.c()[0] == '5' && + at.f()[0] == 6.0f && + at.d()[0] == 7.0 && + at.bool()[0] == true && + at.str()[0].equals("custom") && + at.cls()[0] == Map.class && + at.e()[0] == Stooge.MOE && + at.a()[0].x() == 1 && at.a()[0].y() == 2 && + + at.b().length==1 && at.s().length==1 && at.i().length==1 && + at.l().length==1 && at.c().length==1 && at.d().length==1 && + at.bool().length==1 && at.str().length==1 && + at.cls().length==1 && at.cls().length==1 && at.a().length==1)) + fail("ArrayTypes(One element)" + e); + } + + static void checkArrayTypes2(AnnotatedElement e) { + try { + checkArrayTypes2(e.getAnnotation(ArrayTypes.class), e); + } catch(Throwable t) { + fail("ArrayTypes(Two element)" + e + ": " + t); + } + } + + static void checkArrayTypes2(ArrayTypes at, AnnotatedElement e) { + numTests++; + if (!(at.b()[0] == 1 && at.b()[1] == 2 && + at.s()[0] == 2 && at.s()[1] == 3 && + at.i()[0] == 3 && at.i()[1] == 4 && + at.l()[0] == 4L && at.l()[1] == 5L && + at.c()[0] == '5' && at.c()[1] == '6' && + at.f()[0] == 6.0f && at.f()[1] == 7.0f && + at.d()[0] == 7.0 && at.d()[1] == 8.0 && + at.bool()[0] == true && at.bool()[1] == false && + at.str()[0].equals("custom") && at.str()[1].equals("paint") && + at.cls()[0] == Map.class && at.cls()[1] == Set.class && + at.e()[0] == Stooge.MOE && at.e()[1] == Stooge.CURLY && + at.a()[0].x() == 1 && at.a()[0].y() == 2 && at.a()[1].x() == 3 && at.a()[1].y() == 4 && + + at.b().length==2 && at.s().length==2 && at.i().length==2 && + at.l().length==2 && at.c().length==2 && at.d().length==2 && + at.bool().length==2 && at.str().length==2 && + at.cls().length==2 && at.cls().length==2 && at.a().length==2)) + fail("ArrayTypes(Two element)" + e); + } + + static void checkArrayTypesOverrideDefault(AnnotatedElement e) { + try { + checkArrayTypesOverrideDefault(e.getAnnotation(ArrayTypesWithDefault.class), e); + } catch(Throwable t) { + fail("ArrayTypesOverrideDefault" + e + ": " + t); + } + } + + static void checkArrayTypesOverrideDefault(ArrayTypesWithDefault at, AnnotatedElement e) { + numTests++; + if (!(at.b()[0] == 1 && + at.s()[0] == 2 && + at.i()[0] == 3 && + at.l()[0] == 4L && + at.c()[0] == '5' && + at.f()[0] == 6.0f && + at.d()[0] == 7.0 && + at.bool()[0] == true && + at.str()[0].equals("custom") && + at.cls()[0] == Map.class && + at.e()[0] == Stooge.MOE && + at.a()[0].x() == 1 && at.a()[0].y() == 2 && + + at.b().length==1 && at.s().length==1 && at.i().length==1 && + at.l().length==1 && at.c().length==1 && at.d().length==1 && + at.bool().length==1 && at.str().length==1 && + at.cls().length==1 && at.cls().length==1)) + fail("ArrayTypesOverrideDefault" + e); + } + + static void checkArrayTypesAcceptDefault(AnnotatedElement e) { + try { + checkArrayTypesAcceptDefault(e.getAnnotation(ArrayTypesWithDefault.class), e); + } catch(Throwable t) { + fail("ArrayTypesAcceptDefault" + e + ": " + t); + } + } + + static void checkArrayTypesAcceptDefault(ArrayTypesWithDefault at, AnnotatedElement e) { + numTests++; + if (!(at.b()[0] == 11 && + at.s()[0] == 12 && + at.i()[0] == 13 && + at.l()[0] == 14L && + at.c()[0] == 'V' && + at.f()[0] == 16.0f && + at.d()[0] == 17.0 && + at.bool()[0] == false && + at.str()[0].equals("default") && + at.cls()[0] == Class.class && + at.e()[0] == Stooge.LARRY && + at.a()[0].x() == 11 && at.a()[0].y() == 12 && + + at.b().length==1 && at.s().length==1 && at.i().length==1 && + at.l().length==1 && at.c().length==1 && at.d().length==1 && + at.bool().length==1 && at.str().length==1 && + at.cls().length==1 && at.cls().length==1)) + fail("ArrayTypesAcceptDefault" + e); + } + + // Scalar multi-member for parameters + + static void checkScalarTypesParam(Method m) { + try { + checkScalarTypes((ScalarTypes) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ScalarTypes" + m + ": " + t); + } + } + + static void checkScalarTypesOverrideDefaultParam(Method m) { + try { + checkScalarTypesOverrideDefault((ScalarTypesWithDefault) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ScalarTypesOverrideDefaults" + m + ": " + t); + } + } + + static void checkScalarTypesAcceptDefaultParam(Method m) { + try { + checkScalarTypesAcceptDefault((ScalarTypesWithDefault) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ScalarTypesAcceptDefaults" + m + ": " + t); + } + } + + // Array multi-member for parameters + + static void checkArrayTypes0Param(Method m) { + try { + checkArrayTypes0((ArrayTypes) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ArrayTypes(Empty)" + m + ": " + t); + } + } + + static void checkArrayTypes1Param(Method m) { + try { + checkArrayTypes1((ArrayTypes) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ArrayTypes(One Element)" + m + ": " + t); + } + } + + static void checkArrayTypes2Param(Method m) { + try { + checkArrayTypes2((ArrayTypes) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ArrayTypes(Two Elements)" + m + ": " + t); + } + } + + static void checkArrayTypesOverrideDefaultParam(Method m) { + try { + checkArrayTypesOverrideDefault((ArrayTypesWithDefault) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ArrayTypesOverrideDefault" + m + ": " + t); + } + } + + static void checkArrayTypesAcceptDefaultParam(Method m) { + try { + checkArrayTypesAcceptDefault((ArrayTypesWithDefault) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("ArrayTypesAcceptDefault" + m + ": " + t); + } + } + + // marker type on parameter + static void checkMarkerParam(Method m) { + try { + checkMarker((Marker) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("Marker" + m + ": " + t); + } + } + + // single-member scalar types on parameter + static void checkSingleMemberByteParam(Method m) { + try { + checkSingleMemberByte((SingleMemberByte) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByte" + m + ": " + t); + } + } + + static void checkSingleMemberShortParam(Method m) { + try { + checkSingleMemberShort((SingleMemberShort) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShort" + m + ": " + t); + } + } + + static void checkSingleMemberIntParam(Method m) { + try { + checkSingleMemberInt((SingleMemberInt) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberInt" + m + ": " + t); + } + } + + static void checkSingleMemberLongParam(Method m) { + try { + checkSingleMemberLong((SingleMemberLong) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLong" + m + ": " + t); + } + } + + static void checkSingleMemberCharParam(Method m) { + try { + checkSingleMemberChar((SingleMemberChar) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberChar" + m + ": " + t); + } + } + + static void checkSingleMemberFloatParam(Method m) { + try { + checkSingleMemberFloat((SingleMemberFloat) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloat" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleParam(Method m) { + try { + checkSingleMemberDouble((SingleMemberDouble) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDouble" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanParam(Method m) { + try { + checkSingleMemberBoolean((SingleMemberBoolean) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBoolean" + m + ": " + t); + } + } + + static void checkSingleMemberStringParam(Method m) { + try { + checkSingleMemberString((SingleMemberString) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberString" + m + ": " + t); + } + } + + static void checkSingleMemberClassParam(Method m) { + try { + checkSingleMemberClass((SingleMemberClass) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClass" + m + ": " + t); + } + } + + static void checkSingleMemberEnumParam(Method m) { + try { + checkSingleMemberEnum((SingleMemberEnum) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnum" + m + ": " + t); + } + } + + // single-member scalar types with default-override on parameter + static void checkSingleMemberByteOvrdDefParam(Method m) { + try { + checkSingleMemberByteOvrdDef((SingleMemberByteWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberShortOvrdDefParam(Method m) { + try { + checkSingleMemberShortOvrdDef((SingleMemberShortWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberIntOvrdDefParam(Method m) { + try { + checkSingleMemberIntOvrdDef((SingleMemberIntWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberLongOvrdDefParam(Method m) { + try { + checkSingleMemberLongOvrdDef((SingleMemberLongWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberCharOvrdDefParam(Method m) { + try { + checkSingleMemberCharOvrdDef((SingleMemberCharWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberFloatOvrdDefParam(Method m) { + try { + checkSingleMemberFloatOvrdDef((SingleMemberFloatWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleOvrdDefParam(Method m) { + try { + checkSingleMemberDoubleOvrdDef((SingleMemberDoubleWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanOvrdDefParam(Method m) { + try { + checkSingleMemberBooleanOvrdDef((SingleMemberBooleanWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberStringOvrdDefParam(Method m) { + try { + checkSingleMemberStringOvrdDef((SingleMemberStringWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberClassOvrdDefParam(Method m) { + try { + checkSingleMemberClassOvrdDef((SingleMemberClassWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberEnumOvrdDefParam(Method m) { + try { + checkSingleMemberEnumOvrdDef((SingleMemberEnumWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumOvrdDef" + m + ": " + t); + } + } + + // single-member scalar types with default-accept on PARAMETER + static void checkSingleMemberByteAcceptDefParam(Method m) { + try { + checkSingleMemberByteAcceptDef((SingleMemberByteWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberShortAcceptDefParam(Method m) { + try { + checkSingleMemberShortAcceptDef((SingleMemberShortWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberIntAcceptDefParam(Method m) { + try { + checkSingleMemberIntAcceptDef((SingleMemberIntWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberLongAcceptDefParam(Method m) { + try { + checkSingleMemberLongAcceptDef((SingleMemberLongWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberCharAcceptDefParam(Method m) { + try { + checkSingleMemberCharAcceptDef((SingleMemberCharWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberFloatAcceptDefParam(Method m) { + try { + checkSingleMemberFloatAcceptDef((SingleMemberFloatWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleAcceptDefParam(Method m) { + try { + checkSingleMemberDoubleAcceptDef((SingleMemberDoubleWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanAcceptDefParam(Method m) { + try { + checkSingleMemberBooleanAcceptDef((SingleMemberBooleanWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberStringAcceptDefParam(Method m) { + try { + checkSingleMemberStringAcceptDef((SingleMemberStringWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberClassAcceptDefParam(Method m) { + try { + checkSingleMemberClassAcceptDef((SingleMemberClassWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberEnumAcceptDefParam(Method m) { + try { + checkSingleMemberEnumAcceptDef((SingleMemberEnumWithDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumAcceptDef" + m + ": " + t); + } + } + + // single-member array types (empty array) parameter + static void checkSingleMemberByteArrEmptyParam(Method m) { + try { + checkSingleMemberByteArrEmpty((SingleMemberByteArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberShortArrEmptyParam(Method m) { + try { + checkSingleMemberShortArrEmpty((SingleMemberShortArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberIntArrEmptyParam(Method m) { + try { + checkSingleMemberIntArrEmpty((SingleMemberIntArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberLongArrEmptyParam(Method m) { + try { + checkSingleMemberLongArrEmpty((SingleMemberLongArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberCharArrEmptyParam(Method m) { + try { + checkSingleMemberCharArrEmpty((SingleMemberCharArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberFloatArrEmptyParam(Method m) { + try { + checkSingleMemberFloatArrEmpty((SingleMemberFloatArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleArrEmptyParam(Method m) { + try { + checkSingleMemberDoubleArrEmpty((SingleMemberDoubleArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanArrEmptyParam(Method m) { + try { + checkSingleMemberBooleanArrEmpty((SingleMemberBooleanArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberStringArrEmptyParam(Method m) { + try { + checkSingleMemberStringArrEmpty((SingleMemberStringArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberClassArrEmptyParam(Method m) { + try { + checkSingleMemberClassArrEmpty((SingleMemberClassArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassArrEmpty" + m + ": " + t); + } + } + + static void checkSingleMemberEnumArrEmptyParam(Method m) { + try { + checkSingleMemberEnumArrEmpty((SingleMemberEnumArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumArrEmpty" + m + ": " + t); + } + } + + // single-member array types (one-element array) on parameter + static void checkSingleMemberByteArrOneParam(Method m) { + try { + checkSingleMemberByteArrOne((SingleMemberByteArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberShortArrOneParam(Method m) { + try { + checkSingleMemberShortArrOne((SingleMemberShortArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberIntArrOneParam(Method m) { + try { + checkSingleMemberIntArrOne((SingleMemberIntArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberLongArrOneParam(Method m) { + try { + checkSingleMemberLongArrOne((SingleMemberLongArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberCharArrOneParam(Method m) { + try { + checkSingleMemberCharArrOne((SingleMemberCharArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberFloatArrOneParam(Method m) { + try { + checkSingleMemberFloatArrOne((SingleMemberFloatArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleArrOneParam(Method m) { + try { + checkSingleMemberDoubleArrOne((SingleMemberDoubleArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanArrOneParam(Method m) { + try { + checkSingleMemberBooleanArrOne((SingleMemberBooleanArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberStringArrOneParam(Method m) { + try { + checkSingleMemberStringArrOne((SingleMemberStringArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberClassArrOneParam(Method m) { + try { + checkSingleMemberClassArrOne((SingleMemberClassArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassArrOne" + m + ": " + t); + } + } + + static void checkSingleMemberEnumArrOneParam(Method m) { + try { + checkSingleMemberEnumArrOne((SingleMemberEnumArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumArrOne" + m + ": " + t); + } + } + + // single-member array types (two-element array) on parameter + static void checkSingleMemberByteArrTwoParam(Method m) { + try { + checkSingleMemberByteArrTwo((SingleMemberByteArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberShortArrTwoParam(Method m) { + try { + checkSingleMemberShortArrTwo((SingleMemberShortArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberIntArrTwoParam(Method m) { + try { + checkSingleMemberIntArrTwo((SingleMemberIntArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberLongArrTwoParam(Method m) { + try { + checkSingleMemberLongArrTwo((SingleMemberLongArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberCharArrTwoParam(Method m) { + try { + checkSingleMemberCharArrTwo((SingleMemberCharArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberFloatArrTwoParam(Method m) { + try { + checkSingleMemberFloatArrTwo((SingleMemberFloatArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleArrTwoParam(Method m) { + try { + checkSingleMemberDoubleArrTwo((SingleMemberDoubleArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanArrTwoParam(Method m) { + try { + checkSingleMemberBooleanArrTwo((SingleMemberBooleanArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberStringArrTwoParam(Method m) { + try { + checkSingleMemberStringArrTwo((SingleMemberStringArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberClassArrTwoParam(Method m) { + try { + checkSingleMemberClassArrTwo((SingleMemberClassArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassArrTwo" + m + ": " + t); + } + } + + static void checkSingleMemberEnumArrTwoParam(Method m) { + try { + checkSingleMemberEnumArrTwo((SingleMemberEnumArray) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumArrTwo" + m + ": " + t); + } + } + + // single-member array types with default (override)on parameter + static void checkSingleMemberByteArrOvrdDefParam(Method m) { + try { + checkSingleMemberByteArrOvrdDef((SingleMemberByteArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberShortArrOvrdDefParam(Method m) { + try { + checkSingleMemberShortArrOvrdDef((SingleMemberShortArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberIntArrOvrdDefParam(Method m) { + try { + checkSingleMemberIntArrOvrdDef((SingleMemberIntArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberLongArrOvrdDefParam(Method m) { + try { + checkSingleMemberLongArrOvrdDef((SingleMemberLongArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberCharArrOvrdDefParam(Method m) { + try { + checkSingleMemberCharArrOvrdDef((SingleMemberCharArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberFloatArrOvrdDefParam(Method m) { + try { + checkSingleMemberFloatArrOvrdDef((SingleMemberFloatArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleArrOvrdDefParam(Method m) { + try { + checkSingleMemberDoubleArrOvrdDef((SingleMemberDoubleArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanArrOvrdDefParam(Method m) { + try { + checkSingleMemberBooleanArrOvrdDef((SingleMemberBooleanArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberStringArrOvrdDefParam(Method m) { + try { + checkSingleMemberStringArrOvrdDef((SingleMemberStringArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberClassArrOvrdDefParam(Method m) { + try { + checkSingleMemberClassArrOvrdDef((SingleMemberClassArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassArrOvrdDef" + m + ": " + t); + } + } + + static void checkSingleMemberEnumArrOvrdDefParam(Method m) { + try { + checkSingleMemberEnumArrOvrdDef((SingleMemberEnumArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumArrOvrdDef" + m + ": " + t); + } + } + + // single-member array types with default (accept)on parameter + static void checkSingleMemberByteArrAcceptDefParam(Method m) { + try { + checkSingleMemberByteArrAcceptDef((SingleMemberByteArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberByteArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberShortArrAcceptDefParam(Method m) { + try { + checkSingleMemberShortArrAcceptDef((SingleMemberShortArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberShortArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberIntArrAcceptDefParam(Method m) { + try { + checkSingleMemberIntArrAcceptDef((SingleMemberIntArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberIntArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberLongArrAcceptDefParam(Method m) { + try { + checkSingleMemberLongArrAcceptDef((SingleMemberLongArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberLongArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberCharArrAcceptDefParam(Method m) { + try { + checkSingleMemberCharArrAcceptDef((SingleMemberCharArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberCharArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberFloatArrAcceptDefParam(Method m) { + try { + checkSingleMemberFloatArrAcceptDef((SingleMemberFloatArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberFloatArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberDoubleArrAcceptDefParam(Method m) { + try { + checkSingleMemberDoubleArrAcceptDef((SingleMemberDoubleArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberDoubleArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberBooleanArrAcceptDefParam(Method m) { + try { + checkSingleMemberBooleanArrAcceptDef((SingleMemberBooleanArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberBooleanArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberStringArrAcceptDefParam(Method m) { + try { + checkSingleMemberStringArrAcceptDef((SingleMemberStringArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberStringArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberClassArrAcceptDefParam(Method m) { + try { + checkSingleMemberClassArrAcceptDef((SingleMemberClassArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberClassArrAcceptDef" + m + ": " + t); + } + } + + static void checkSingleMemberEnumArrAcceptDefParam(Method m) { + try { + checkSingleMemberEnumArrAcceptDef((SingleMemberEnumArrayDef) m.getParameterAnnotations()[0][0], m); + } catch(Throwable t) { + fail("SingleMemberEnumArrAcceptDef" + m + ": " + t); + } + } + + // Marker + static void checkMarker(AnnotatedElement e) { + checkMarker(e.getAnnotation(Marker.class), e); + } + static void checkMarker(Marker m, AnnotatedElement e) { + numTests++; + try { + if (m == null) fail("Marker " + e); + } catch(Throwable t) { + fail("Marker " + e + ": " + t); + } + } + + // Single-member + + static void checkSingleMemberByte(AnnotatedElement e) { + checkSingleMemberByte(e.getAnnotation(SingleMemberByte.class), e); + } + static void checkSingleMemberByte(SingleMemberByte a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 1) fail("SingleMemberByte " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByte " + e + ": " + t); + } + } + + static void checkSingleMemberShort(AnnotatedElement e) { + checkSingleMemberShort(e.getAnnotation(SingleMemberShort.class), e); + } + static void checkSingleMemberShort(SingleMemberShort a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 2) fail("SingleMemberShort " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShort " + e + ": " + t); + } + } + + static void checkSingleMemberInt(AnnotatedElement e) { + checkSingleMemberInt(e.getAnnotation(SingleMemberInt.class), e); + } + static void checkSingleMemberInt(SingleMemberInt a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 3) fail("SingleMemberInt " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberInt " + e + ": " + t); + } + } + + static void checkSingleMemberLong(AnnotatedElement e) { + checkSingleMemberLong(e.getAnnotation(SingleMemberLong.class), e); + } + static void checkSingleMemberLong(SingleMemberLong a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 4L) fail("SingleMemberLong " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLong " + e + ": " + t); + } + } + + static void checkSingleMemberChar(AnnotatedElement e) { + checkSingleMemberChar(e.getAnnotation(SingleMemberChar.class), e); + } + static void checkSingleMemberChar(SingleMemberChar a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != '5') fail("SingleMemberChar " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberChar " + e + ": " + t); + } + } + + static void checkSingleMemberFloat(AnnotatedElement e) { + checkSingleMemberFloat(e.getAnnotation(SingleMemberFloat.class), e); + } + static void checkSingleMemberFloat(SingleMemberFloat a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 6.0f) fail("SingleMemberFloat " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloat " + e + ": " + t); + } + } + + static void checkSingleMemberDouble(AnnotatedElement e) { + checkSingleMemberDouble(e.getAnnotation(SingleMemberDouble.class), e); + } + static void checkSingleMemberDouble(SingleMemberDouble a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 7.0) fail("SingleMemberDouble " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDouble " + e + ": " + t); + } + } + + static void checkSingleMemberBoolean(AnnotatedElement e) { + checkSingleMemberBoolean(e.getAnnotation(SingleMemberBoolean.class), e); + } + static void checkSingleMemberBoolean(SingleMemberBoolean a, AnnotatedElement e) { + numTests++; + try { + if (!a.value()) fail("SingleMemberBoolean " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBoolean " + e + ": " + t); + } + } + + static void checkSingleMemberString(AnnotatedElement e) { + checkSingleMemberString(e.getAnnotation(SingleMemberString.class), e); + } + static void checkSingleMemberString(SingleMemberString a, AnnotatedElement e) { + numTests++; + try { + if (!(a.value().equals("custom"))) fail("SingleMemberString " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberString " + e + ": " + t); + } + } + + static void checkSingleMemberClass(AnnotatedElement e) { + checkSingleMemberClass(e.getAnnotation(SingleMemberClass.class), e); + } + static void checkSingleMemberClass(SingleMemberClass a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Map.class) fail("SingleMemberClass " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClass " + e + ": " + t); + } + } + + static void checkSingleMemberEnum(AnnotatedElement e) { + checkSingleMemberEnum(e.getAnnotation(SingleMemberEnum.class), e); + } + static void checkSingleMemberEnum(SingleMemberEnum a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Stooge.MOE) fail("SingleMemberEnum " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnum " + e + ": " + t); + } + } + + // Single-member with default (Override) + + static void checkSingleMemberByteOvrdDef(AnnotatedElement e) { + checkSingleMemberByteOvrdDef(e.getAnnotation(SingleMemberByteWithDef.class), e); + } + static void checkSingleMemberByteOvrdDef(SingleMemberByteWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 1) fail("SingleMemberByteOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberShortOvrdDef(AnnotatedElement e) { + checkSingleMemberShortOvrdDef(e.getAnnotation(SingleMemberShortWithDef.class), e); + } + static void checkSingleMemberShortOvrdDef(SingleMemberShortWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 2) fail("SingleMemberShortOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberIntOvrdDef(AnnotatedElement e) { + checkSingleMemberIntOvrdDef(e.getAnnotation(SingleMemberIntWithDef.class), e); + } + static void checkSingleMemberIntOvrdDef(SingleMemberIntWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 3) fail("SingleMemberIntOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberLongOvrdDef(AnnotatedElement e) { + checkSingleMemberLongOvrdDef(e.getAnnotation(SingleMemberLongWithDef.class), e); + } + static void checkSingleMemberLongOvrdDef(SingleMemberLongWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 4L) fail("SingleMemberLongOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberCharOvrdDef(AnnotatedElement e) { + checkSingleMemberCharOvrdDef(e.getAnnotation(SingleMemberCharWithDef.class), e); + } + static void checkSingleMemberCharOvrdDef(SingleMemberCharWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != '5') fail("SingleMemberCharOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberFloatOvrdDef(AnnotatedElement e) { + checkSingleMemberFloatOvrdDef(e.getAnnotation(SingleMemberFloatWithDef.class), e); + } + static void checkSingleMemberFloatOvrdDef(SingleMemberFloatWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 6.0f) fail("SingleMemberFloatOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleOvrdDef(AnnotatedElement e) { + checkSingleMemberDoubleOvrdDef(e.getAnnotation(SingleMemberDoubleWithDef.class), e); + } + static void checkSingleMemberDoubleOvrdDef(SingleMemberDoubleWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 7.0) fail("SingleMemberDoubleOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanOvrdDef(AnnotatedElement e) { + checkSingleMemberBooleanOvrdDef(e.getAnnotation(SingleMemberBooleanWithDef.class), e); + } + static void checkSingleMemberBooleanOvrdDef(SingleMemberBooleanWithDef a, AnnotatedElement e) { + numTests++; + try { + if (!a.value()) fail("SingleMemberBooleanOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberStringOvrdDef(AnnotatedElement e) { + checkSingleMemberStringOvrdDef(e.getAnnotation(SingleMemberStringWithDef.class), e); + } + static void checkSingleMemberStringOvrdDef(SingleMemberStringWithDef a, AnnotatedElement e) { + numTests++; + try { + if (!(a.value().equals("custom"))) fail("SingleMemberStringOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberClassOvrdDef(AnnotatedElement e) { + checkSingleMemberClassOvrdDef(e.getAnnotation(SingleMemberClassWithDef.class), e); + } + static void checkSingleMemberClassOvrdDef(SingleMemberClassWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Map.class) fail("SingleMemberClassOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberEnumOvrdDef(AnnotatedElement e) { + checkSingleMemberEnumOvrdDef(e.getAnnotation(SingleMemberEnumWithDef.class), e); + } + static void checkSingleMemberEnumOvrdDef(SingleMemberEnumWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Stooge.MOE) fail("SingleMemberEnumOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumOvrdDef " + e + ": " + t); + } + } + + // Single-member with default (Accept) + + static void checkSingleMemberByteAcceptDef(AnnotatedElement e) { + checkSingleMemberByteAcceptDef(e.getAnnotation(SingleMemberByteWithDef.class), e); + } + static void checkSingleMemberByteAcceptDef(SingleMemberByteWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 11) fail("SingleMemberByteAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberShortAcceptDef(AnnotatedElement e) { + checkSingleMemberShortAcceptDef(e.getAnnotation(SingleMemberShortWithDef.class), e); + } + static void checkSingleMemberShortAcceptDef(SingleMemberShortWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 12) fail("SingleMemberShortAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberIntAcceptDef(AnnotatedElement e) { + checkSingleMemberIntAcceptDef(e.getAnnotation(SingleMemberIntWithDef.class), e); + } + static void checkSingleMemberIntAcceptDef(SingleMemberIntWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 13) fail("SingleMemberIntAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberLongAcceptDef(AnnotatedElement e) { + checkSingleMemberLongAcceptDef(e.getAnnotation(SingleMemberLongWithDef.class), e); + } + static void checkSingleMemberLongAcceptDef(SingleMemberLongWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 14L) fail("SingleMemberLongAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberCharAcceptDef(AnnotatedElement e) { + checkSingleMemberCharAcceptDef(e.getAnnotation(SingleMemberCharWithDef.class), e); + } + static void checkSingleMemberCharAcceptDef(SingleMemberCharWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 'V') fail("SingleMemberCharAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberFloatAcceptDef(AnnotatedElement e) { + checkSingleMemberFloatAcceptDef(e.getAnnotation(SingleMemberFloatWithDef.class), e); + } + static void checkSingleMemberFloatAcceptDef(SingleMemberFloatWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 16.0f) fail("SingleMemberFloatAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleAcceptDef(AnnotatedElement e) { + checkSingleMemberDoubleAcceptDef(e.getAnnotation(SingleMemberDoubleWithDef.class), e); + } + static void checkSingleMemberDoubleAcceptDef(SingleMemberDoubleWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != 17.0) fail("SingleMemberDoubleAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanAcceptDef(AnnotatedElement e) { + checkSingleMemberBooleanAcceptDef(e.getAnnotation(SingleMemberBooleanWithDef.class), e); + } + static void checkSingleMemberBooleanAcceptDef(SingleMemberBooleanWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value()) fail("SingleMemberBooleanAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberStringAcceptDef(AnnotatedElement e) { + checkSingleMemberStringAcceptDef(e.getAnnotation(SingleMemberStringWithDef.class), e); + } + static void checkSingleMemberStringAcceptDef(SingleMemberStringWithDef a, AnnotatedElement e) { + numTests++; + try { + if (!(a.value().equals("default"))) fail("SingleMemberStringAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberClassAcceptDef(AnnotatedElement e) { + checkSingleMemberClassAcceptDef(e.getAnnotation(SingleMemberClassWithDef.class), e); + } + static void checkSingleMemberClassAcceptDef(SingleMemberClassWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Class.class) fail("SingleMemberClassAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberEnumAcceptDef(AnnotatedElement e) { + checkSingleMemberEnumAcceptDef(e.getAnnotation(SingleMemberEnumWithDef.class), e); + } + static void checkSingleMemberEnumAcceptDef(SingleMemberEnumWithDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value() != Stooge.LARRY) fail("SingleMemberEnumAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumAcceptDef " + e + ": " + t); + } + } + + // Single member array (empty array) + static void checkSingleMemberByteArrEmpty(AnnotatedElement e) { + checkSingleMemberByteArrEmpty(e.getAnnotation(SingleMemberByteArray.class), e); + } + static void checkSingleMemberByteArrEmpty(SingleMemberByteArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberByteArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberShortArrEmpty(AnnotatedElement e) { + checkSingleMemberShortArrEmpty(e.getAnnotation(SingleMemberShortArray.class), e); + } + static void checkSingleMemberShortArrEmpty(SingleMemberShortArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberShortArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberIntArrEmpty(AnnotatedElement e) { + checkSingleMemberIntArrEmpty(e.getAnnotation(SingleMemberIntArray.class), e); + } + static void checkSingleMemberIntArrEmpty(SingleMemberIntArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberIntArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberLongArrEmpty(AnnotatedElement e) { + checkSingleMemberLongArrEmpty(e.getAnnotation(SingleMemberLongArray.class), e); + } + static void checkSingleMemberLongArrEmpty(SingleMemberLongArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberLongArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberCharArrEmpty(AnnotatedElement e) { + checkSingleMemberCharArrEmpty(e.getAnnotation(SingleMemberCharArray.class), e); + } + static void checkSingleMemberCharArrEmpty(SingleMemberCharArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberCharArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberFloatArrEmpty(AnnotatedElement e) { + checkSingleMemberFloatArrEmpty(e.getAnnotation(SingleMemberFloatArray.class), e); + } + static void checkSingleMemberFloatArrEmpty(SingleMemberFloatArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberFloatArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleArrEmpty(AnnotatedElement e) { + checkSingleMemberDoubleArrEmpty(e.getAnnotation(SingleMemberDoubleArray.class), e); + } + static void checkSingleMemberDoubleArrEmpty(SingleMemberDoubleArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberDoubleArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanArrEmpty(AnnotatedElement e) { + checkSingleMemberBooleanArrEmpty(e.getAnnotation(SingleMemberBooleanArray.class), e); + } + static void checkSingleMemberBooleanArrEmpty(SingleMemberBooleanArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberBooleanArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberStringArrEmpty(AnnotatedElement e) { + checkSingleMemberStringArrEmpty(e.getAnnotation(SingleMemberStringArray.class), e); + } + static void checkSingleMemberStringArrEmpty(SingleMemberStringArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberStringArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberClassArrEmpty(AnnotatedElement e) { + checkSingleMemberClassArrEmpty(e.getAnnotation(SingleMemberClassArray.class), e); + } + static void checkSingleMemberClassArrEmpty(SingleMemberClassArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberClassArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassArrEmpty " + e + ": " + t); + } + } + + static void checkSingleMemberEnumArrEmpty(AnnotatedElement e) { + checkSingleMemberEnumArrEmpty(e.getAnnotation(SingleMemberEnumArray.class), e); + } + static void checkSingleMemberEnumArrEmpty(SingleMemberEnumArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 0) fail("SingleMemberEnumArrEmpty " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumArrEmpty " + e + ": " + t); + } + } + + // Single member array (one element array) + static void checkSingleMemberByteArrOne(AnnotatedElement e) { + checkSingleMemberByteArrOne(e.getAnnotation(SingleMemberByteArray.class), e); + } + static void checkSingleMemberByteArrOne(SingleMemberByteArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (byte)1) + fail("SingleMemberByteArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberShortArrOne(AnnotatedElement e) { + checkSingleMemberShortArrOne(e.getAnnotation(SingleMemberShortArray.class), e); + } + static void checkSingleMemberShortArrOne(SingleMemberShortArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (short)2) + fail("SingleMemberShortArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberIntArrOne(AnnotatedElement e) { + checkSingleMemberIntArrOne(e.getAnnotation(SingleMemberIntArray.class), e); + } + static void checkSingleMemberIntArrOne(SingleMemberIntArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 3) + fail("SingleMemberIntArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberLongArrOne(AnnotatedElement e) { + checkSingleMemberLongArrOne(e.getAnnotation(SingleMemberLongArray.class), e); + } + static void checkSingleMemberLongArrOne(SingleMemberLongArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 4L) + fail("SingleMemberLongArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberCharArrOne(AnnotatedElement e) { + checkSingleMemberCharArrOne(e.getAnnotation(SingleMemberCharArray.class), e); + } + static void checkSingleMemberCharArrOne(SingleMemberCharArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != '5') + fail("SingleMemberCharArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberFloatArrOne(AnnotatedElement e) { + checkSingleMemberFloatArrOne(e.getAnnotation(SingleMemberFloatArray.class), e); + } + static void checkSingleMemberFloatArrOne(SingleMemberFloatArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 6.0f) + fail("SingleMemberFloatArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleArrOne(AnnotatedElement e) { + checkSingleMemberDoubleArrOne(e.getAnnotation(SingleMemberDoubleArray.class), e); + } + static void checkSingleMemberDoubleArrOne(SingleMemberDoubleArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 7.0) + fail("SingleMemberDoubleArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanArrOne(AnnotatedElement e) { + checkSingleMemberBooleanArrOne(e.getAnnotation(SingleMemberBooleanArray.class), e); + } + static void checkSingleMemberBooleanArrOne(SingleMemberBooleanArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || !a.value()[0]) + fail("SingleMemberBooleanArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberStringArrOne(AnnotatedElement e) { + checkSingleMemberStringArrOne(e.getAnnotation(SingleMemberStringArray.class), e); + } + static void checkSingleMemberStringArrOne(SingleMemberStringArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || !(a.value()[0].equals("custom"))) + fail("SingleMemberStringArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberClassArrOne(AnnotatedElement e) { + checkSingleMemberClassArrOne(e.getAnnotation(SingleMemberClassArray.class), e); + } + static void checkSingleMemberClassArrOne(SingleMemberClassArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Map.class) + fail("SingleMemberClassArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassArrOne " + e + ": " + t); + } + } + + static void checkSingleMemberEnumArrOne(AnnotatedElement e) { + checkSingleMemberEnumArrOne(e.getAnnotation(SingleMemberEnumArray.class), e); + } + static void checkSingleMemberEnumArrOne(SingleMemberEnumArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Stooge.MOE) + fail("SingleMemberEnumArrOne " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumArrOne " + e + ": " + t); + } + } + + // Single member array (two element array) + static void checkSingleMemberByteArrTwo(AnnotatedElement e) { + checkSingleMemberByteArrTwo(e.getAnnotation(SingleMemberByteArray.class), e); + } + static void checkSingleMemberByteArrTwo(SingleMemberByteArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != (byte)1 || a.value()[1] != (byte)2) + fail("SingleMemberByteArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberShortArrTwo(AnnotatedElement e) { + checkSingleMemberShortArrTwo(e.getAnnotation(SingleMemberShortArray.class), e); + } + static void checkSingleMemberShortArrTwo(SingleMemberShortArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != (short)2 || a.value()[1] != (short)3) + fail("SingleMemberShortArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberIntArrTwo(AnnotatedElement e) { + checkSingleMemberIntArrTwo(e.getAnnotation(SingleMemberIntArray.class), e); + } + static void checkSingleMemberIntArrTwo(SingleMemberIntArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != 3 || a.value()[1] != 4) + fail("SingleMemberIntArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberLongArrTwo(AnnotatedElement e) { + checkSingleMemberLongArrTwo(e.getAnnotation(SingleMemberLongArray.class), e); + } + static void checkSingleMemberLongArrTwo(SingleMemberLongArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != 4L || a.value()[1] != 5L) + fail("SingleMemberLongArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberCharArrTwo(AnnotatedElement e) { + checkSingleMemberCharArrTwo(e.getAnnotation(SingleMemberCharArray.class), e); + } + static void checkSingleMemberCharArrTwo(SingleMemberCharArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != '5' || a.value()[1] != '6') + fail("SingleMemberCharArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberFloatArrTwo(AnnotatedElement e) { + checkSingleMemberFloatArrTwo(e.getAnnotation(SingleMemberFloatArray.class), e); + } + static void checkSingleMemberFloatArrTwo(SingleMemberFloatArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != 6.0f || a.value()[1] != 7.0f) + fail("SingleMemberFloatArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleArrTwo(AnnotatedElement e) { + checkSingleMemberDoubleArrTwo(e.getAnnotation(SingleMemberDoubleArray.class), e); + } + static void checkSingleMemberDoubleArrTwo(SingleMemberDoubleArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != 7.0 || a.value()[1] != 8.0) + fail("SingleMemberDoubleArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanArrTwo(AnnotatedElement e) { + checkSingleMemberBooleanArrTwo(e.getAnnotation(SingleMemberBooleanArray.class), e); + } + static void checkSingleMemberBooleanArrTwo(SingleMemberBooleanArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || !a.value()[0] || a.value()[1]) + fail("SingleMemberBooleanArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberStringArrTwo(AnnotatedElement e) { + checkSingleMemberStringArrTwo(e.getAnnotation(SingleMemberStringArray.class), e); + } + static void checkSingleMemberStringArrTwo(SingleMemberStringArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || !(a.value()[0].equals("custom")) || !(a.value()[1].equals("paint"))) + fail("SingleMemberStringArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberClassArrTwo(AnnotatedElement e) { + checkSingleMemberClassArrTwo(e.getAnnotation(SingleMemberClassArray.class), e); + } + static void checkSingleMemberClassArrTwo(SingleMemberClassArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != Map.class || a.value()[1] != Set.class) + fail("SingleMemberClassArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassArrTwo " + e + ": " + t); + } + } + + static void checkSingleMemberEnumArrTwo(AnnotatedElement e) { + checkSingleMemberEnumArrTwo(e.getAnnotation(SingleMemberEnumArray.class), e); + } + static void checkSingleMemberEnumArrTwo(SingleMemberEnumArray a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 2 || a.value()[0] != Stooge.MOE || a.value()[1] != Stooge.CURLY) + fail("SingleMemberEnumArrTwo " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumArrTwo " + e + ": " + t); + } + } + + // Single member array with default (override) + static void checkSingleMemberByteArrOvrdDef(AnnotatedElement e) { + checkSingleMemberByteArrOvrdDef(e.getAnnotation(SingleMemberByteArrayDef.class), e); + } + static void checkSingleMemberByteArrOvrdDef(SingleMemberByteArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (byte)1) + fail("SingleMemberByteArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberShortArrOvrdDef(AnnotatedElement e) { + checkSingleMemberShortArrOvrdDef(e.getAnnotation(SingleMemberShortArrayDef.class), e); + } + static void checkSingleMemberShortArrOvrdDef(SingleMemberShortArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (short)2) + fail("SingleMemberShortArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberIntArrOvrdDef(AnnotatedElement e) { + checkSingleMemberIntArrOvrdDef(e.getAnnotation(SingleMemberIntArrayDef.class), e); + } + static void checkSingleMemberIntArrOvrdDef(SingleMemberIntArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 3) + fail("SingleMemberIntArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberLongArrOvrdDef(AnnotatedElement e) { + checkSingleMemberLongArrOvrdDef(e.getAnnotation(SingleMemberLongArrayDef.class), e); + } + static void checkSingleMemberLongArrOvrdDef(SingleMemberLongArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 4L) + fail("SingleMemberLongArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberCharArrOvrdDef(AnnotatedElement e) { + checkSingleMemberCharArrOvrdDef(e.getAnnotation(SingleMemberCharArrayDef.class), e); + } + static void checkSingleMemberCharArrOvrdDef(SingleMemberCharArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != '5') + fail("SingleMemberCharArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberFloatArrOvrdDef(AnnotatedElement e) { + checkSingleMemberFloatArrOvrdDef(e.getAnnotation(SingleMemberFloatArrayDef.class), e); + } + static void checkSingleMemberFloatArrOvrdDef(SingleMemberFloatArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 6.0f) + fail("SingleMemberFloatArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleArrOvrdDef(AnnotatedElement e) { + checkSingleMemberDoubleArrOvrdDef(e.getAnnotation(SingleMemberDoubleArrayDef.class), e); + } + static void checkSingleMemberDoubleArrOvrdDef(SingleMemberDoubleArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 7.0) + fail("SingleMemberDoubleArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanArrOvrdDef(AnnotatedElement e) { + checkSingleMemberBooleanArrOvrdDef(e.getAnnotation(SingleMemberBooleanArrayDef.class), e); + } + static void checkSingleMemberBooleanArrOvrdDef(SingleMemberBooleanArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || !a.value()[0]) + fail("SingleMemberBooleanArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberStringArrOvrdDef(AnnotatedElement e) { + checkSingleMemberStringArrOvrdDef(e.getAnnotation(SingleMemberStringArrayDef.class), e); + } + static void checkSingleMemberStringArrOvrdDef(SingleMemberStringArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || !(a.value()[0].equals("custom"))) + fail("SingleMemberStringArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberClassArrOvrdDef(AnnotatedElement e) { + checkSingleMemberClassArrOvrdDef(e.getAnnotation(SingleMemberClassArrayDef.class), e); + } + static void checkSingleMemberClassArrOvrdDef(SingleMemberClassArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Map.class) + fail("SingleMemberClassArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassArrOvrdDef " + e + ": " + t); + } + } + + static void checkSingleMemberEnumArrOvrdDef(AnnotatedElement e) { + checkSingleMemberEnumArrOvrdDef(e.getAnnotation(SingleMemberEnumArrayDef.class), e); + } + static void checkSingleMemberEnumArrOvrdDef(SingleMemberEnumArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Stooge.MOE) + fail("SingleMemberEnumArrOvrdDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumArrOvrdDef " + e + ": " + t); + } + } + + // Single member array with default (accept) + static void checkSingleMemberByteArrAcceptDef(AnnotatedElement e) { + checkSingleMemberByteArrAcceptDef(e.getAnnotation(SingleMemberByteArrayDef.class), e); + } + static void checkSingleMemberByteArrAcceptDef(SingleMemberByteArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (byte)11) + fail("SingleMemberByteArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberByteArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberShortArrAcceptDef(AnnotatedElement e) { + checkSingleMemberShortArrAcceptDef(e.getAnnotation(SingleMemberShortArrayDef.class), e); + } + static void checkSingleMemberShortArrAcceptDef(SingleMemberShortArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != (short)12) + fail("SingleMemberShortArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberShortArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberIntArrAcceptDef(AnnotatedElement e) { + checkSingleMemberIntArrAcceptDef(e.getAnnotation(SingleMemberIntArrayDef.class), e); + } + static void checkSingleMemberIntArrAcceptDef(SingleMemberIntArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 13) + fail("SingleMemberIntArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberIntArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberLongArrAcceptDef(AnnotatedElement e) { + checkSingleMemberLongArrAcceptDef(e.getAnnotation(SingleMemberLongArrayDef.class), e); + } + static void checkSingleMemberLongArrAcceptDef(SingleMemberLongArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 14L) + fail("SingleMemberLongArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberLongArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberCharArrAcceptDef(AnnotatedElement e) { + checkSingleMemberCharArrAcceptDef(e.getAnnotation(SingleMemberCharArrayDef.class), e); + } + static void checkSingleMemberCharArrAcceptDef(SingleMemberCharArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 'V') + fail("SingleMemberCharArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberCharArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberFloatArrAcceptDef(AnnotatedElement e) { + checkSingleMemberFloatArrAcceptDef(e.getAnnotation(SingleMemberFloatArrayDef.class), e); + } + static void checkSingleMemberFloatArrAcceptDef(SingleMemberFloatArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 16.0f) + fail("SingleMemberFloatArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberFloatArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberDoubleArrAcceptDef(AnnotatedElement e) { + checkSingleMemberDoubleArrAcceptDef(e.getAnnotation(SingleMemberDoubleArrayDef.class), e); + } + static void checkSingleMemberDoubleArrAcceptDef(SingleMemberDoubleArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != 17.0) + fail("SingleMemberDoubleArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberDoubleArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberBooleanArrAcceptDef(AnnotatedElement e) { + checkSingleMemberBooleanArrAcceptDef(e.getAnnotation(SingleMemberBooleanArrayDef.class), e); + } + static void checkSingleMemberBooleanArrAcceptDef(SingleMemberBooleanArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0]) + fail("SingleMemberBooleanArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberBooleanArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberStringArrAcceptDef(AnnotatedElement e) { + checkSingleMemberStringArrAcceptDef(e.getAnnotation(SingleMemberStringArrayDef.class), e); + } + static void checkSingleMemberStringArrAcceptDef(SingleMemberStringArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || !(a.value()[0].equals("default"))) + fail("SingleMemberStringArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberStringArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberClassArrAcceptDef(AnnotatedElement e) { + checkSingleMemberClassArrAcceptDef(e.getAnnotation(SingleMemberClassArrayDef.class), e); + } + static void checkSingleMemberClassArrAcceptDef(SingleMemberClassArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Class.class) + fail("SingleMemberClassArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberClassArrAcceptDef " + e + ": " + t); + } + } + + static void checkSingleMemberEnumArrAcceptDef(AnnotatedElement e) { + checkSingleMemberEnumArrAcceptDef(e.getAnnotation(SingleMemberEnumArrayDef.class), e); + } + static void checkSingleMemberEnumArrAcceptDef(SingleMemberEnumArrayDef a, AnnotatedElement e) { + numTests++; + try { + if (a.value().length != 1 || a.value()[0] != Stooge.LARRY) + fail("SingleMemberEnumArrAcceptDef " + e + " = " + a.value()); + } catch(Throwable t) { + fail("SingleMemberEnumArrAcceptDef " + e + ": " + t); + } + } + + // Verfification methods for equals/hashCode/serialization + + static void checkEquals(AnnotatedElement e1, AnnotatedElement e2, Class annoType) { + numTests++; + T a1 = e1.getAnnotation(annoType); + T a2 = e2.getAnnotation(annoType); + try { + if (!a1.equals(a2)) + fail(a1 + " != " + a2); + if (a1.hashCode() != a2.hashCode()) + fail(a1 + ".hashCode() [" + a1.hashCode() + "] != " + a2 + " .hashCode()["+ a2.hashCode()+"]"); + if (!(a1.toString().equals(a2.toString()))) + fail(a1 + ".toString() != " + a2 + ".toString()"); + } catch(Throwable t) { + fail(a1 + " == " + a2 + ": " + t); + } + } + + static void checkUnequals(AnnotatedElement e1, AnnotatedElement e2, Class annoType) { + numTests++; + T a1 = e1.getAnnotation(annoType); + T a2 = e2.getAnnotation(annoType); + try { + if (a1.equals(a2)) + fail(a1 + " == " + a2); + if (a1.hashCode() == a2.hashCode()) + fail(a1 + ".hashCode() [" + a1.hashCode() + "] == " + a2 + " .hashCode()[" + a2.hashCode() + "]"); + if (a1.toString().equals(a2.toString())) + fail(a1 + ".toString() == " + a2 + ".toString()"); + } catch(Throwable t) { + fail(a1 + " != " + a2 + ": " + t); + } + } + + // Verfification method for serialization/deserialization + + static void checkSerialization(AnnotatedElement e, Class annoType) { + numTests++; + T a1 = e.getAnnotation(annoType); + Object a2 = deepCopy(a1); + try { + if (!a1.equals(a2)) + fail("Serialization: " + a1 + " != " + a2); + if (a1.hashCode() != a2.hashCode()) + fail("Serialization: " + a1 + ".hashCode() [" + a1.hashCode() + "] != " + a2 + " .hashCode()["+a2.hashCode()+"]"); + if (!(a1.toString().equals(a2.toString()))) + fail("Serialization: " + a1 + ".toString() != " + a2 + ".toString()"); + } catch(Throwable t) { + fail("Serialization: " + a1 + " == " + a2 + ": " + t); + } + } + + private static Object deepCopy(Object original) { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(original); + oos.flush(); + ByteArrayInputStream bin = new ByteArrayInputStream( + bos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bin); + return ois.readObject(); + } catch(Exception e) { + throw new IllegalArgumentException(e); + } + } + + // Verification method for inheritance test + static void checkInheritence(AnnotatedElement e, boolean shouldHaveFoo, boolean shouldHaveBar) { + numTests++; + try { + boolean hasFoo = e.isAnnotationPresent(Foo.class); + boolean hasBar = e.isAnnotationPresent(Bar.class); + if (hasFoo != shouldHaveFoo || hasBar != shouldHaveBar) + fail("Inheritance(1): " + e +" - Foo: " + hasFoo + ", Bar: " + hasBar); + + // Now test getAnnotations + hasFoo = hasBar = false; + Annotation[] allAnnotations = e.getAnnotations(); + for (Annotation a : allAnnotations) { + if (a instanceof Foo) + hasFoo = true; + else if (a instanceof Bar) + hasBar = true; + } + if (hasFoo != shouldHaveFoo ||hasBar != shouldHaveBar) + fail("Inheritance(2): " + e +" - Foo: " + hasFoo + ", Bar: " + hasBar); + } catch(Throwable t) { + fail("Inheritance: " + e +": " + t); + } + } + + // Verification method for declared annotations test + static void checkDeclaredAnnotations(AnnotatedElement e, boolean shouldHaveFoo, boolean shouldHaveBar) { + numTests++; + try { + boolean hasFoo = false; + boolean hasBar = false; + Annotation[] declaredAnnotations = e.getDeclaredAnnotations(); + for (Annotation a : declaredAnnotations) { + if (a instanceof Foo) + hasFoo = true; + else if (a instanceof Bar) + hasBar = true; + } + if (hasFoo != shouldHaveFoo ||hasBar != shouldHaveBar) + fail("Declared annotations: " + e +" - Foo: " + hasFoo + ", Bar: " + hasBar); + } catch(Throwable t) { + fail("Declared annotations: " + e +": " + t); + } + } + + + // ANNOTATED METHODS + + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + public void scalarTypesMethod() { } + + @ScalarTypesWithDefault ( ) + public void scalarTypesAcceptDefaultMethod() { } + + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + public void scalarTypesOverrideDefaultMethod() { } + + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + public void emptyArrayTypesMethod() { } + + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + public void singleElementArrayTypesMethod() { } + + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + public void twoElementArrayTypesMethod() { } + + @ArrayTypesWithDefault ( + ) + public void arrayTypesAcceptDefaultMethod() { } + + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + public void arrayTypesOverrideDefaultMethod() { } + + // Marker + @Marker public void markerMethod() { } + + // Single-member (shorthand) + @SingleMemberByte(1) public void SingleMemberByte() {} + @SingleMemberShort(2) public void SingleMemberShort() {} + @SingleMemberInt(3) public void SingleMemberInt() {} + @SingleMemberLong(4L) public void SingleMemberLong() {} + @SingleMemberChar('5') public void SingleMemberChar() {} + @SingleMemberFloat(6.0f) public void SingleMemberFloat() {} + @SingleMemberDouble(7.0) public void SingleMemberDouble() {} + @SingleMemberBoolean(true) public void SingleMemberBoolean() {} + @SingleMemberString("custom") public void SingleMemberString() {} + @SingleMemberClass(Map.class) public void SingleMemberClass() {} + @SingleMemberEnum(Stooge.MOE) public void SingleMemberEnum() {} + + // Single-member with default (Override) + @SingleMemberByteWithDef(1) public void SingleMemberByteOvrdDef() {} + @SingleMemberShortWithDef(2) public void SingleMemberShortOvrdDef() {} + @SingleMemberIntWithDef(3) public void SingleMemberIntOvrdDef() {} + @SingleMemberLongWithDef(4L) public void SingleMemberLongOvrdDef() {} + @SingleMemberCharWithDef('5') public void SingleMemberCharOvrdDef() {} + @SingleMemberFloatWithDef(6.0f) public void SingleMemberFloatOvrdDef() {} + @SingleMemberDoubleWithDef(7.0) public void SingleMemberDoubleOvrdDef() {} + @SingleMemberBooleanWithDef(true) public void SingleMemberBooleanOvrdDef() {} + @SingleMemberStringWithDef("custom") public void SingleMemberStringOvrdDef() {} + @SingleMemberClassWithDef(Map.class) public void SingleMemberClassOvrdDef() {} + @SingleMemberEnumWithDef(Stooge.MOE) public void SingleMemberEnumOvrdDef() {} + + // Single-member with default (Accept) + @SingleMemberByteWithDef public void SingleMemberByteAcceptDef() {} + @SingleMemberShortWithDef public void SingleMemberShortAcceptDef() {} + @SingleMemberIntWithDef public void SingleMemberIntAcceptDef() {} + @SingleMemberLongWithDef public void SingleMemberLongAcceptDef() {} + @SingleMemberCharWithDef public void SingleMemberCharAcceptDef() {} + @SingleMemberFloatWithDef public void SingleMemberFloatAcceptDef() {} + @SingleMemberDoubleWithDef public void SingleMemberDoubleAcceptDef() {} + @SingleMemberBooleanWithDef public void SingleMemberBooleanAcceptDef() {} + @SingleMemberStringWithDef public void SingleMemberStringAcceptDef() {} + @SingleMemberClassWithDef public void SingleMemberClassAcceptDef() {} + @SingleMemberEnumWithDef public void SingleMemberEnumAcceptDef() {} + + // Single member array (empty array) + @SingleMemberByteArray({}) public void SingleMemberByteArrEmpty() {} + @SingleMemberShortArray({}) public void SingleMemberShortArrEmpty() {} + @SingleMemberIntArray({}) public void SingleMemberIntArrEmpty() {} + @SingleMemberLongArray({}) public void SingleMemberLongArrEmpty() {} + @SingleMemberCharArray({}) public void SingleMemberCharArrEmpty() {} + @SingleMemberFloatArray({}) public void SingleMemberFloatArrEmpty() {} + @SingleMemberDoubleArray({}) public void SingleMemberDoubleArrEmpty() {} + @SingleMemberBooleanArray({})public void SingleMemberBooleanArrEmpty() {} + @SingleMemberStringArray({}) public void SingleMemberStringArrEmpty() {} + @SingleMemberClassArray({}) public void SingleMemberClassArrEmpty() {} + @SingleMemberEnumArray({}) public void SingleMemberEnumArrEmpty() {} + + // Single member array (one-element shorthand) + @SingleMemberByteArray(1) public void SingleMemberByteArrOne() {} + @SingleMemberShortArray(2) public void SingleMemberShortArrOne() {} + @SingleMemberIntArray(3) public void SingleMemberIntArrOne() {} + @SingleMemberLongArray(4L) public void SingleMemberLongArrOne() {} + @SingleMemberCharArray('5') public void SingleMemberCharArrOne() {} + @SingleMemberFloatArray(6.0f) public void SingleMemberFloatArrOne() {} + @SingleMemberDoubleArray(7.0) public void SingleMemberDoubleArrOne() {} + @SingleMemberBooleanArray(true) public void SingleMemberBooleanArrOne() {} + @SingleMemberStringArray("custom") public void SingleMemberStringArrOne() {} + @SingleMemberClassArray(Map.class) public void SingleMemberClassArrOne() {} + @SingleMemberEnumArray(Stooge.MOE) public void SingleMemberEnumArrOne() {} + + // Single member array (two elements) + @SingleMemberByteArray({1, 2}) public void SingleMemberByteArrTwo() {} + @SingleMemberShortArray({2, 3}) public void SingleMemberShortArrTwo() {} + @SingleMemberIntArray({3, 4}) public void SingleMemberIntArrTwo() {} + @SingleMemberLongArray({4L, 5L}) public void SingleMemberLongArrTwo() {} + @SingleMemberCharArray({'5', '6'}) public void SingleMemberCharArrTwo() {} + @SingleMemberFloatArray({6.0f, 7.0f}) public void SingleMemberFloatArrTwo() {} + @SingleMemberDoubleArray({7.0, 8.0}) public void SingleMemberDoubleArrTwo() {} + @SingleMemberBooleanArray({true, false}) public void SingleMemberBooleanArrTwo(){} + @SingleMemberStringArray({"custom", "paint"}) public void SingleMemberStringArrTwo(){} + @SingleMemberClassArray({Map.class, Set.class}) public void SingleMemberClassArrTwo() {} + @SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) public void SingleMemberEnumArrTwo() {} + + // Single member array with default (override) + @SingleMemberByteArrayDef(1) public void SingleMemberByteArrOvrdDef() {} + @SingleMemberShortArrayDef(2) public void SingleMemberShortArrOvrdDef() {} + @SingleMemberIntArrayDef(3) public void SingleMemberIntArrOvrdDef() {} + @SingleMemberLongArrayDef(4L) public void SingleMemberLongArrOvrdDef() {} + @SingleMemberCharArrayDef('5') public void SingleMemberCharArrOvrdDef() {} + @SingleMemberFloatArrayDef(6.0f) public void SingleMemberFloatArrOvrdDef() {} + @SingleMemberDoubleArrayDef(7.0) public void SingleMemberDoubleArrOvrdDef() {} + @SingleMemberBooleanArrayDef(true) public void SingleMemberBooleanArrOvrdDef(){} + @SingleMemberStringArrayDef("custom") public void SingleMemberStringArrOvrdDef() {} + @SingleMemberClassArrayDef(Map.class) public void SingleMemberClassArrOvrdDef() {} + @SingleMemberEnumArrayDef(Stooge.MOE) public void SingleMemberEnumArrOvrdDef() {} + + // Single member array with default - accept + @SingleMemberByteArrayDef public void SingleMemberByteArrAcceptDef() {} + @SingleMemberShortArrayDef public void SingleMemberShortArrAcceptDef() {} + @SingleMemberIntArrayDef public void SingleMemberIntArrAcceptDef() {} + @SingleMemberLongArrayDef public void SingleMemberLongArrAcceptDef() {} + @SingleMemberCharArrayDef public void SingleMemberCharArrAcceptDef() {} + @SingleMemberFloatArrayDef public void SingleMemberFloatArrAcceptDef() {} + @SingleMemberDoubleArrayDef public void SingleMemberDoubleArrAcceptDef() {} + @SingleMemberBooleanArrayDef public void SingleMemberBooleanArrAcceptDef() {} + @SingleMemberStringArrayDef public void SingleMemberStringArrAcceptDef() {} + @SingleMemberClassArrayDef public void SingleMemberClassArrAcceptDef() {} + @SingleMemberEnumArrayDef public void SingleMemberEnumArrAcceptDef() {} + + // ANNOTATED FIELDS + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + public int scalarTypesField; + + @ScalarTypesWithDefault ( ) + public int scalarTypesAcceptDefaultField; + + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + public int scalarTypesOverrideDefaultField; + + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + public int emptyArrayTypesField; + + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + public int singleElementArrayTypesField; + + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + public int twoElementArrayTypesField; + + @ArrayTypesWithDefault ( ) + public int arrayTypesAcceptDefaultField; + + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + public int arrayTypesOverrideDefaultField; + + @Marker public int markerField; + + // Single-member (shorthand) + @SingleMemberByte(1) public int SingleMemberByteField; + @SingleMemberShort(2) public int SingleMemberShortField; + @SingleMemberInt(3) public int SingleMemberIntField; + @SingleMemberLong(4L) public int SingleMemberLongField; + @SingleMemberChar('5') public int SingleMemberCharField; + @SingleMemberFloat(6.0f) public int SingleMemberFloatField; + @SingleMemberDouble(7.0) public int SingleMemberDoubleField; + @SingleMemberBoolean(true) public int SingleMemberBooleanField; + @SingleMemberString("custom") public int SingleMemberStringField; + @SingleMemberClass(Map.class) public int SingleMemberClassField; + @SingleMemberEnum(Stooge.MOE) public int SingleMemberEnumField; + + // Single-member with default (Override) + @SingleMemberByteWithDef(1) public int SingleMemberByteOvrdDefField; + @SingleMemberShortWithDef(2) public int SingleMemberShortOvrdDefField; + @SingleMemberIntWithDef(3) public int SingleMemberIntOvrdDefField; + @SingleMemberLongWithDef(4L) public int SingleMemberLongOvrdDefField; + @SingleMemberCharWithDef('5') public int SingleMemberCharOvrdDefField; + @SingleMemberFloatWithDef(6.0f) public int SingleMemberFloatOvrdDefField; + @SingleMemberDoubleWithDef(7.0) public int SingleMemberDoubleOvrdDefField; + @SingleMemberBooleanWithDef(true) public int SingleMemberBooleanOvrdDefField; + @SingleMemberStringWithDef("custom") public int SingleMemberStringOvrdDefField; + @SingleMemberClassWithDef(Map.class) public int SingleMemberClassOvrdDefField; + @SingleMemberEnumWithDef(Stooge.MOE) public int SingleMemberEnumOvrdDefField; + + // Single-member with default (Accept) + @SingleMemberByteWithDef public int SingleMemberByteAcceptDefField; + @SingleMemberShortWithDef public int SingleMemberShortAcceptDefField; + @SingleMemberIntWithDef public int SingleMemberIntAcceptDefField; + @SingleMemberLongWithDef public int SingleMemberLongAcceptDefField; + @SingleMemberCharWithDef public int SingleMemberCharAcceptDefField; + @SingleMemberFloatWithDef public int SingleMemberFloatAcceptDefField; + @SingleMemberDoubleWithDef public int SingleMemberDoubleAcceptDefField; + @SingleMemberBooleanWithDef public int SingleMemberBooleanAcceptDefField; + @SingleMemberStringWithDef public int SingleMemberStringAcceptDefField; + @SingleMemberClassWithDef public int SingleMemberClassAcceptDefField; + @SingleMemberEnumWithDef public int SingleMemberEnumAcceptDefField; + + // Single member array (empty array) + @SingleMemberByteArray({}) public int SingleMemberByteArrEmptyField; + @SingleMemberShortArray({}) public int SingleMemberShortArrEmptyField; + @SingleMemberIntArray({}) public int SingleMemberIntArrEmptyField; + @SingleMemberLongArray({}) public int SingleMemberLongArrEmptyField; + @SingleMemberCharArray({}) public int SingleMemberCharArrEmptyField; + @SingleMemberFloatArray({}) public int SingleMemberFloatArrEmptyField; + @SingleMemberDoubleArray({}) public int SingleMemberDoubleArrEmptyField; + @SingleMemberBooleanArray({})public int SingleMemberBooleanArrEmptyField; + @SingleMemberStringArray({}) public int SingleMemberStringArrEmptyField; + @SingleMemberClassArray({}) public int SingleMemberClassArrEmptyField; + @SingleMemberEnumArray({}) public int SingleMemberEnumArrEmptyField; + + // Single member array (one-element shorthand) + @SingleMemberByteArray(1) public int SingleMemberByteArrOneField; + @SingleMemberShortArray(2) public int SingleMemberShortArrOneField; + @SingleMemberIntArray(3) public int SingleMemberIntArrOneField; + @SingleMemberLongArray(4L) public int SingleMemberLongArrOneField; + @SingleMemberCharArray('5') public int SingleMemberCharArrOneField; + @SingleMemberFloatArray(6.0f) public int SingleMemberFloatArrOneField; + @SingleMemberDoubleArray(7.0) public int SingleMemberDoubleArrOneField; + @SingleMemberBooleanArray(true) public int SingleMemberBooleanArrOneField; + @SingleMemberStringArray("custom") public int SingleMemberStringArrOneField; + @SingleMemberClassArray(Map.class) public int SingleMemberClassArrOneField; + @SingleMemberEnumArray(Stooge.MOE) public int SingleMemberEnumArrOneField; + + // Single member array (two elements) + @SingleMemberByteArray({1, 2}) public int SingleMemberByteArrTwoField; + @SingleMemberShortArray({2, 3}) public int SingleMemberShortArrTwoField; + @SingleMemberIntArray({3, 4}) public int SingleMemberIntArrTwoField; + @SingleMemberLongArray({4L, 5L}) public int SingleMemberLongArrTwoField; + @SingleMemberCharArray({'5', '6'}) public int SingleMemberCharArrTwoField; + @SingleMemberFloatArray({6.0f, 7.0f}) public int SingleMemberFloatArrTwoField; + @SingleMemberDoubleArray({7.0, 8.0}) public int SingleMemberDoubleArrTwoField; + @SingleMemberBooleanArray({true,false}) public int SingleMemberBooleanArrTwoField; + @SingleMemberStringArray({"custom", "paint"}) public int SingleMemberStringArrTwoField; + @SingleMemberClassArray({Map.class, Set.class}) public int SingleMemberClassArrTwoField; + @SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) public int SingleMemberEnumArrTwoField; + + // Single member array with default (override) + @SingleMemberByteArrayDef(1) public int SingleMemberByteArrOvrdDefField; + @SingleMemberShortArrayDef(2) public int SingleMemberShortArrOvrdDefField; + @SingleMemberIntArrayDef(3) public int SingleMemberIntArrOvrdDefField; + @SingleMemberLongArrayDef(4L) public int SingleMemberLongArrOvrdDefField; + @SingleMemberCharArrayDef('5') public int SingleMemberCharArrOvrdDefField; + @SingleMemberFloatArrayDef(6.0f) public int SingleMemberFloatArrOvrdDefField; + @SingleMemberDoubleArrayDef(7.0) public int SingleMemberDoubleArrOvrdDefField; + @SingleMemberBooleanArrayDef(true) public int SingleMemberBooleanArrOvrdDefField; + @SingleMemberStringArrayDef("custom") public int SingleMemberStringArrOvrdDefField; + @SingleMemberClassArrayDef(Map.class) public int SingleMemberClassArrOvrdDefField; + @SingleMemberEnumArrayDef(Stooge.MOE) public int SingleMemberEnumArrOvrdDefField; + + // Single member array with default - accept + @SingleMemberByteArrayDef public int SingleMemberByteArrAcceptDefField; + @SingleMemberShortArrayDef public int SingleMemberShortArrAcceptDefField; + @SingleMemberIntArrayDef public int SingleMemberIntArrAcceptDefField; + @SingleMemberLongArrayDef public int SingleMemberLongArrAcceptDefField; + @SingleMemberCharArrayDef public int SingleMemberCharArrAcceptDefField; + @SingleMemberFloatArrayDef public int SingleMemberFloatArrAcceptDefField; + @SingleMemberDoubleArrayDef public int SingleMemberDoubleArrAcceptDefField; + @SingleMemberBooleanArrayDef public int SingleMemberBooleanArrAcceptDefField; + @SingleMemberStringArrayDef public int SingleMemberStringArrAcceptDefField; + @SingleMemberClassArrayDef public int SingleMemberClassArrAcceptDefField; + @SingleMemberEnumArrayDef public int SingleMemberEnumArrAcceptDefField; + + // ANNOTATED ENUM CONSTANTS + enum TestType { + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + scalarTypesField, + + @ScalarTypesWithDefault ( ) + scalarTypesAcceptDefaultField, + + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + scalarTypesOverrideDefaultField, + + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + emptyArrayTypesField, + + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + singleElementArrayTypesField, + + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + twoElementArrayTypesField, + + @ArrayTypesWithDefault ( ) + arrayTypesAcceptDefaultField, + + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + arrayTypesOverrideDefaultField, + + // marker + @Marker marker, + + // Single-member (shorthand) + @SingleMemberByte(1) SingleMemberByte, + @SingleMemberShort(2) SingleMemberShort, + @SingleMemberInt(3) SingleMemberInt, + @SingleMemberLong(4L) SingleMemberLong, + @SingleMemberChar('5') SingleMemberChar, + @SingleMemberFloat(6.0f) SingleMemberFloat, + @SingleMemberDouble(7.0) SingleMemberDouble, + @SingleMemberBoolean(true) SingleMemberBoolean, + @SingleMemberString("custom") SingleMemberString, + @SingleMemberClass(Map.class) SingleMemberClass, + @SingleMemberEnum(Stooge.MOE) SingleMemberEnum, + + // Single-member with default (Override) + @SingleMemberByteWithDef(1) SingleMemberByteOvrdDef, + @SingleMemberShortWithDef(2) SingleMemberShortOvrdDef, + @SingleMemberIntWithDef(3) SingleMemberIntOvrdDef, + @SingleMemberLongWithDef(4L) SingleMemberLongOvrdDef, + @SingleMemberCharWithDef('5') SingleMemberCharOvrdDef, + @SingleMemberFloatWithDef(6.0f) SingleMemberFloatOvrdDef, + @SingleMemberDoubleWithDef(7.0) SingleMemberDoubleOvrdDef, + @SingleMemberBooleanWithDef(true) SingleMemberBooleanOvrdDef, + @SingleMemberStringWithDef("custom") SingleMemberStringOvrdDef, + @SingleMemberClassWithDef(Map.class) SingleMemberClassOvrdDef, + @SingleMemberEnumWithDef(Stooge.MOE) SingleMemberEnumOvrdDef, + + // Single-member with default (Accept) + @SingleMemberByteWithDef SingleMemberByteAcceptDef, + @SingleMemberShortWithDef SingleMemberShortAcceptDef, + @SingleMemberIntWithDef SingleMemberIntAcceptDef, + @SingleMemberLongWithDef SingleMemberLongAcceptDef, + @SingleMemberCharWithDef SingleMemberCharAcceptDef, + @SingleMemberFloatWithDef SingleMemberFloatAcceptDef, + @SingleMemberDoubleWithDef SingleMemberDoubleAcceptDef, + @SingleMemberBooleanWithDef SingleMemberBooleanAcceptDef, + @SingleMemberStringWithDef SingleMemberStringAcceptDef, + @SingleMemberClassWithDef SingleMemberClassAcceptDef, + @SingleMemberEnumWithDef SingleMemberEnumAcceptDef, + + // Single member array (empty array) + @SingleMemberByteArray({}) SingleMemberByteArrEmpty, + @SingleMemberShortArray({}) SingleMemberShortArrEmpty, + @SingleMemberIntArray({}) SingleMemberIntArrEmpty, + @SingleMemberLongArray({}) SingleMemberLongArrEmpty, + @SingleMemberCharArray({}) SingleMemberCharArrEmpty, + @SingleMemberFloatArray({}) SingleMemberFloatArrEmpty, + @SingleMemberDoubleArray({}) SingleMemberDoubleArrEmpty, + @SingleMemberBooleanArray({})SingleMemberBooleanArrEmpty, + @SingleMemberStringArray({}) SingleMemberStringArrEmpty, + @SingleMemberClassArray({}) SingleMemberClassArrEmpty, + @SingleMemberEnumArray({}) SingleMemberEnumArrEmpty, + + // Single member array (one-element shorthand) + @SingleMemberByteArray(1) SingleMemberByteArrOne, + @SingleMemberShortArray(2) SingleMemberShortArrOne, + @SingleMemberIntArray(3) SingleMemberIntArrOne, + @SingleMemberLongArray(4L) SingleMemberLongArrOne, + @SingleMemberCharArray('5') SingleMemberCharArrOne, + @SingleMemberFloatArray(6.0f) SingleMemberFloatArrOne, + @SingleMemberDoubleArray(7.0) SingleMemberDoubleArrOne, + @SingleMemberBooleanArray(true) SingleMemberBooleanArrOne, + @SingleMemberStringArray("custom") SingleMemberStringArrOne, + @SingleMemberClassArray(Map.class) SingleMemberClassArrOne, + @SingleMemberEnumArray(Stooge.MOE) SingleMemberEnumArrOne, + + // Single member array (two elements) + @SingleMemberByteArray({1, 2}) SingleMemberByteArrTwo, + @SingleMemberShortArray({2, 3}) SingleMemberShortArrTwo, + @SingleMemberIntArray({3, 4}) SingleMemberIntArrTwo, + @SingleMemberLongArray({4L, 5L}) SingleMemberLongArrTwo, + @SingleMemberCharArray({'5', '6'}) SingleMemberCharArrTwo, + @SingleMemberFloatArray({6.0f, 7.0f}) SingleMemberFloatArrTwo, + @SingleMemberDoubleArray({7.0, 8.0}) SingleMemberDoubleArrTwo, + @SingleMemberBooleanArray({true,false}) SingleMemberBooleanArrTwo, + @SingleMemberStringArray({"custom", "paint"}) SingleMemberStringArrTwo, + @SingleMemberClassArray({Map.class, Set.class}) SingleMemberClassArrTwo, + @SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) SingleMemberEnumArrTwo, + + // Single member array with default (override) + @SingleMemberByteArrayDef(1) SingleMemberByteArrOvrdDef, + @SingleMemberShortArrayDef(2) SingleMemberShortArrOvrdDef, + @SingleMemberIntArrayDef(3) SingleMemberIntArrOvrdDef, + @SingleMemberLongArrayDef(4L) SingleMemberLongArrOvrdDef, + @SingleMemberCharArrayDef('5') SingleMemberCharArrOvrdDef, + @SingleMemberFloatArrayDef(6.0f) SingleMemberFloatArrOvrdDef, + @SingleMemberDoubleArrayDef(7.0) SingleMemberDoubleArrOvrdDef, + @SingleMemberBooleanArrayDef(true) SingleMemberBooleanArrOvrdDef, + @SingleMemberStringArrayDef("custom") SingleMemberStringArrOvrdDef, + @SingleMemberClassArrayDef(Map.class) SingleMemberClassArrOvrdDef, + @SingleMemberEnumArrayDef(Stooge.MOE) SingleMemberEnumArrOvrdDef, + + // Single member array with default - accept + @SingleMemberByteArrayDef SingleMemberByteArrAcceptDef, + @SingleMemberShortArrayDef SingleMemberShortArrAcceptDef, + @SingleMemberIntArrayDef SingleMemberIntArrAcceptDef, + @SingleMemberLongArrayDef SingleMemberLongArrAcceptDef, + @SingleMemberCharArrayDef SingleMemberCharArrAcceptDef, + @SingleMemberFloatArrayDef SingleMemberFloatArrAcceptDef, + @SingleMemberDoubleArrayDef SingleMemberDoubleArrAcceptDef, + @SingleMemberBooleanArrayDef SingleMemberBooleanArrAcceptDef, + @SingleMemberStringArrayDef SingleMemberStringArrAcceptDef, + @SingleMemberClassArrayDef SingleMemberClassArrAcceptDef, + @SingleMemberEnumArrayDef SingleMemberEnumArrAcceptDef, + } + + // ANNOTATED CONSTRUCTORS + + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + public UnitTest(Iterator it) { } // scalar types + + @ScalarTypesWithDefault ( ) + public UnitTest(Set s) { } // scalarTypesAcceptDefault + + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + public UnitTest(Map s) { } // scalarTypesOverrideDefault + + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + public UnitTest(List l){ } // emptyArrayTypes + + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + public UnitTest(Collection c) { } // singleElementArrayTypes + + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + public UnitTest(SortedSet ss) { } // twoElementArrayTypes + + @ArrayTypesWithDefault ( ) + public UnitTest(SortedMap sm) { } // arrayTypesAcceptDefault + + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + public UnitTest(RandomAccess r) { } // arrayTypesOverrideDefault + + // Marker + @Marker public UnitTest() { } // marker + + // Single-member (shorthand) + @SingleMemberByte(1) public UnitTest(byte b) { } + @SingleMemberShort(2) public UnitTest(short s) { } + @SingleMemberInt(3) public UnitTest(int i) { } + @SingleMemberLong(4L) public UnitTest(long l) { } + @SingleMemberChar('5') public UnitTest(char c) { } + @SingleMemberFloat(6.0f) public UnitTest(float f) { } + @SingleMemberDouble(7.0) public UnitTest(double d) { } + @SingleMemberBoolean(true) public UnitTest(boolean b) { } + @SingleMemberString("custom") public UnitTest(String s) { } + @SingleMemberClass(Map.class) public UnitTest(Class c) { } + @SingleMemberEnum(Stooge.MOE) public UnitTest(Enum e) { } + + // Single-member with default (Override) + @SingleMemberByteWithDef(1) public UnitTest(byte b, Set s) { } + @SingleMemberShortWithDef(2) public UnitTest(short s, Set x) { } + @SingleMemberIntWithDef(3) public UnitTest(int i, Set s) { } + @SingleMemberLongWithDef(4L) public UnitTest(long l, Set s) { } + @SingleMemberCharWithDef('5') public UnitTest(char c, Set s) { } + @SingleMemberFloatWithDef(6.0f) public UnitTest(float f, Set s) { } + @SingleMemberDoubleWithDef(7.0) public UnitTest(double d, Set s) { } + @SingleMemberBooleanWithDef(true) public UnitTest(boolean b, Set s) { } + @SingleMemberStringWithDef("custom") public UnitTest(String s, Set x) { } + @SingleMemberClassWithDef(Map.class) public UnitTest(Class c, Set s) { } + @SingleMemberEnumWithDef(Stooge.MOE) public UnitTest(Enum e, Set s) { } + + // Single-member with default (Accept) + @SingleMemberByteWithDef public UnitTest(byte b, Map m) { } + @SingleMemberShortWithDef public UnitTest(short s, Map m) { } + @SingleMemberIntWithDef public UnitTest(int i, Map m) { } + @SingleMemberLongWithDef public UnitTest(long l, Map m) { } + @SingleMemberCharWithDef public UnitTest(char c, Map m) { } + @SingleMemberFloatWithDef public UnitTest(float f, Map m) { } + @SingleMemberDoubleWithDef public UnitTest(double d, Map m) { } + @SingleMemberBooleanWithDef public UnitTest(boolean b, Map m) { } + @SingleMemberStringWithDef public UnitTest(String s, Map m) { } + @SingleMemberClassWithDef public UnitTest(Class c, Map m) { } + @SingleMemberEnumWithDef public UnitTest(Enum e, Map m) { } + + // Single member array (empty array) + @SingleMemberByteArray({}) public UnitTest(byte[] b) { } + @SingleMemberShortArray({}) public UnitTest(short[] s) { } + @SingleMemberIntArray({}) public UnitTest(int[] i) { } + @SingleMemberLongArray({}) public UnitTest(long[] l) { } + @SingleMemberCharArray({}) public UnitTest(char[] c) { } + @SingleMemberFloatArray({}) public UnitTest(float[] f) { } + @SingleMemberDoubleArray({}) public UnitTest(double[] d) { } + @SingleMemberBooleanArray({})public UnitTest(boolean[] b) { } + @SingleMemberStringArray({}) public UnitTest(String[] s) { } + @SingleMemberClassArray({}) public UnitTest(Class[] c) { } + @SingleMemberEnumArray({}) public UnitTest(Enum[] e) { } + + // Single member array (one-element shorthand) + @SingleMemberByteArray(1) public UnitTest(byte[] b, Set s) { } + @SingleMemberShortArray(2) public UnitTest(short[] s, Set x) { } + @SingleMemberIntArray(3) public UnitTest(int[] i, Set s) { } + @SingleMemberLongArray(4L) public UnitTest(long[] l, Set s) { } + @SingleMemberCharArray('5') public UnitTest(char[] c, Set s) { } + @SingleMemberFloatArray(6.0f) public UnitTest(float[] f, Set s) { } + @SingleMemberDoubleArray(7.0) public UnitTest(double[] d, Set s) { } + @SingleMemberBooleanArray(true) public UnitTest(boolean[] b, Set s) { } + @SingleMemberStringArray("custom") public UnitTest(String[] s, Set x) { } + @SingleMemberClassArray(Map.class) public UnitTest(Class[] c, Set s) { } + @SingleMemberEnumArray(Stooge.MOE) public UnitTest(Enum[] e, Set s) { } + + // Single member array (two elements) + @SingleMemberByteArray({1, 2}) public UnitTest(byte[] b, Map m) { } + @SingleMemberShortArray({2, 3}) public UnitTest(short[] s, Map m) { } + @SingleMemberIntArray({3, 4}) public UnitTest(int[] i, Map m) { } + @SingleMemberLongArray({4L, 5L}) public UnitTest(long[] l, Map m) { } + @SingleMemberCharArray({'5', '6'}) public UnitTest(char[] c, Map m) { } + @SingleMemberFloatArray({6.0f, 7.0f}) public UnitTest(float[] f, Map m) { } + @SingleMemberDoubleArray({7.0, 8.0}) public UnitTest(double[] d, Map m) { } + @SingleMemberBooleanArray({true, false}) public UnitTest(boolean[] b, Map m) { } + @SingleMemberStringArray({"custom", "paint"}) public UnitTest(String[] s, Map m) { } + @SingleMemberClassArray({Map.class,Set.class}) public UnitTest(Class[] c, Map m) { } + @SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) public UnitTest(Enum[] e, Map m) { } + + + // Single member array with default (override) + @SingleMemberByteArrayDef(1) public UnitTest(byte[] b, List l) { } + @SingleMemberShortArrayDef(2) public UnitTest(short[] s, List l) { } + @SingleMemberIntArrayDef(3) public UnitTest(int[] i, List l) { } + @SingleMemberLongArrayDef(4L) public UnitTest(long[] l, List x) { } + @SingleMemberCharArrayDef('5') public UnitTest(char[] c, List l) { } + @SingleMemberFloatArrayDef(6.0f) public UnitTest(float[] f, List l) { } + @SingleMemberDoubleArrayDef(7.0) public UnitTest(double[] d, List l) { } + @SingleMemberBooleanArrayDef(true) public UnitTest(boolean[] b, List l) { } + @SingleMemberStringArrayDef("custom") public UnitTest(String[] s, List l) { } + @SingleMemberClassArrayDef(Map.class) public UnitTest(Class[] c, List l) { } + @SingleMemberEnumArrayDef(Stooge.MOE) public UnitTest(Enum[] e, List l) { } + + // Single member array with default - accept + @SingleMemberByteArrayDef public UnitTest(byte[] b, Collection c) { } + @SingleMemberShortArrayDef public UnitTest(short[] s, Collection c) { } + @SingleMemberIntArrayDef public UnitTest(int[] i, Collection c) { } + @SingleMemberLongArrayDef public UnitTest(long[] l, Collection c) { } + @SingleMemberCharArrayDef public UnitTest(char[] c, Collection x) { } + @SingleMemberFloatArrayDef public UnitTest(float[] f, Collection c) { } + @SingleMemberDoubleArrayDef public UnitTest(double[] d, Collection c) { } + @SingleMemberBooleanArrayDef public UnitTest(boolean[] b, Collection c) { } + @SingleMemberStringArrayDef public UnitTest(String[] s, Collection c) { } + @SingleMemberClassArrayDef public UnitTest(Class[] c, Collection x) { } + @SingleMemberEnumArrayDef public UnitTest(Enum[] e, Collection c) { } + + // ANNOTATED PARAMETERS + + public void scalarTypesParam( + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + int x) { } + + + public void scalarTypesAcceptDefaultParam( + @ScalarTypesWithDefault int x) { } + + public void scalarTypesOverrideDefaultParam( + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + int x) { } + + public void emptyArrayTypesParam( + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + int x) { } + + public void singleElementArrayTypesParam( + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + int x) { } + + public void twoElementArrayTypesParam( + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + int x) { } + + public void arrayTypesAcceptDefaultParam( + @ArrayTypesWithDefault + int x) { } + + public void arrayTypesOverrideDefaultParam( + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + int x) { } + + // Marker + public void markerParam(@Marker int x) { } + + // Single-member (shorthand) + public void SingleMemberByteParam(@SingleMemberByte(1) int x) {} + public void SingleMemberShortParam(@SingleMemberShort(2) int x) {} + public void SingleMemberIntParam(@SingleMemberInt(3) int x) {} + public void SingleMemberLongParam(@SingleMemberLong(4L) int x) {} + public void SingleMemberCharParam(@SingleMemberChar('5') int x) {} + public void SingleMemberFloatParam(@SingleMemberFloat(6.0f) int x) {} + public void SingleMemberDoubleParam(@SingleMemberDouble(7.0) int x) {} + public void SingleMemberBooleanParam(@SingleMemberBoolean(true) int x) {} + public void SingleMemberStringParam(@SingleMemberString("custom") int x) {} + public void SingleMemberClassParam(@SingleMemberClass(Map.class) int x) {} + public void SingleMemberEnumParam(@SingleMemberEnum(Stooge.MOE) int x) {} + + // Single-member with default (Override) + public void SingleMemberByteOvrdDefParam(@SingleMemberByteWithDef(1) int x) {} + public void SingleMemberShortOvrdDefParam(@SingleMemberShortWithDef(2) int x) {} + public void SingleMemberIntOvrdDefParam(@SingleMemberIntWithDef(3) int x) {} + public void SingleMemberLongOvrdDefParam(@SingleMemberLongWithDef(4L) int x) {} + public void SingleMemberCharOvrdDefParam(@SingleMemberCharWithDef('5') int x) {} + public void SingleMemberFloatOvrdDefParam(@SingleMemberFloatWithDef(6.0f) int x) {} + public void SingleMemberDoubleOvrdDefParam(@SingleMemberDoubleWithDef(7.0) int x) {} + public void SingleMemberBooleanOvrdDefParam(@SingleMemberBooleanWithDef(true) int x) {} + public void SingleMemberStringOvrdDefParam(@SingleMemberStringWithDef("custom") int x) {} + public void SingleMemberClassOvrdDefParam(@SingleMemberClassWithDef(Map.class) int x) {} + public void SingleMemberEnumOvrdDefParam(@SingleMemberEnumWithDef(Stooge.MOE) int x) {} + + // Single-member with default (Accept) + public void SingleMemberByteAcceptDefParam(@SingleMemberByteWithDef int x) {} + public void SingleMemberShortAcceptDefParam(@SingleMemberShortWithDef int x) {} + public void SingleMemberIntAcceptDefParam(@SingleMemberIntWithDef int x) {} + public void SingleMemberLongAcceptDefParam(@SingleMemberLongWithDef int x) {} + public void SingleMemberCharAcceptDefParam(@SingleMemberCharWithDef int x) {} + public void SingleMemberFloatAcceptDefParam(@SingleMemberFloatWithDef int x) {} + public void SingleMemberDoubleAcceptDefParam(@SingleMemberDoubleWithDef int x) {} + public void SingleMemberBooleanAcceptDefParam(@SingleMemberBooleanWithDef int x){} + public void SingleMemberStringAcceptDefParam(@SingleMemberStringWithDef int x) {} + public void SingleMemberClassAcceptDefParam(@SingleMemberClassWithDef int x) {} + public void SingleMemberEnumAcceptDefParam(@SingleMemberEnumWithDef int x) {} + + // Single member array (empty array) + public void SingleMemberByteArrEmptyParam(@SingleMemberByteArray({}) int x) {} + public void SingleMemberShortArrEmptyParam(@SingleMemberShortArray({}) int x) {} + public void SingleMemberIntArrEmptyParam(@SingleMemberIntArray({}) int x) {} + public void SingleMemberLongArrEmptyParam(@SingleMemberLongArray({}) int x) {} + public void SingleMemberCharArrEmptyParam(@SingleMemberCharArray({}) int x) {} + public void SingleMemberFloatArrEmptyParam(@SingleMemberFloatArray({}) int x) {} + public void SingleMemberDoubleArrEmptyParam(@SingleMemberDoubleArray({}) int x) {} + public void SingleMemberBooleanArrEmptyParam(@SingleMemberBooleanArray({}) int x) {} + public void SingleMemberStringArrEmptyParam(@SingleMemberStringArray({}) int x) {} + public void SingleMemberClassArrEmptyParam(@SingleMemberClassArray({}) int x) {} + public void SingleMemberEnumArrEmptyParam(@SingleMemberEnumArray({}) int x) {} + + // Single member array (one-element shorthand) + public void SingleMemberByteArrOneParam(@SingleMemberByteArray(1) int x) {} + public void SingleMemberShortArrOneParam(@SingleMemberShortArray(2) int x) {} + public void SingleMemberIntArrOneParam(@SingleMemberIntArray(3) int x) {} + public void SingleMemberLongArrOneParam(@SingleMemberLongArray(4L) int x) {} + public void SingleMemberCharArrOneParam(@SingleMemberCharArray('5') int x) {} + public void SingleMemberFloatArrOneParam(@SingleMemberFloatArray(6.0f) int x) {} + public void SingleMemberDoubleArrOneParam(@SingleMemberDoubleArray(7.0) int x) {} + public void SingleMemberBooleanArrOneParam(@SingleMemberBooleanArray(true) int x) {} + public void SingleMemberStringArrOneParam(@SingleMemberStringArray("custom") int x) {} + public void SingleMemberClassArrOneParam(@SingleMemberClassArray(Map.class) int x) {} + public void SingleMemberEnumArrOneParam(@SingleMemberEnumArray(Stooge.MOE) int x) {} + + // Single member array (two elements) + public void SingleMemberByteArrTwoParam(@SingleMemberByteArray({1, 2}) int x) {} + public void SingleMemberShortArrTwoParam(@SingleMemberShortArray({2, 3}) int x) {} + public void SingleMemberIntArrTwoParam(@SingleMemberIntArray({3, 4}) int x) {} + public void SingleMemberLongArrTwoParam(@SingleMemberLongArray({4L, 5L}) int x) {} + public void SingleMemberCharArrTwoParam(@SingleMemberCharArray({'5', '6'}) int x) {} + public void SingleMemberFloatArrTwoParam(@SingleMemberFloatArray({6.0f, 7.0f}) int x) {} + public void SingleMemberDoubleArrTwoParam(@SingleMemberDoubleArray({7.0, 8.0}) int x) {} + public void SingleMemberBooleanArrTwoParam(@SingleMemberBooleanArray({true, false}) int x){} + public void SingleMemberStringArrTwoParam(@SingleMemberStringArray({"custom", "paint"}) int x) {} + public void SingleMemberClassArrTwoParam(@SingleMemberClassArray({Map.class, Set.class}) int x) {} + public void SingleMemberEnumArrTwoParam(@SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) int x) {} + + // Single member array with default (override) + public void SingleMemberByteArrOvrdDefParam(@SingleMemberByteArrayDef(1) int x) {} + public void SingleMemberShortArrOvrdDefParam(@SingleMemberShortArrayDef(2) int x) {} + public void SingleMemberIntArrOvrdDefParam(@SingleMemberIntArrayDef(3) int x) {} + public void SingleMemberLongArrOvrdDefParam(@SingleMemberLongArrayDef(4L) int x) {} + public void SingleMemberCharArrOvrdDefParam(@SingleMemberCharArrayDef('5') int x) {} + public void SingleMemberFloatArrOvrdDefParam(@SingleMemberFloatArrayDef(6.0f) int x) {} + public void SingleMemberDoubleArrOvrdDefParam(@SingleMemberDoubleArrayDef(7.0) int x) {} + public void SingleMemberBooleanArrOvrdDefParam(@SingleMemberBooleanArrayDef(true) int x){} + public void SingleMemberStringArrOvrdDefParam(@SingleMemberStringArrayDef("custom") int x) {} + public void SingleMemberClassArrOvrdDefParam(@SingleMemberClassArrayDef(Map.class) int x) {} + public void SingleMemberEnumArrOvrdDefParam(@SingleMemberEnumArrayDef(Stooge.MOE) int x) {} + + // Single member array with default - accept + public void SingleMemberByteArrAcceptDefParam(@SingleMemberByteArrayDef int x) {} + public void SingleMemberShortArrAcceptDefParam(@SingleMemberShortArrayDef int x) {} + public void SingleMemberIntArrAcceptDefParam(@SingleMemberIntArrayDef int x) {} + public void SingleMemberLongArrAcceptDefParam(@SingleMemberLongArrayDef int x) {} + public void SingleMemberCharArrAcceptDefParam(@SingleMemberCharArrayDef int x) {} + public void SingleMemberFloatArrAcceptDefParam(@SingleMemberFloatArrayDef int x) {} + public void SingleMemberDoubleArrAcceptDefParam(@SingleMemberDoubleArrayDef int x) {} + public void SingleMemberBooleanArrAcceptDefParam(@SingleMemberBooleanArrayDef int x){} + public void SingleMemberStringArrAcceptDefParam(@SingleMemberStringArrayDef int x) {} + public void SingleMemberClassArrAcceptDefParam(@SingleMemberClassArrayDef int x) {} + public void SingleMemberEnumArrAcceptDefParam(@SingleMemberEnumArrayDef int x) {} +} + +// Helper types + +enum Stooge { LARRY, MOE, CURLY } + +@Target({}) @interface Point { int x(); int y(); } + +// ANNOTATION TYPES + +@Retention(RUNTIME) @interface ScalarTypes { + byte b(); + short s(); + int i(); + long l(); + char c(); + float f(); + double d(); + boolean bool(); + String str(); + Class cls(); + Stooge e(); + Point a(); +} + +@Retention(RUNTIME) @interface ScalarTypesWithDefault { + byte b() default 11; + short s() default 12; + int i() default 13; + long l() default 14; + char c() default 'V'; + float f() default 16.0f; + double d() default 17.0; + boolean bool() default false; + String str() default "default"; + Class cls() default Class.class; + Stooge e() default Stooge.LARRY; + Point a() default @Point(x = 11, y = 12); +} + +@Retention(RUNTIME) @interface ArrayTypes { + byte[] b(); + short[] s(); + int[] i(); + long[] l(); + char[] c(); + float[] f(); + double[] d(); + boolean[] bool(); + String[] str(); + Class[] cls(); + Stooge[] e(); + Point[] a(); +} + +@Retention(RUNTIME) @interface ArrayTypesWithDefault { + byte[] b() default { 11 }; + short[] s() default { 12 }; + int[] i() default { 13 }; + long[] l() default { 14L }; + char[] c() default { 'V' }; + float[] f() default { 16.0f }; + double[] d() default { 17.0 }; + boolean[] bool() default { false }; + String[] str() default { "default" }; + Class[] cls() default { Class.class }; + Stooge[] e() default { Stooge.LARRY }; + Point[] a() default { @Point(x = 11, y = 12) }; +} + +@Retention(RUNTIME) @interface Marker { } + +@Retention(RUNTIME) @interface SingleMemberByte { byte value(); } +@Retention(RUNTIME) @interface SingleMemberShort { short value(); } +@Retention(RUNTIME) @interface SingleMemberInt { int value(); } +@Retention(RUNTIME) @interface SingleMemberLong { long value(); } +@Retention(RUNTIME) @interface SingleMemberChar { char value(); } +@Retention(RUNTIME) @interface SingleMemberFloat { float value(); } +@Retention(RUNTIME) @interface SingleMemberDouble { double value(); } +@Retention(RUNTIME) @interface SingleMemberBoolean { boolean value(); } +@Retention(RUNTIME) @interface SingleMemberString { String value(); } +@Retention(RUNTIME) @interface SingleMemberClass { Class value(); } +@Retention(RUNTIME) @interface SingleMemberEnum { Stooge value(); } + +@Retention(RUNTIME) @interface SingleMemberByteWithDef { byte value() default 11; } +@Retention(RUNTIME) @interface SingleMemberShortWithDef { short value() default 12; } +@Retention(RUNTIME) @interface SingleMemberIntWithDef { int value() default 13; } +@Retention(RUNTIME) @interface SingleMemberLongWithDef { long value() default 14; } +@Retention(RUNTIME) @interface SingleMemberCharWithDef { char value() default 'V'; } +@Retention(RUNTIME) @interface SingleMemberFloatWithDef { float value() default 16.0f; } +@Retention(RUNTIME) @interface SingleMemberDoubleWithDef { double value() default 17.0; } +@Retention(RUNTIME) @interface SingleMemberBooleanWithDef { boolean value() default false; } +@Retention(RUNTIME) @interface SingleMemberStringWithDef { String value() default "default"; } +@Retention(RUNTIME) @interface SingleMemberClassWithDef { Class value() default Class.class; } +@Retention(RUNTIME) @interface SingleMemberEnumWithDef { Stooge value() default Stooge.LARRY; } + +@Retention(RUNTIME) @interface SingleMemberByteArray { byte[] value(); } +@Retention(RUNTIME) @interface SingleMemberShortArray { short[] value(); } +@Retention(RUNTIME) @interface SingleMemberIntArray { int[] value(); } +@Retention(RUNTIME) @interface SingleMemberLongArray { long[] value(); } +@Retention(RUNTIME) @interface SingleMemberCharArray { char[] value(); } +@Retention(RUNTIME) @interface SingleMemberFloatArray { float[] value(); } +@Retention(RUNTIME) @interface SingleMemberDoubleArray { double[] value(); } +@Retention(RUNTIME) @interface SingleMemberBooleanArray { boolean[] value(); } +@Retention(RUNTIME) @interface SingleMemberStringArray { String[] value(); } +@Retention(RUNTIME) @interface SingleMemberClassArray { Class[] value(); } +@Retention(RUNTIME) @interface SingleMemberEnumArray { Stooge[] value(); } + +@Retention(RUNTIME) @interface SingleMemberByteArrayDef { byte[] value() default { 11 }; } +@Retention(RUNTIME) @interface SingleMemberShortArrayDef { short[] value() default { 12 }; } +@Retention(RUNTIME) @interface SingleMemberIntArrayDef { int[] value() default { 13 }; } +@Retention(RUNTIME) @interface SingleMemberLongArrayDef { long[] value() default { 14 }; } +@Retention(RUNTIME) @interface SingleMemberCharArrayDef { char[] value() default { 'V' }; } +@Retention(RUNTIME) @interface SingleMemberFloatArrayDef { float[] value() default { 16.0f };} +@Retention(RUNTIME) @interface SingleMemberDoubleArrayDef { double[] value() default { 17.0 }; } +@Retention(RUNTIME) @interface SingleMemberBooleanArrayDef { boolean[] value() default { false };} +@Retention(RUNTIME) @interface SingleMemberStringArrayDef { + String[] value() default {"default"}; +} +@Retention(RUNTIME) @interface SingleMemberClassArrayDef { + Class[] value() default {Class.class}; +} +@Retention(RUNTIME) @interface SingleMemberEnumArrayDef { + Stooge[] value() default {Stooge.LARRY}; +} + +// Annotation types for inheritance and declared-annotations tests +@Inherited @Retention(RUNTIME) @interface Foo { } + @Retention(RUNTIME) @interface Bar { } + + + // ANNOTATED CLASSES + + @ScalarTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + class scalarTypesClass { } + + @ScalarTypesWithDefault ( ) + class scalarTypesAcceptDefaultClass { } + + @ScalarTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE + ) + class scalarTypesOverrideDefaultClass { } + + @ArrayTypes ( + b = { }, + s = { }, + i = { }, + l = { }, + c = { }, + f = { }, + d = { }, + bool = { }, + str = { }, + cls = { }, + e = { }, + a = { } + ) + class emptyArrayTypesClass { } + + @ArrayTypes ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = @Point(x = 1, y = 2) + ) + class singleElementArrayTypesClass { } + + @ArrayTypes ( + b = { 1, 2 }, + s = { 2, 3 }, + i = { 3, 4 }, + l = { 4L, 5L }, + c = { '5', '6' }, + f = { 6.0f, 7.0f }, + d = { 7.0, 8.0 }, + bool = { true, false }, + str = { "custom", "paint" }, + cls = { Map.class, Set.class }, + e = { Stooge.MOE, Stooge.CURLY }, + a = { @Point(x = 1, y = 2), @Point(x = 3, y = 4) } + ) + class twoElementArrayTypesClass { } + + @ArrayTypesWithDefault ( + ) + class arrayTypesAcceptDefaultClass { } + + @ArrayTypesWithDefault ( + b = 1, + s = 2, + i = 3, + l = 4L, + c = '5', + f = 6.0f, + d = 7.0, + bool = true, + str = "custom", + cls = Map.class, + e = Stooge.MOE, + a = { @Point(x = 1, y = 2) } + ) + class arrayTypesOverrideDefaultClass { } + + @Marker class markerClass { } + + // Single-member (shorthand) + @SingleMemberByte(1) class SingleMemberByteClass { } + @SingleMemberShort(2) class SingleMemberShortClass { } + @SingleMemberInt(3) class SingleMemberIntClass { } + @SingleMemberLong(4L) class SingleMemberLongClass { } + @SingleMemberChar('5') class SingleMemberCharClass { } + @SingleMemberFloat(6.0f) class SingleMemberFloatClass { } + @SingleMemberDouble(7.0) class SingleMemberDoubleClass { } + @SingleMemberBoolean(true) class SingleMemberBooleanClass { } + @SingleMemberString("custom") class SingleMemberStringClass { } + @SingleMemberClass(Map.class) class SingleMemberClassClass { } + @SingleMemberEnum(Stooge.MOE) class SingleMemberEnumClass { } + + // Single-member with default (Override) + @SingleMemberByteWithDef(1) class SingleMemberByteOvrdDefClass { } + @SingleMemberShortWithDef(2) class SingleMemberShortOvrdDefClass { } + @SingleMemberIntWithDef(3) class SingleMemberIntOvrdDefClass { } + @SingleMemberLongWithDef(4L) class SingleMemberLongOvrdDefClass { } + @SingleMemberCharWithDef('5') class SingleMemberCharOvrdDefClass { } + @SingleMemberFloatWithDef(6.0f) class SingleMemberFloatOvrdDefClass { } + @SingleMemberDoubleWithDef(7.0) class SingleMemberDoubleOvrdDefClass { } + @SingleMemberBooleanWithDef(true) class SingleMemberBooleanOvrdDefClass { } + @SingleMemberStringWithDef("custom") class SingleMemberStringOvrdDefClass { } + @SingleMemberClassWithDef(Map.class) class SingleMemberClassOvrdDefClass { } + @SingleMemberEnumWithDef(Stooge.MOE) class SingleMemberEnumOvrdDefClass { } + + // Single-member with default (Accept) + @SingleMemberByteWithDef class SingleMemberByteAcceptDefClass { } + @SingleMemberShortWithDef class SingleMemberShortAcceptDefClass { } + @SingleMemberIntWithDef class SingleMemberIntAcceptDefClass { } + @SingleMemberLongWithDef class SingleMemberLongAcceptDefClass { } + @SingleMemberCharWithDef class SingleMemberCharAcceptDefClass { } + @SingleMemberFloatWithDef class SingleMemberFloatAcceptDefClass { } + @SingleMemberDoubleWithDef class SingleMemberDoubleAcceptDefClass { } + @SingleMemberBooleanWithDef class SingleMemberBooleanAcceptDefClass { } + @SingleMemberStringWithDef class SingleMemberStringAcceptDefClass { } + @SingleMemberClassWithDef class SingleMemberClassAcceptDefClass { } + @SingleMemberEnumWithDef class SingleMemberEnumAcceptDefClass { } + + // Single member array (empty array) + @SingleMemberByteArray({}) class SingleMemberByteArrEmptyClass { } + @SingleMemberShortArray({}) class SingleMemberShortArrEmptyClass { } + @SingleMemberIntArray({}) class SingleMemberIntArrEmptyClass { } + @SingleMemberLongArray({}) class SingleMemberLongArrEmptyClass { } + @SingleMemberCharArray({}) class SingleMemberCharArrEmptyClass { } + @SingleMemberFloatArray({}) class SingleMemberFloatArrEmptyClass { } + @SingleMemberDoubleArray({}) class SingleMemberDoubleArrEmptyClass { } + @SingleMemberBooleanArray({})class SingleMemberBooleanArrEmptyClass { } + @SingleMemberStringArray({}) class SingleMemberStringArrEmptyClass { } + @SingleMemberClassArray({}) class SingleMemberClassArrEmptyClass { } + @SingleMemberEnumArray({}) class SingleMemberEnumArrEmptyClass { } + + // Single member array (one-element shorthand) + @SingleMemberByteArray(1) class SingleMemberByteArrOneClass { } + @SingleMemberShortArray(2) class SingleMemberShortArrOneClass { } + @SingleMemberIntArray(3) class SingleMemberIntArrOneClass { } + @SingleMemberLongArray(4L) class SingleMemberLongArrOneClass { } + @SingleMemberCharArray('5') class SingleMemberCharArrOneClass { } + @SingleMemberFloatArray(6.0f) class SingleMemberFloatArrOneClass { } + @SingleMemberDoubleArray(7.0) class SingleMemberDoubleArrOneClass { } + @SingleMemberBooleanArray(true) class SingleMemberBooleanArrOneClass { } + @SingleMemberStringArray("custom") class SingleMemberStringArrOneClass { } + @SingleMemberClassArray(Map.class) class SingleMemberClassArrOneClass { } + @SingleMemberEnumArray(Stooge.MOE) class SingleMemberEnumArrOneClass { } + + // Single member array (two elements) + @SingleMemberByteArray({1, 2}) class SingleMemberByteArrTwoClass { } + @SingleMemberShortArray({2, 3}) class SingleMemberShortArrTwoClass { } + @SingleMemberIntArray({3, 4}) class SingleMemberIntArrTwoClass { } + @SingleMemberLongArray({4L, 5L}) class SingleMemberLongArrTwoClass { } + @SingleMemberCharArray({'5', '6'}) class SingleMemberCharArrTwoClass { } + @SingleMemberFloatArray({6.0f, 7.0f}) class SingleMemberFloatArrTwoClass { } + @SingleMemberDoubleArray({7.0, 8.0}) class SingleMemberDoubleArrTwoClass { } + @SingleMemberBooleanArray({true,false}) class SingleMemberBooleanArrTwoClass { } + @SingleMemberStringArray({"custom", "paint"}) class SingleMemberStringArrTwoClass { } + @SingleMemberClassArray({Map.class, Set.class}) class SingleMemberClassArrTwoClass { } + @SingleMemberEnumArray({Stooge.MOE, Stooge.CURLY}) class SingleMemberEnumArrTwoClass { } + + // Single member array with default (override) + @SingleMemberByteArrayDef(1) class SingleMemberByteArrOvrdDefClass { } + @SingleMemberShortArrayDef(2) class SingleMemberShortArrOvrdDefClass { } + @SingleMemberIntArrayDef(3) class SingleMemberIntArrOvrdDefClass { } + @SingleMemberLongArrayDef(4L) class SingleMemberLongArrOvrdDefClass { } + @SingleMemberCharArrayDef('5') class SingleMemberCharArrOvrdDefClass { } + @SingleMemberFloatArrayDef(6.0f) class SingleMemberFloatArrOvrdDefClass { } + @SingleMemberDoubleArrayDef(7.0) class SingleMemberDoubleArrOvrdDefClass { } + @SingleMemberBooleanArrayDef(true) class SingleMemberBooleanArrOvrdDefClass { } + @SingleMemberStringArrayDef("custom") class SingleMemberStringArrOvrdDefClass { } + @SingleMemberClassArrayDef(Map.class) class SingleMemberClassArrOvrdDefClass { } + @SingleMemberEnumArrayDef(Stooge.MOE) class SingleMemberEnumArrOvrdDefClass { } + + // Single member array with default - accept + @SingleMemberByteArrayDef class SingleMemberByteArrAcceptDefClass { } + @SingleMemberShortArrayDef class SingleMemberShortArrAcceptDefClass { } + @SingleMemberIntArrayDef class SingleMemberIntArrAcceptDefClass { } + @SingleMemberLongArrayDef class SingleMemberLongArrAcceptDefClass { } + @SingleMemberCharArrayDef class SingleMemberCharArrAcceptDefClass { } + @SingleMemberFloatArrayDef class SingleMemberFloatArrAcceptDefClass { } + @SingleMemberDoubleArrayDef class SingleMemberDoubleArrAcceptDefClass { } + @SingleMemberBooleanArrayDef class SingleMemberBooleanArrAcceptDefClass { } + @SingleMemberStringArrayDef class SingleMemberStringArrAcceptDefClass { } + @SingleMemberClassArrayDef class SingleMemberClassArrAcceptDefClass { } + @SingleMemberEnumArrayDef class SingleMemberEnumArrAcceptDefClass { } + + // Annotated classes for inheritance and declared-annotations tests + @Foo @Bar class Grandpa { } + class Dad extends Grandpa { } + @Bar class Son extends Dad { } diff --git a/jdk/test/java/lang/annotation/loaderLeak/A.java b/jdk/test/java/lang/annotation/loaderLeak/A.java new file mode 100644 index 00000000000..0836eb4507c --- /dev/null +++ b/jdk/test/java/lang/annotation/loaderLeak/A.java @@ -0,0 +1,28 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +public +@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +@interface A { + B b(); +} diff --git a/jdk/test/java/lang/annotation/loaderLeak/B.java b/jdk/test/java/lang/annotation/loaderLeak/B.java new file mode 100644 index 00000000000..f22a6707936 --- /dev/null +++ b/jdk/test/java/lang/annotation/loaderLeak/B.java @@ -0,0 +1,24 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +public @interface B {} diff --git a/jdk/test/java/lang/annotation/loaderLeak/C.java b/jdk/test/java/lang/annotation/loaderLeak/C.java new file mode 100644 index 00000000000..be5347670e6 --- /dev/null +++ b/jdk/test/java/lang/annotation/loaderLeak/C.java @@ -0,0 +1,24 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +public @A(b=@B()) class C {} diff --git a/jdk/test/java/lang/annotation/loaderLeak/LoaderLeak.sh b/jdk/test/java/lang/annotation/loaderLeak/LoaderLeak.sh new file mode 100644 index 00000000000..d8a47462f9b --- /dev/null +++ b/jdk/test/java/lang/annotation/loaderLeak/LoaderLeak.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTSRC=${TESTSRC}" +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTJAVA=${TESTJAVA}" +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi +echo "TESTCLASSES=${TESTCLASSES}" +echo "CLASSPATH=${CLASSPATH}" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + NULL=/dev/null + PS=":" + FS="/" + ;; + Windows* ) + NULL=NUL + PS=";" + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +mkdir -p classes +cp ${TESTSRC}${FS}*.java . +${TESTJAVA}${FS}bin${FS}javac -d classes A.java B.java C.java +${TESTJAVA}${FS}bin${FS}javac Main.java +${TESTJAVA}${FS}bin${FS}java Main +result=$? +if [ $result -eq 0 ] +then + echo "Passed 1 of 2" +else + echo "Failed 1 of 2" + exit $result +fi +${TESTJAVA}${FS}bin${FS}java Main foo +result=$? +if [ $result -eq 0 ] +then + echo "Passed 2 of 2" +else + echo "Failed 2 of 2" +fi +exit $result diff --git a/jdk/test/java/lang/annotation/loaderLeak/Main.java b/jdk/test/java/lang/annotation/loaderLeak/Main.java new file mode 100644 index 00000000000..b27616b0c08 --- /dev/null +++ b/jdk/test/java/lang/annotation/loaderLeak/Main.java @@ -0,0 +1,127 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 5040740 + * @summary annotations cause memory leak + * @author gafter + * + * @run shell LoaderLeak.sh + */ + +import java.net.*; +import java.lang.ref.*; +import java.util.*; +import java.io.*; + +public class Main { + public static void main(String[] args) throws Exception { + for (int i=0; i<100; i++) + doTest(args.length != 0); + } + + static void doTest(boolean readAnn) throws Exception { + // URL classes = new URL("file://" + System.getProperty("user.dir") + "/classes"); + // URL[] path = { classes }; + // URLClassLoader loader = new URLClassLoader(path); + ClassLoader loader = new SimpleClassLoader(); + WeakReference> c = new WeakReference(loader.loadClass("C")); + if (c.get() == null) throw new AssertionError(); + if (c.get().getClassLoader() != loader) throw new AssertionError(); + if (readAnn) System.out.println(c.get().getAnnotations()[0]); + if (c.get() == null) throw new AssertionError(); + System.gc(); + System.gc(); + if (c.get() == null) throw new AssertionError(); + System.gc(); + System.gc(); + loader = null; + System.gc(); + System.gc(); + if (c.get() != null) throw new AssertionError(); + } +} + +class SimpleClassLoader extends ClassLoader { + private Hashtable classes = new Hashtable(); + + public SimpleClassLoader() { + } + private byte getClassImplFromDataBase(String className)[] { + byte result[]; + try { + FileInputStream fi = new FileInputStream("classes/"+className+".class"); + result = new byte[fi.available()]; + fi.read(result); + return result; + } catch (Exception e) { + + /* + * If we caught an exception, either the class wasnt found or it + * was unreadable by our process. + */ + return null; + } + } + public Class loadClass(String className) throws ClassNotFoundException { + return (loadClass(className, true)); + } + public synchronized Class loadClass(String className, boolean resolveIt) + throws ClassNotFoundException { + Class result; + byte classData[]; + + /* Check our local cache of classes */ + result = (Class)classes.get(className); + if (result != null) { + return result; + } + + /* Check with the primordial class loader */ + try { + result = super.findSystemClass(className); + return result; + } catch (ClassNotFoundException e) { + } + + /* Try to load it from our repository */ + classData = getClassImplFromDataBase(className); + if (classData == null) { + throw new ClassNotFoundException(); + } + + /* Define it (parse the class file) */ + result = defineClass(classData, 0, classData.length); + if (result == null) { + throw new ClassFormatError(); + } + + if (resolveIt) { + resolveClass(result); + } + + classes.put(className, result); + return result; + } +} diff --git a/jdk/test/java/lang/annotation/package-info.java b/jdk/test/java/lang/annotation/package-info.java new file mode 100644 index 00000000000..78afb3f6c0a --- /dev/null +++ b/jdk/test/java/lang/annotation/package-info.java @@ -0,0 +1,37 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4901290 5037531 + * @summary Package annotations + * @author gafter + * + * @compile -source 1.5 package-info.java PackageMain.java + * @run main PackageMain + */ + +@java.lang.annotation.Documented +package foo.bar; + +class Baz {} diff --git a/jdk/test/java/lang/reflect/Generics/Probe.java b/jdk/test/java/lang/reflect/Generics/Probe.java index 79628a30bf6..30d6f21e5a3 100644 --- a/jdk/test/java/lang/reflect/Generics/Probe.java +++ b/jdk/test/java/lang/reflect/Generics/Probe.java @@ -23,7 +23,7 @@ /* * @test - * @bug 5003916 + * @bug 5003916 6704655 * @summary Testing parsing of signatures attributes of nested classes * @author Joseph D. Darcy * @compile -source 1.5 Probe.java @@ -32,8 +32,10 @@ import java.lang.reflect.*; import java.lang.annotation.*; +import java.util.*; +import static java.util.Arrays.*; -@Classes({ +@Classes(value={ "java.util.concurrent.FutureTask", "java.util.concurrent.ConcurrentHashMap$EntryIterator", "java.util.concurrent.ConcurrentHashMap$KeyIterator", @@ -56,7 +58,9 @@ import java.lang.annotation.*; "java.util.HashMap$ValueIterator", "java.util.LinkedHashMap$EntryIterator", "java.util.LinkedHashMap$KeyIterator", - "java.util.LinkedHashMap$ValueIterator", + "java.util.LinkedHashMap$ValueIterator" + }, + sunClasses={ "javax.crypto.SunJCE_c", "javax.crypto.SunJCE_e", "javax.crypto.SunJCE_f", @@ -66,7 +70,15 @@ import java.lang.annotation.*; }) public class Probe { public static void main (String[] args) throws Throwable { - String [] names = (Probe.class).getAnnotation(Classes.class).value(); + Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class); + List names = + new ArrayList(asList(classesAnnotation.value())); + + if (System.getProperty("java.runtime.name").startsWith("Java(TM)")) { + // Sun production JDK; test crypto classes too + for(String name: classesAnnotation.sunClasses()) + names.add(name); + } int errs = 0; for(String name: names) { @@ -140,4 +152,5 @@ public class Probe { @Retention(RetentionPolicy.RUNTIME) @interface Classes { String [] value(); // list of classes to probe + String [] sunClasses(); // list of Sun-production JDK specific classes to probe } diff --git a/jdk/test/java/math/BigDecimal/AddTests.java b/jdk/test/java/math/BigDecimal/AddTests.java new file mode 100644 index 00000000000..828a7064f1b --- /dev/null +++ b/jdk/test/java/math/BigDecimal/AddTests.java @@ -0,0 +1,280 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6362557 + * @summary Some tests of add(BigDecimal, mc) + * @author Joseph D. Darcy + */ + +import java.math.*; +import static java.math.BigDecimal.*; +import java.util.Set; +import java.util.EnumSet; + +public class AddTests { + + private static Set nonExactRoundingModes = + EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY)); + + /** + * Test for extreme value of scale and rounding precision that + * could cause integer overflow in right-shift-into-sticky-bit + * computations. + */ + private static int extremaTests() { + int failures = 0; + + failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE), + valueOf(2, Integer.MAX_VALUE), null); + failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE), + valueOf(-2, Integer.MAX_VALUE), null); + return failures; + } + + /** + * Print sum of b1 and b2; correct result will not throw an + * exception. + */ + private static int addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) { + if (mc == null) + mc = new MathContext(2, RoundingMode.DOWN); + + try { + BigDecimal sum = b1.add(b2, mc); + printAddition(b1, b2, sum.toString()); + return 0; + } catch(ArithmeticException ae) { + printAddition(b1, b2, "Exception!"); + return 1; + } + } + + /** + * Test combinations of operands that may meet the condensation + * criteria when rounded to different precisions. + */ + private static int roundingGradationTests() { + int failures = 0; + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e97")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e96")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e95")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e94")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e93")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal( "1234e92")); + + failures += roundAway(new BigDecimal("1234e100"), + new BigDecimal("1234e50")); + + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e97")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e96")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e95")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e94")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e93")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal( "1234e92")); + + failures += roundAway(new BigDecimal("1000e100"), + new BigDecimal("1234e50")); + + + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e97")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e96")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e95")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e94")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e93")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal( "1234e92")); + + failures += roundAway(new BigDecimal("1999e100"), + new BigDecimal("1234e50")); + + + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e97")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e96")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e95")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e94")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e93")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal( "1234e92")); + + failures += roundAway(new BigDecimal("9999e100"), + new BigDecimal("1234e50")); + + return failures; + } + + private static void printAddition(BigDecimal b1, BigDecimal b2, String s) { + System.out.println("" + b1+ "\t+\t" + b2 + "\t=\t" + s); + } + + private static int roundAway(BigDecimal b1, BigDecimal b2) { + int failures = 0; + + b1.precision(); + b2.precision(); + + BigDecimal b1_negate = b1.negate(); + BigDecimal b2_negate = b2.negate(); + + b1_negate.precision(); + b2_negate.precision(); + + failures += roundAway1(b1, b2); + failures += roundAway1(b1, b2_negate); + failures += roundAway1(b1_negate, b2); + failures += roundAway1(b1_negate, b2_negate); + + return failures; + } + + private static int roundAway1(BigDecimal b1, BigDecimal b2) { + int failures = 0; + failures += roundAway0(b1, b2); + failures += roundAway0(b2, b1); + return failures; + } + + /** + * Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety + * of MathContexts. + */ + private static int roundAway0(BigDecimal b1, BigDecimal b2) { + int failures = 0; + BigDecimal exactSum = b1.add(b2); + + for(int precision = 1 ; precision < exactSum.precision()+2; precision++) { + for(RoundingMode rm : nonExactRoundingModes) { + MathContext mc = new MathContext(precision, rm); + BigDecimal roundedExactSum = exactSum.round(mc); + + try { + BigDecimal sum = b1.add(b2, mc); + + if (!roundedExactSum.equals(sum) ) { + failures++; + System.out.println("Exact sum " + exactSum + + "\trounded by " + mc + + "\texpected: " + roundedExactSum + " got: "); + printAddition(b1, b2, sum.toString()); + } +// else { +// System.out.print(mc + "\t"); +// printAddition(b1, b2, sum.toString()); +// } + + } catch (ArithmeticException ae) { + printAddition(b1, b2, "Exception!"); + failures++; + } + } + } + + return failures; + } + + /** + * Verify calling the precision method should not change the + * computed result. + */ + private static int precisionConsistencyTest() { + int failures = 0; + MathContext mc = new MathContext(1,RoundingMode.DOWN); + BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990 + + BigDecimal sum1 = a.add(BigDecimal.ONE, mc); + a.precision(); + BigDecimal sum2 = a.add(BigDecimal.ONE, mc); + + if (!sum1.equals(sum2)) { + failures ++; + System.out.println("Unequal sums after calling precision!"); + System.out.print("Before:\t"); + printAddition(a, BigDecimal.ONE, sum1.toString()); + + System.out.print("After:\t"); + printAddition(a, BigDecimal.ONE, sum2.toString()); + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += extremaTests(); + failures += roundingGradationTests(); + failures += precisionConsistencyTest(); + + if (failures > 0) { + throw new RuntimeException("Incurred " + failures + + " failures while testing rounding add."); + } + } +} diff --git a/jdk/test/java/math/BigDecimal/CompareToTests.java b/jdk/test/java/math/BigDecimal/CompareToTests.java new file mode 100644 index 00000000000..a33da953a8e --- /dev/null +++ b/jdk/test/java/math/BigDecimal/CompareToTests.java @@ -0,0 +1,101 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6473768 + * @summary Tests of BigDecimal.compareTo + * @author Joseph D. Darcy + */ +import java.math.*; +import static java.math.BigDecimal.*; + +public class CompareToTests { + private static int compareToTests() { + int failures = 0; + + final BigDecimal MINUS_ONE = BigDecimal.ONE.negate(); + + // First operand, second operand, expected compareTo result + BigDecimal [][] testCases = { + // Basics + {valueOf(0), valueOf(0), ZERO}, + {valueOf(0), valueOf(1), MINUS_ONE}, + {valueOf(1), valueOf(2), MINUS_ONE}, + {valueOf(2), valueOf(1), ONE}, + {valueOf(10), valueOf(10), ZERO}, + + // Significands would compare differently than scaled value + {valueOf(2,1), valueOf(2), MINUS_ONE}, + {valueOf(2,-1), valueOf(2), ONE}, + {valueOf(1,1), valueOf(2), MINUS_ONE}, + {valueOf(1,-1), valueOf(2), ONE}, + {valueOf(5,-1), valueOf(2), ONE}, + + // Boundary and near boundary values + {valueOf(Long.MAX_VALUE), valueOf(Long.MAX_VALUE), ZERO}, + {valueOf(Long.MAX_VALUE-1), valueOf(Long.MAX_VALUE), MINUS_ONE}, + {valueOf(Long.MIN_VALUE), valueOf(Long.MAX_VALUE), MINUS_ONE}, + {valueOf(Long.MIN_VALUE+1), valueOf(Long.MAX_VALUE), MINUS_ONE}, + {valueOf(Long.MIN_VALUE), valueOf(Long.MIN_VALUE), ZERO}, + {valueOf(Long.MIN_VALUE+1), valueOf(Long.MAX_VALUE), ONE}, + }; + + for (BigDecimal[] testCase : testCases) { + BigDecimal a = testCase[0]; + BigDecimal a_negate = a.negate(); + BigDecimal b = testCase[1]; + BigDecimal b_negate = b.negate(); + int expected = testCase[2].intValue(); + + failures += compareToTest(a, b, expected); + failures += compareToTest(a_negate, b, -1); + failures += compareToTest(a, b_negate, 1); + failures += compareToTest(a_negate, b_negate, -expected); + } + + + return failures; + } + + private static int compareToTest(BigDecimal a, BigDecimal b, int expected) { + int result = a.compareTo(b); + int failed = (result==expected) ? 0 : 1; + if (result == 1) { + System.err.println("(" + a + ").compareTo(" + b + ") => " + result + + "\n\tExpected " + expected); + } + return result; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += compareToTests(); + + if (failures > 0) { + throw new RuntimeException("Incurred " + failures + + " failures while testing exact compareTo."); + } + } +} diff --git a/jdk/test/java/math/BigDecimal/Constructor.java b/jdk/test/java/math/BigDecimal/Constructor.java new file mode 100644 index 00000000000..f93c5849f43 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/Constructor.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4259453 + * @summary Test string constructor of BigDecimal + */ +import java.math.BigDecimal; + +public class Constructor { + public static void main(String[] args) throws Exception { + boolean nfe = false; + try { + BigDecimal bd = new BigDecimal("1.2e"); + } catch (NumberFormatException e) { + nfe = true; + } + if (!nfe) + throw new Exception("Didn't throw NumberFormatException"); + } +} diff --git a/jdk/test/java/math/BigDecimal/DivideTests.java b/jdk/test/java/math/BigDecimal/DivideTests.java new file mode 100644 index 00000000000..e988ca554d6 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/DivideTests.java @@ -0,0 +1,340 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851776 4907265 6177836 + * @summary Some tests for the divide methods. + * @author Joseph D. Darcy + * @compile -source 1.5 DivideTests.java + * @run main DivideTests + */ + +import java.math.*; +import static java.math.BigDecimal.*; + +public class DivideTests { + + // Preliminary exact divide method; could be used for comparison + // purposes. + BigDecimal anotherDivide(BigDecimal dividend, BigDecimal divisor) { + /* + * Handle zero cases first. + */ + if (divisor.signum() == 0) { // x/0 + if (dividend.signum() == 0) // 0/0 + throw new ArithmeticException("Division undefined"); // NaN + throw new ArithmeticException("Division by zero"); + } + if (dividend.signum() == 0) // 0/y + return BigDecimal.ZERO; + else { + /* + * Determine if there is a result with a terminating + * decimal expansion. Putting aside overflow and + * underflow considerations, the existance of an exact + * result only depends on the ratio of the intVal's of the + * dividend (i.e. this) and and divisor since the scales + * of the argument just affect where the decimal point + * lies. + * + * For the ratio of (a = this.intVal) and (b = + * divisor.intVal) to have a finite decimal expansion, + * once a/b is put in lowest terms, b must be equal to + * (2^i)*(5^j) for some integer i,j >= 0. Therefore, we + * first compute to see if b_prime =(b/gcd(a,b)) is equal + * to (2^i)*(5^j). + */ + BigInteger TWO = BigInteger.valueOf(2); + BigInteger FIVE = BigInteger.valueOf(5); + BigInteger TEN = BigInteger.valueOf(10); + + BigInteger divisorIntvalue = divisor.scaleByPowerOfTen(divisor.scale()).toBigInteger().abs(); + BigInteger dividendIntvalue = dividend.scaleByPowerOfTen(dividend.scale()).toBigInteger().abs(); + + BigInteger b_prime = divisorIntvalue.divide(dividendIntvalue.gcd(divisorIntvalue)); + + boolean goodDivisor = false; + int i=0, j=0; + + badDivisor: { + while(! b_prime.equals(BigInteger.ONE) ) { + int b_primeModTen = b_prime.mod(TEN).intValue() ; + + switch(b_primeModTen) { + case 0: + // b_prime divisible by 10=2*5, increment i and j + i++; + j++; + b_prime = b_prime.divide(TEN); + break; + + case 5: + // b_prime divisible by 5, increment j + j++; + b_prime = b_prime.divide(FIVE); + break; + + case 2: + case 4: + case 6: + case 8: + // b_prime divisible by 2, increment i + i++; + b_prime = b_prime.divide(TWO); + break; + + default: // hit something we shouldn't have + b_prime = BigInteger.ONE; // terminate loop + break badDivisor; + } + } + + goodDivisor = true; + } + + if( ! goodDivisor ) { + throw new ArithmeticException("Non terminating decimal expansion"); + } + else { + // What is a rule for determining how many digits are + // needed? Once that is determined, cons up a new + // MathContext object and pass it on to the divide(bd, + // mc) method; precision == ?, roundingMode is unnecessary. + + // Are we sure this is the right scale to use? Should + // also determine a precision-based method. + MathContext mc = new MathContext(dividend.precision() + + (int)Math.ceil( + 10.0*divisor.precision()/3.0), + RoundingMode.UNNECESSARY); + // Should do some more work here to rescale, etc. + return dividend.divide(divisor, mc); + } + } + } + + public static int powersOf2and5() { + int failures = 0; + + for(int i = 0; i < 6; i++) { + int powerOf2 = (int)StrictMath.pow(2.0, i); + + for(int j = 0; j < 6; j++) { + int powerOf5 = (int)StrictMath.pow(5.0, j); + int product; + + BigDecimal bd; + + try { + bd = BigDecimal.ONE.divide(new BigDecimal(product=powerOf2*powerOf5)); + } catch (ArithmeticException e) { + failures++; + System.err.println((new BigDecimal(powerOf2)).toString() + " / " + + (new BigDecimal(powerOf5)).toString() + " threw an exception."); + e.printStackTrace(); + } + + try { + bd = new BigDecimal(powerOf2).divide(new BigDecimal(powerOf5)); + } catch (ArithmeticException e) { + failures++; + System.err.println((new BigDecimal(powerOf2)).toString() + " / " + + (new BigDecimal(powerOf5)).toString() + " threw an exception."); + e.printStackTrace(); + } + + try { + bd = new BigDecimal(powerOf5).divide(new BigDecimal(powerOf2)); + } catch (ArithmeticException e) { + failures++; + System.err.println((new BigDecimal(powerOf5)).toString() + " / " + + (new BigDecimal(powerOf2)).toString() + " threw an exception."); + + e.printStackTrace(); + } + + } + } + return failures; + } + + public static int nonTerminating() { + int failures = 0; + int[] primes = {1, 3, 7, 13, 17}; + + // For each pair of prime products, verify the ratio of + // non-equal products has a non-terminating expansion. + + for(int i = 0; i < primes.length; i++) { + for(int j = i+1; j < primes.length; j++) { + + for(int m = 0; m < primes.length; m++) { + for(int n = m+1; n < primes.length; n++) { + int dividend = primes[i] * primes[j]; + int divisor = primes[m] * primes[n]; + + if ( ((dividend/divisor) * divisor) != dividend ) { + try { + BigDecimal quotient = (new BigDecimal(dividend). + divide(new BigDecimal(divisor))); + failures++; + System.err.println("Exact quotient " + quotient.toString() + + " returned for non-terminating fraction " + + dividend + " / " + divisor + "."); + } + catch (ArithmeticException e) { + ; // Correct result + } + } + + } + } + } + } + + return failures; + } + + public static int properScaleTests(){ + int failures = 0; + + BigDecimal[][] testCases = { + {new BigDecimal("1"), new BigDecimal("5"), new BigDecimal("2e-1")}, + {new BigDecimal("1"), new BigDecimal("50e-1"), new BigDecimal("2e-1")}, + {new BigDecimal("10e-1"), new BigDecimal("5"), new BigDecimal("2e-1")}, + {new BigDecimal("1"), new BigDecimal("500e-2"), new BigDecimal("2e-1")}, + {new BigDecimal("100e-2"), new BigDecimal("5"), new BigDecimal("20e-2")}, + {new BigDecimal("1"), new BigDecimal("32"), new BigDecimal("3125e-5")}, + {new BigDecimal("1"), new BigDecimal("64"), new BigDecimal("15625e-6")}, + {new BigDecimal("1.0000000"), new BigDecimal("64"), new BigDecimal("156250e-7")}, + }; + + + for(BigDecimal[] tc : testCases) { + BigDecimal quotient; + if (! (quotient = tc[0].divide(tc[1])).equals(tc[2]) ) { + failures++; + System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] + + "; expected " + tc[2] + " got " + quotient); + } + } + + return failures; + } + + public static int trailingZeroTests() { + int failures = 0; + + MathContext mc = new MathContext(3, RoundingMode.FLOOR); + BigDecimal[][] testCases = { + {new BigDecimal("19"), new BigDecimal("100"), new BigDecimal("0.19")}, + {new BigDecimal("21"), new BigDecimal("110"), new BigDecimal("0.190")}, + }; + + for(BigDecimal[] tc : testCases) { + BigDecimal quotient; + if (! (quotient = tc[0].divide(tc[1], mc)).equals(tc[2]) ) { + failures++; + System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] + + "; expected " + tc[2] + " got " + quotient); + } + } + + return failures; + } + + public static int scaledRoundedDivideTests() { + int failures = 0; + // Tests of the traditional scaled divide under different + // rounding modes. + + // Encode rounding mode and scale for the divide in a + // BigDecimal with the significand equal to the rounding mode + // and the scale equal to the number's scale. + + // {dividend, dividisor, rounding, quotient} + BigDecimal a = new BigDecimal("31415"); + BigDecimal a_minus = a.negate(); + BigDecimal b = new BigDecimal("10000"); + + BigDecimal c = new BigDecimal("31425"); + BigDecimal c_minus = c.negate(); + + BigDecimal[][] testCases = { + {a, b, BigDecimal.valueOf(ROUND_UP, 3), new BigDecimal("3.142")}, + {a_minus, b, BigDecimal.valueOf(ROUND_UP, 3), new BigDecimal("-3.142")}, + + {a, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("3.141")}, + {a_minus, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("-3.141")}, + + {a, b, BigDecimal.valueOf(ROUND_CEILING, 3), new BigDecimal("3.142")}, + {a_minus, b, BigDecimal.valueOf(ROUND_CEILING, 3), new BigDecimal("-3.141")}, + + {a, b, BigDecimal.valueOf(ROUND_FLOOR, 3), new BigDecimal("3.141")}, + {a_minus, b, BigDecimal.valueOf(ROUND_FLOOR, 3), new BigDecimal("-3.142")}, + + {a, b, BigDecimal.valueOf(ROUND_HALF_UP, 3), new BigDecimal("3.142")}, + {a_minus, b, BigDecimal.valueOf(ROUND_HALF_UP, 3), new BigDecimal("-3.142")}, + + {a, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("3.141")}, + {a_minus, b, BigDecimal.valueOf(ROUND_DOWN, 3), new BigDecimal("-3.141")}, + + {a, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")}, + {a_minus, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")}, + + {c, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")}, + {c_minus, b, BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")}, + }; + + for(BigDecimal tc[] : testCases) { + int scale = tc[2].scale(); + int rm = tc[2].unscaledValue().intValue(); + + BigDecimal quotient = tc[0].divide(tc[1], scale, rm); + if (!quotient.equals(tc[3])) { + failures++; + System.err.println("Unexpected quotient from " + tc[0] + " / " + tc[1] + + " scale " + scale + " rounding mode " + RoundingMode.valueOf(rm) + + "; expected " + tc[3] + " got " + quotient); + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += powersOf2and5(); + failures += nonTerminating(); + failures += properScaleTests(); + failures += trailingZeroTests(); + failures += scaledRoundedDivideTests(); + + if (failures > 0) { + throw new RuntimeException("Incurred " + failures + + " failures while testing exact divide."); + } + } +} diff --git a/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java b/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java new file mode 100644 index 00000000000..a75850da20c --- /dev/null +++ b/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java @@ -0,0 +1,164 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6274390 + * @summary Verify {float, double}Value methods work with condensed representation + */ +import java.math.*; + +public class FloatDoubleValueTests { + private static final long two2the24 = 1L<<23; + private static final long two2the53 = 1L<<52; + + // Largest long that fits exactly in a float + private static final long maxFltLong = (long)(Integer.MAX_VALUE & ~(0xff)); + + // Largest long that fits exactly in a double + private static final long maxDblLong = Long.MAX_VALUE & ~(0x7ffL); + + static void testDoubleValue0(long i, BigDecimal bd) { + if (bd.doubleValue() != i || + bd.longValue() != i) + throw new RuntimeException("Unexpected equality failure for " + + i + "\t" + bd); + } + + static void testFloatValue0(long i, BigDecimal bd) { + if (bd.floatValue() != i || + bd.longValue() != i) + throw new RuntimeException("Unexpected equality failure for " + + i + "\t" + bd); + } + + static void checkFloat(BigDecimal bd, float f) { + float fbd = bd.floatValue(); + if (f != fbd ) { + String message = String.format("Bad conversion:"+ + "got %g (%a)\texpected %g (%a)", + f, f, fbd, fbd); + throw new RuntimeException(message); + } + } + + static void checkDouble(BigDecimal bd, double d) { + double dbd = bd.doubleValue(); + if (d != dbd ) { + String message = String.format("Bad conversion:"+ + "got %g (%a)\texpected %g (%a)", + d, d, dbd, dbd); + throw new RuntimeException(message); + } + } + + // Test integral values that will convert exactly to both float + // and double. + static void testFloatDoubleValue() { + long longValues[] = { + 0, + 1, + 2, + + two2the24-1, + two2the24, + two2the24+1, + + maxFltLong-1, + maxFltLong, + maxFltLong+1, + }; + + for(long i : longValues) { + BigDecimal bd1 = new BigDecimal(i); + BigDecimal bd2 = new BigDecimal(-i); + + testDoubleValue0( i, bd1); + testDoubleValue0(-i, bd2); + + testFloatValue0( i, bd1); + testFloatValue0(-i, bd2); + } + + } + + static void testDoubleValue() { + long longValues[] = { + Integer.MAX_VALUE-1, + Integer.MAX_VALUE, + (long)Integer.MAX_VALUE+1, + + two2the53-1, + two2the53, + two2the53+1, + + maxDblLong, + }; + + // Test integral values that will convert exactly to double + // but not float. + for(long i : longValues) { + BigDecimal bd1 = new BigDecimal(i); + BigDecimal bd2 = new BigDecimal(-i); + + testDoubleValue0( i, bd1); + testDoubleValue0(-i, bd2); + + checkFloat(bd1, (float)i); + checkFloat(bd2, -(float)i); + } + + // Now check values that should not convert the same in double + for(long i = maxDblLong; i < Long.MAX_VALUE; i++) { + BigDecimal bd1 = new BigDecimal(i); + BigDecimal bd2 = new BigDecimal(-i); + checkDouble(bd1, (double)i); + checkDouble(bd2, -(double)i); + + checkFloat(bd1, (float)i); + checkFloat(bd2, -(float)i); + } + + checkDouble(new BigDecimal(Long.MIN_VALUE), (double)Long.MIN_VALUE); + checkDouble(new BigDecimal(Long.MAX_VALUE), (double)Long.MAX_VALUE); + } + + static void testFloatValue() { + // Now check values that should not convert the same in float + for(long i = maxFltLong; i <= Integer.MAX_VALUE; i++) { + BigDecimal bd1 = new BigDecimal(i); + BigDecimal bd2 = new BigDecimal(-i); + checkFloat(bd1, (float)i); + checkFloat(bd2, -(float)i); + + testDoubleValue0( i, bd1); + testDoubleValue0(-i, bd2); + } + } + + public static void main(String[] args) throws Exception { + testFloatDoubleValue(); + testDoubleValue(); + testFloatValue(); + } +} diff --git a/jdk/test/java/math/BigDecimal/IntegralDivisionTests.java b/jdk/test/java/math/BigDecimal/IntegralDivisionTests.java new file mode 100644 index 00000000000..100eca40cce --- /dev/null +++ b/jdk/test/java/math/BigDecimal/IntegralDivisionTests.java @@ -0,0 +1,352 @@ +/* + * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 4904082 4917089 6337226 + * @summary Tests that integral division and related methods return the proper result and scale. + * @author Joseph D. Darcy + * @compile -source 1.5 IntegralDivisionTests.java + * @run main IntegralDivisionTests + */ +import java.math.*; +public class IntegralDivisionTests { + + static int dividetoIntegralValueTests() { + int failures = 0; + + // Exact integer quotient should have the same results from + // the exact divide and dividetoIntegralValue + + + // Rounded results + BigDecimal [][] moreTestCases = { + {new BigDecimal("11003"), new BigDecimal("10"), new BigDecimal("1100")}, + {new BigDecimal("11003"), new BigDecimal("1e1"), new BigDecimal("1100.0")}, + {new BigDecimal("1e9"), new BigDecimal("1"), new BigDecimal("1e9")}, + {new BigDecimal("1e9"), new BigDecimal("1.00"), new BigDecimal("1e9")}, + {new BigDecimal("1e9"), new BigDecimal("0.1"), new BigDecimal("1e10")}, + {new BigDecimal("10e8"), new BigDecimal("0.1"), new BigDecimal("10e9")}, + {new BigDecimal("400e1"), new BigDecimal("5"), new BigDecimal("80e1")}, + {new BigDecimal("400e1"), new BigDecimal("4.999999999"), new BigDecimal("8e2")}, + {new BigDecimal("40e2"), new BigDecimal("5"), new BigDecimal("8e2")}, + }; + + for(BigDecimal [] testCase: moreTestCases) { + BigDecimal quotient; + if (! (quotient=testCase[0].divideToIntegralValue(testCase[1])).equals(testCase[2]) ){ + failures++; + // BigDecimal exact = testCase[0].divide(testCase[1]); + System.err.println(); + System.err.println("dividend = " + testCase[0] + " scale = " + testCase[0].scale()); + System.err.println("divisor = " + testCase[1] + " scale = " + testCase[1].scale()); + System.err.println("quotient = " + quotient + " scale = " + quotient.scale()); + System.err.println("expected = " + testCase[2] + " scale = " + testCase[2].scale()); + // System.err.println("exact = " + exact + " scale = " + exact.scale()); + } + } + + return failures; + } + + static int dividetoIntegralValueRoundedTests() { + int failures = 0; + + BigDecimal dividend = new BigDecimal("11003"); + BigDecimal divisor = new BigDecimal("10"); + BigDecimal [] quotients = { // Expected results with precision = + new BigDecimal("1100"), // 0 + null, // 1 + new BigDecimal("11e2"), // 2 + new BigDecimal("110e1"), // 3 + new BigDecimal("1100"), // 4 + }; + failures += divideContextTestPrecs(dividend, divisor, quotients); + + dividend = new BigDecimal("11003"); + divisor = new BigDecimal("1e1"); + BigDecimal [] quotients2 = { // Expected results with precision = + new BigDecimal("1100.0"), // 0 + null, // 1 + new BigDecimal("11e2"), // 2 + new BigDecimal("110e1"), // 3 + new BigDecimal("1100"), // 4 + new BigDecimal("1100.0"), // 5 + }; + failures += divideContextTestPrecs(dividend, divisor, quotients2); + + dividend = new BigDecimal("1230000"); + divisor = new BigDecimal("100"); + BigDecimal [] quotients3 = { // Expected results with precision = + new BigDecimal("12300"), // 0 + null, // 1 + null, // 2 + new BigDecimal("123e2"), // 3 + new BigDecimal("1230e1"), // 4 + new BigDecimal("12300"), // 5 + }; + failures += divideContextTestPrecs(dividend, divisor, quotients3); + + dividend = new BigDecimal("33"); + divisor = new BigDecimal("3"); + BigDecimal [] quotients4 = { // Expected results with precision = + new BigDecimal("11"), // 0 + null, // 1 + new BigDecimal("11"), // 2 + new BigDecimal("11"), // 3 + }; + failures += divideContextTestPrecs(dividend, divisor, quotients4); + + dividend = new BigDecimal("34"); + divisor = new BigDecimal("3"); + BigDecimal [] quotients5 = { // Expected results with precision = + new BigDecimal("11"), // 0 + null, // 1 + new BigDecimal("11"), // 2 + new BigDecimal("11"), // 3 + }; + failures += divideContextTestPrecs(dividend, divisor, quotients5); + + return failures; + } + + static int divideContextTestPrecs(BigDecimal dividend, + BigDecimal divisor, + BigDecimal[] quotients) + { + int failures = 0; + for(int i = 0; i < quotients.length; i++) { + BigDecimal result = null; + BigDecimal quotient = quotients[i]; + + try { + result = dividend.divideToIntegralValue(divisor, + new MathContext(i, RoundingMode.DOWN)); + } catch (ArithmeticException e) { + if (quotient != null) { + failures++; + System.err.println(); + System.err.println("Unexpected exception:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("expected = " + quotient + " scale = " + quotient.scale()); + } + } + + if (quotient != null) { + if (! result.equals(quotient)) { + failures++; + System.err.println(); + System.err.println("Unexpected result:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("quotient = " + result + " scale = " + result.scale()); + System.err.println("expected = " + quotient + " scale = " + quotient.scale()); + System.err.println("precision = " + i); + } + } else { + if (result != null) { + failures++; + System.err.println(); + System.err.println("Unexpected unexceptional result:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("quotient = " + result + " scale = " + result.scale()); + System.err.println("precision = " + i); + } + } + + } + return failures; + } + + + static int divideContextTests(BigDecimal dividend, + BigDecimal divisor, + BigDecimal expected, + MathContext mc) { + int failures = 0; + + failures += divideContextTest(dividend, divisor, expected, mc); + failures += divideContextTest(dividend.negate(), divisor.negate(), expected, mc); + + if (expected != null) { + failures += divideContextTest(dividend.negate(), divisor, expected.negate(), mc); + failures += divideContextTest(dividend, divisor.negate(), expected.negate(), mc); + } + + return failures; + } + + + static int divideContextTest(BigDecimal dividend, + BigDecimal divisor, + BigDecimal expected, + MathContext mc) + { + int failures = 0; + + BigDecimal result = null; + + try { + result = dividend.divideToIntegralValue(divisor, mc); + } catch (ArithmeticException e) { + if (expected != null) { + failures++; + System.err.println(); + System.err.println("Unexpected exception:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("expected = " + expected + " scale = " + expected.scale()); + System.err.println("MathContext = " + mc); + } + } + + if (expected != null) { + if (! result.equals(expected)) { + failures++; + System.err.println(); + System.err.println("Unexpected result:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("expected = " + expected + " scale = " + expected.scale()); + System.err.println("result = " + result + " scale = " + result.scale()); + System.err.println("MathContext = " + mc); + } + } else { + if (result != null) { + failures++; + System.err.println(); + System.err.println("Unexpected unexceptional result:"); + System.err.println("dividend = " + dividend + " scale = " + dividend.scale()); + System.err.println("divisor = " + divisor + " scale = " + divisor.scale()); + System.err.println("quotient = " + result + " scale = " + result.scale()); + System.err.println("MathConext = " + mc); + } + } + + return failures; + } + + static int dividetoIntegralValueScalingTests() { + int failures = 0; + + BigDecimal dividend = new BigDecimal("123456789000"); + BigDecimal divisor = BigDecimal.ONE; + BigDecimal expected = new BigDecimal("123456789e3"); + MathContext mc = new MathContext(9,RoundingMode.DOWN); + failures += divideContextTests(dividend, divisor, expected, mc); + + + // 100/3 = 33 remainder 1 + int [] precisions = {0, 2, 3, 4}; + dividend = new BigDecimal(100); + divisor = new BigDecimal(3); + expected = new BigDecimal(33); + + for(RoundingMode rm: RoundingMode.values()) + for(int precision: precisions) { + failures += divideContextTests(dividend, divisor, expected, + new MathContext(precision, rm)); + } + + // 123000/10 = 12300 remainder 0 + dividend = new BigDecimal(123000); + divisor = new BigDecimal(10); + int[] precisions1 = {0, 1, 2, 3, 4, 5}; + BigDecimal[] expected1 = { + new BigDecimal("12300"), + null, + null, + new BigDecimal("123e2"), + new BigDecimal("1230e1"), + new BigDecimal("12300"), + }; + + for(RoundingMode rm: RoundingMode.values()) + for(int i = 0; i < precisions1.length; i++) { + failures += divideContextTests(dividend, divisor, + expected1[i], + new MathContext(precisions1[i], rm)); + } + + // 123e3/10 = 123e2 remainder 0 + dividend = new BigDecimal("123e3"); + divisor = new BigDecimal(10); + int[] precisions2 = {0, 1, 2, 3, 4, 5}; + BigDecimal[] expected2 = { + new BigDecimal("123e2"), + null, + null, + new BigDecimal("123e2"), + new BigDecimal("123e2"), + new BigDecimal("123e2"), + }; + + for(RoundingMode rm: RoundingMode.values()) + for(int i = 0; i < precisions2.length; i++) { + failures += divideContextTests(dividend, divisor, + expected2[i], + new MathContext(precisions2[i], rm)); + } + + + // 123000/1e1 = 12300.0 remainder 0 + dividend = new BigDecimal("123000"); + divisor = new BigDecimal("1e1"); + int[] precisions3 = {0, 1, 2, 3, 4, 5, 6}; + BigDecimal[] expected3 = { + new BigDecimal("12300.0"), + null, + null, + new BigDecimal("123e2"), + new BigDecimal("1230e1"), + new BigDecimal("12300"), + new BigDecimal("12300.0"), + }; + + for(RoundingMode rm: RoundingMode.values()) + for(int i = 0; i < precisions3.length; i++) { + failures += divideContextTests(dividend, divisor, + expected3[i], + new MathContext(precisions3[i], rm)); + } + + + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += dividetoIntegralValueTests(); + failures += dividetoIntegralValueRoundedTests(); + failures += dividetoIntegralValueScalingTests(); + + if (failures > 0) { + System.err.println("Encountered " + failures + + " failures while testing integral division."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/math/BigDecimal/NegateTests.java b/jdk/test/java/math/BigDecimal/NegateTests.java new file mode 100644 index 00000000000..2556bbde035 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/NegateTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6325535 + * @summary Test for the rounding behavior of negate(MathContext) + * @author Joseph D. Darcy + */ + +import java.math.*; + +public class NegateTests { + + static BigDecimal negateThenRound(BigDecimal bd, MathContext mc) { + return bd.negate().plus(mc); + } + + + static BigDecimal absThenRound(BigDecimal bd, MathContext mc) { + return bd.abs().plus(mc); + } + + + static int negateTest(BigDecimal[][] testCases, MathContext mc) { + int failures = 0; + + for (BigDecimal [] testCase : testCases) { + + BigDecimal bd = testCase[0]; + BigDecimal neg1 = bd.negate(mc); + BigDecimal neg2 = negateThenRound(bd, mc); + BigDecimal expected = testCase[1]; + + if (! neg1.equals(expected) ) { + failures++; + System.err.println("(" + bd + ").negate(" + mc + ") => " + + neg1 + " != expected " + expected); + } + + if (! neg1.equals(neg2) ) { + failures++; + System.err.println("(" + bd + ").negate(" + mc + ") => " + + neg1 + " != ntr " + neg2); + } + + // Test abs consistency + BigDecimal abs = bd.abs(mc); + BigDecimal expectedAbs = absThenRound(bd,mc); + if (! abs.equals(expectedAbs) ) { + failures++; + System.err.println("(" + bd + ").abs(" + mc + ") => " + + abs + " != atr " + expectedAbs); + } + + } + + return failures; + } + + static int negateTests() { + int failures = 0; + BigDecimal [][] testCasesCeiling = { + {new BigDecimal("1.3"), new BigDecimal("-1")}, + {new BigDecimal("-1.3"), new BigDecimal("2")}, + }; + + failures += negateTest(testCasesCeiling, + new MathContext(1, RoundingMode.CEILING)); + + BigDecimal [][] testCasesFloor = { + {new BigDecimal("1.3"), new BigDecimal("-2")}, + {new BigDecimal("-1.3"), new BigDecimal("1")}, + }; + + failures += negateTest(testCasesFloor, + new MathContext(1, RoundingMode.FLOOR)); + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += negateTests(); + + if (failures > 0 ) + throw new RuntimeException("Incurred " + failures + " failures" + + " testing the negate and/or abs."); + } +} diff --git a/jdk/test/java/math/BigDecimal/PowTests.java b/jdk/test/java/math/BigDecimal/PowTests.java new file mode 100644 index 00000000000..9623b70bc11 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/PowTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4916097 + * @summary Some exponent over/undeflow tests for the pow method + * @author Joseph D. Darcy + * @compile -source 1.5 PowTests.java + * @run main PowTests + */ + +import java.math.*; + +public class PowTests { + static int zeroAndOneTests() { + int failures = 0; + + BigDecimal[][] testCases = { + {BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)}, + {BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(1), BigDecimal.valueOf(0, Integer.MAX_VALUE)}, + {BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(2), BigDecimal.valueOf(0, Integer.MAX_VALUE)}, + {BigDecimal.valueOf(0, Integer.MAX_VALUE), new BigDecimal(999999999), BigDecimal.valueOf(0, Integer.MAX_VALUE)}, + + {BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)}, + {BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(1), BigDecimal.valueOf(0, Integer.MIN_VALUE)}, + {BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(2), BigDecimal.valueOf(0, Integer.MIN_VALUE)}, + {BigDecimal.valueOf(0, Integer.MIN_VALUE), new BigDecimal(999999999), BigDecimal.valueOf(0, Integer.MIN_VALUE)}, + + {BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)}, + {BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(1), BigDecimal.valueOf(1, Integer.MAX_VALUE)}, + {BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(2), null}, // overflow + {BigDecimal.valueOf(1, Integer.MAX_VALUE), new BigDecimal(999999999), null}, // overflow + + {BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(0), BigDecimal.valueOf(1, 0)}, + {BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(1), BigDecimal.valueOf(1, Integer.MIN_VALUE)}, + {BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(2), null}, // underflow + {BigDecimal.valueOf(1, Integer.MIN_VALUE), new BigDecimal(999999999), null}, // underflow + }; + + for(BigDecimal[] testCase: testCases) { + int exponent = testCase[1].intValueExact(); + BigDecimal result; + + try{ + result = testCase[0].pow(exponent); + if (!result.equals(testCase[2]) ) { + failures++; + System.err.println("Unexpected result while raising " + + testCase[0] + + " to the " + exponent + " power; expected " + + testCase[2] + ", got " + result + "."); + } + } catch (ArithmeticException e) { + if (testCase[2] != null) { + failures++; + System.err.println("Unexpected exception while raising " + testCase[0] + + " to the " + exponent + " power."); + + } + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += zeroAndOneTests(); + + if (failures > 0) { + throw new RuntimeException("Incurred " + failures + + " failures while testing pow methods."); + } + } + +} diff --git a/jdk/test/java/math/BigDecimal/RoundingTests.java b/jdk/test/java/math/BigDecimal/RoundingTests.java new file mode 100644 index 00000000000..69a66a174c1 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/RoundingTests.java @@ -0,0 +1,59 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6334849 + * @summary Tests of dropping digits near the scale threshold + * @author Joseph D. Darcy + */ +import java.math.*; +public class RoundingTests { + private static int roundingTests() { + int failures = 0; + BigDecimal bd1 = BigDecimal.valueOf(11, Integer.MIN_VALUE); + BigDecimal bd2 = null; + MathContext mc = new MathContext(1); + try { + bd2 = bd1.round(mc); // should overflow here + failures++; + System.err.printf("Did not get expected overflow rounding %s to %d digits, got %s%n", + bd1, mc.getPrecision(), bd2); + } catch(ArithmeticException e) { + ; // expected + } + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += roundingTests(); + + if (failures > 0) { + System.err.println("Encountered " + failures + + " failures while testing rounding."); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java b/jdk/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java new file mode 100644 index 00000000000..cb0519262d6 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4899722 + * @summary Basic tests of scaleByPowerOfTen + * @author Joseph D. Darcy + */ + +import java.math.*; + +public class ScaleByPowerOfTenTests { + + public static void main(String argv[]) { + for (int i = -10; i < 10; i++) { + BigDecimal bd = BigDecimal.ONE.scaleByPowerOfTen(i); + BigDecimal expected; + + if (!bd.equals(expected = new BigDecimal(BigInteger.ONE, -i))) { + throw new RuntimeException("Unexpected result " + + bd.toString() + + "; expected " + + expected.toString()); + } + + bd = BigDecimal.ONE.negate().scaleByPowerOfTen(i); + if (!bd.equals(expected = new BigDecimal(BigInteger.ONE.negate(), -i))) { + throw new RuntimeException("Unexpected result " + + bd.toString() + + "; expected " + + expected.toString()); + } + + + } + } +} diff --git a/jdk/test/java/math/BigDecimal/SerializationTests.java b/jdk/test/java/math/BigDecimal/SerializationTests.java new file mode 100644 index 00000000000..902e21661ab --- /dev/null +++ b/jdk/test/java/math/BigDecimal/SerializationTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6177836 + * @summary Verify BigDecimal objects with collapsed values are serialized properly. + * @author Joseph D. Darcy + */ + +import java.math.*; +import java.io.*; + +public class SerializationTests { + + static void checkSerialForm(BigDecimal bd) throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(bd); + oos.flush(); + oos.close(); + ObjectInputStream ois = new + ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); + BigDecimal tmp = (BigDecimal)ois.readObject(); + + if (!bd.equals(tmp) || + bd.hashCode() != tmp.hashCode()) { + System.err.print(" original : " + bd); + System.err.println(" (hash: 0x" + Integer.toHexString(bd.hashCode()) + ")"); + System.err.print("serialized : " + tmp); + System.err.println(" (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")"); + throw new RuntimeException("Bad serial roundtrip"); + } + } + + public static void main(String[] args) throws Exception { + BigDecimal values[] = { + BigDecimal.ZERO, + BigDecimal.ONE, + BigDecimal.TEN, + new BigDecimal(0), + new BigDecimal(1), + new BigDecimal(10), + new BigDecimal(Integer.MAX_VALUE), + new BigDecimal(Long.MAX_VALUE-1), + new BigDecimal(BigInteger.valueOf(1), 1), + new BigDecimal(BigInteger.valueOf(100), 50), + }; + + for(BigDecimal value : values) { + checkSerialForm(value); + checkSerialForm(value.negate()); + } + + } +} diff --git a/jdk/test/java/math/BigDecimal/StringConstructor.java b/jdk/test/java/math/BigDecimal/StringConstructor.java new file mode 100644 index 00000000000..5fdd23c0456 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/StringConstructor.java @@ -0,0 +1,163 @@ +/* + * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4103117 4331084 4488017 4490929 6255285 6268365 + * @summary Tests the BigDecimal string constructor. + */ + +import java.math.*; +import java.util.Random; + +public class StringConstructor { + + private static int seed = new Random().nextInt(); + private static Random rnd = new Random(seed); + + public static void main(String[] args) throws Exception { + constructWithError(""); + constructWithError("+"); + constructWithError("-"); + constructWithError("+e"); + constructWithError("-e"); + constructWithError("e+"); + constructWithError("1.-0"); + constructWithError(".-123"); + constructWithError("-"); + constructWithError("--1.1"); + constructWithError("-+1.1"); + constructWithError("+-1.1"); + constructWithError("1-.1"); + constructWithError("1+.1"); + constructWithError("1.111+1"); + constructWithError("1.111-1"); + constructWithError("11.e+"); + constructWithError("11.e-"); + constructWithError("11.e+-"); + constructWithError("11.e-+"); + constructWithError("11.e-+1"); + constructWithError("11.e+-1"); + + // Range checks + constructWithError("1e"+Integer.MIN_VALUE); + constructWithError("10e"+Integer.MIN_VALUE); + constructWithError("0.01e"+Integer.MIN_VALUE); + constructWithError("1e"+((long)Integer.MIN_VALUE-1)); + constructWithError("1e"+((long)Integer.MAX_VALUE + 1)); + + leadingExponentZeroTest(); + nonAsciiZeroTest(); + + // Roundtrip tests + for (int i=0; i<100; i++) { + int size = rnd.nextInt(100) + 1; + BigInteger bi = new BigInteger(size, rnd); + if (rnd.nextBoolean()) + bi = bi.negate(); + int decimalLength = bi.toString().length(); + int scale = rnd.nextInt(decimalLength); + BigDecimal bd = new BigDecimal(bi, scale); + String bdString = bd.toString(); + // System.err.println("bi" + bi.toString() + "\tscale " + scale); + // System.err.println("bd string: " + bdString); + BigDecimal bdDoppel = new BigDecimal(bdString); + if (!bd.equals(bdDoppel)) { + System.err.println("Random number seed = " + seed); + System.err.println("bd string: scale: " + bd.scale() + + "\t" + bdString); + System.err.println("bd doppel: scale: " + bdDoppel.scale() + + "\t" + bdDoppel.toString()); + throw new RuntimeException("String constructor failure."); + } + } + } + + + /* + * Verify precision is set properly if the significand has + * non-ASCII leading zeros. + */ + private static void nonAsciiZeroTest() { + String values[] = { + "00004e5", + "\u0660\u0660\u0660\u06604e5", + }; + + BigDecimal expected = new BigDecimal("4e5"); + + for(String s : values) { + BigDecimal tmp = new BigDecimal(s); + // System.err.println("Testing " + s); + if (! expected.equals(tmp) || tmp.precision() != 1) { + System.err.println("Bad conversion of " + s + "got " + + tmp + "precision = " + tmp.precision()); + throw new RuntimeException("String constructor failure."); + } + } + + } + + private static void leadingExponentZeroTest() { + BigDecimal twelve = new BigDecimal("12"); + BigDecimal onePointTwo = new BigDecimal("1.2"); + + String start = "1.2e0"; + String end = "1"; + String middle = ""; + + // Test with more excess zeros than the largest number of + // decimal digits needed to represent a long + int limit = ((int)Math.log10(Long.MAX_VALUE)) + 6; + for(int i = 0; i < limit; i++, middle += "0") { + String t1 = start + middle; + String t2 = t1 + end; + + // System.out.println(i + "\t" + t1 + "\t" + t2); + testString(t1, onePointTwo); + testString(t2, twelve); + } + } + + private static void testString(String s, BigDecimal expected) { + testString0(s, expected); + testString0(switchZero(s), expected); + } + + private static void testString0(String s, BigDecimal expected) { + if (!expected.equals(new BigDecimal(s))) + throw new RuntimeException(s + " is not equal to " + expected); + } + + private static String switchZero(String s) { + return s.replace('0', '\u0660'); // Arabic-Indic zero + } + + private static void constructWithError(String badString) { + try { + BigDecimal d = new BigDecimal(badString); + throw new RuntimeException(badString + " accepted"); + } catch(NumberFormatException e) { + } + } +} diff --git a/jdk/test/java/math/BigDecimal/StrippingZerosTest.java b/jdk/test/java/math/BigDecimal/StrippingZerosTest.java new file mode 100644 index 00000000000..918d46ef10f --- /dev/null +++ b/jdk/test/java/math/BigDecimal/StrippingZerosTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4108852 + * @summary A few tests of stripTrailingZeros + * @author Joseph D. Darcy + */ + +import java.math.*; + +public class StrippingZerosTest { + public static void main(String argv[]) { + BigDecimal [][] testCases = { + {new BigDecimal("1.00000"), new BigDecimal("1")}, + {new BigDecimal("1.000"), new BigDecimal("1")}, + {new BigDecimal("1"), new BigDecimal("1")}, + {new BigDecimal("0.1234"), new BigDecimal("0.1234")}, + {new BigDecimal("0.12340"), new BigDecimal("0.1234")}, + {new BigDecimal("0.12340000000"), new BigDecimal("0.1234")}, + {new BigDecimal("1234.5678"), new BigDecimal("1234.5678")}, + {new BigDecimal("1234.56780"), new BigDecimal("1234.5678")}, + {new BigDecimal("1234.567800000"), new BigDecimal("1234.5678")}, + {new BigDecimal("0"), new BigDecimal("0")}, + {new BigDecimal("0e100"), new BigDecimal("0e100")}, + {new BigDecimal("0e-100"), new BigDecimal("0e-100")}, + {new BigDecimal("10"), new BigDecimal("1e1")}, + {new BigDecimal("20"), new BigDecimal("2e1")}, + {new BigDecimal("100"), new BigDecimal("1e2")}, + {new BigDecimal("1000000000"), new BigDecimal("1e9")}, + {new BigDecimal("100000000e1"), new BigDecimal("1e9")}, + {new BigDecimal("10000000e2"), new BigDecimal("1e9")}, + {new BigDecimal("1000000e3"), new BigDecimal("1e9")}, + {new BigDecimal("100000e4"), new BigDecimal("1e9")}, + }; + + for(int i = 0; i < testCases.length; i++) { + + if (!(testCases[i][0]).stripTrailingZeros().equals(testCases[i][1])) { + throw new RuntimeException("For input " + testCases[i][0].toString() + + " did not received expected result " + + testCases[i][1].toString() + ", got " + + testCases[i][0].stripTrailingZeros()); + } + + testCases[i][0] = testCases[i][0].negate(); + testCases[i][1] = testCases[i][1].negate(); + + if (!(testCases[i][0]).stripTrailingZeros().equals(testCases[i][1])) { + throw new RuntimeException("For input " + testCases[i][0].toString() + + " did not received expected result " + + testCases[i][1].toString() + ", got " + + testCases[i][0].stripTrailingZeros()); + } + + } + } +} diff --git a/jdk/test/java/math/BigDecimal/ToPlainStringTests.java b/jdk/test/java/math/BigDecimal/ToPlainStringTests.java new file mode 100644 index 00000000000..aca745b7e4b --- /dev/null +++ b/jdk/test/java/math/BigDecimal/ToPlainStringTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4984872 + * @summary Basic tests of toPlainString method + * @author Joseph D. Darcy + * @compile -source 1.5 ToPlainStringTests.java + * @run main ToPlainStringTests + */ + +import java.math.*; + +public class ToPlainStringTests { + public static void main(String argv[]) { + String [][] testCases = { + {"0", "0"}, + {"1", "1"}, + {"10", "10"}, + {"2e1", "20"}, + {"3e2", "300"}, + {"4e3", "4000"}, + {"5e4", "50000"}, + {"6e5", "600000"}, + {"7e6", "7000000"}, + {"8e7", "80000000"}, + {"9e8", "900000000"}, + {"1e9", "1000000000"}, + + {".0", "0.0"}, + {".1", "0.1"}, + {".10", "0.10"}, + {"1e-1", "0.1"}, + {"1e-1", "0.1"}, + {"2e-2", "0.02"}, + {"3e-3", "0.003"}, + {"4e-4", "0.0004"}, + {"5e-5", "0.00005"}, + {"6e-6", "0.000006"}, + {"7e-7", "0.0000007"}, + {"8e-8", "0.00000008"}, + {"9e-9", "0.000000009"}, + {"9000e-12", "0.000000009000"}, + }; + + int errors = 0; + for(String[] testCase: testCases) { + BigDecimal bd = new BigDecimal(testCase[0]); + String s; + + if (!(s=bd.toPlainString()).equals(testCase[1])) { + errors++; + System.err.println("Unexpected plain result ``" + + s + "'' from BigDecimal " + + bd); + } + + if (!(s=("-"+bd.toPlainString())).equals("-"+testCase[1])) { + errors++; + System.err.println("Unexpected plain result ``" + + s + "'' from BigDecimal " + + bd); + } + } + + if(errors > 0) + throw new RuntimeException(errors + " errors during run."); + } +} diff --git a/jdk/test/java/math/BigDecimal/ZeroScalingTests.java b/jdk/test/java/math/BigDecimal/ZeroScalingTests.java new file mode 100644 index 00000000000..a48e005a4b1 --- /dev/null +++ b/jdk/test/java/math/BigDecimal/ZeroScalingTests.java @@ -0,0 +1,466 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4902952 4905407 4916149 + * @summary Tests that the scale of zero is propagated properly and has the proper effect. + * @author Joseph D. Darcy + * @compile -source 1.5 ZeroScalingTests.java + * @run main ZeroScalingTests + */ + +import java.math.*; +import java.util.*; + +public class ZeroScalingTests { + + static MathContext longEnough = new MathContext(50, RoundingMode.UNNECESSARY); + + static BigDecimal[] zeros = new BigDecimal[23]; + static { + for(int i = 0; i < 21; i++) { + zeros[i] = new BigDecimal(BigInteger.ZERO, i-10); + } + zeros[21] = new BigDecimal(BigInteger.ZERO, Integer.MIN_VALUE); + zeros[22] = new BigDecimal(BigInteger.ZERO, Integer.MAX_VALUE); + } + + static BigDecimal element = BigDecimal.valueOf(100, -2); + + static MathContext contexts[] = { + new MathContext(0, RoundingMode.UNNECESSARY), + new MathContext(100, RoundingMode.UNNECESSARY), + new MathContext(5, RoundingMode.UNNECESSARY), + new MathContext(4, RoundingMode.UNNECESSARY), + new MathContext(3, RoundingMode.UNNECESSARY), + new MathContext(2, RoundingMode.UNNECESSARY), + new MathContext(1, RoundingMode.UNNECESSARY), + }; + + + static int addTests() { + int failures = 0; + + for(BigDecimal zero1: zeros) { + for(BigDecimal zero2: zeros) { + BigDecimal expected = new BigDecimal(BigInteger.ZERO, + Math.max(zero1.scale(), zero2.scale())); + BigDecimal result; + + if(! (result=zero1.add(zero2)).equals(expected) ) { + failures++; + System.err.println("For classic exact add, expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.add(zero2, MathContext.UNLIMITED)).equals(expected) ) { + failures++; + System.err.println("For UNLIMITED math context add," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.add(zero2, longEnough)).equals(expected) ) { + failures++; + System.err.println("For longEnough math context add," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + } + } + + // Test effect of adding zero to a nonzero value. + for (MathContext mc: contexts) { + for (BigDecimal zero: zeros) { + if (Math.abs((long)zero.scale()) < 100 ) { + + int preferredScale = Math.max(zero.scale(), element.scale()); + if (mc.getPrecision() != 0) { + if (preferredScale < -4 ) + preferredScale = -4; + else if (preferredScale > -(5 - mc.getPrecision())) { + preferredScale = -(5 - mc.getPrecision()); + } + } + + + /* + System.err.println("\n " + element + " +\t" + zero + " =\t" + result); + + System.err.println("scales" + element.scale() + " \t" + zero.scale() + + " \t " + result.scale() + "\t precison = " + mc.getPrecision()); + System.err.println("expected scale = " + preferredScale); + */ + + BigDecimal result = element.add(zero, mc); + if (result.scale() != preferredScale || + result.compareTo(element) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = zero.add(element, mc); + if (result.scale() != preferredScale || + result.compareTo(element) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = element.negate().add(zero, mc); + if (result.scale() != preferredScale || + result.compareTo(element.negate()) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = zero.add(element.negate(), mc); + if (result.scale() != preferredScale || + result.compareTo(element.negate()) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + } + } + } + + return failures; + } + + static int subtractTests() { + int failures = 0; + + for(BigDecimal zero1: zeros) { + for(BigDecimal zero2: zeros) { + BigDecimal expected = new BigDecimal(BigInteger.ZERO, + Math.max(zero1.scale(), zero2.scale())); + BigDecimal result; + + if(! (result=zero1.subtract(zero2)).equals(expected) ) { + failures++; + System.err.println("For classic exact subtract, expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.subtract(zero2, MathContext.UNLIMITED)).equals(expected) ) { + failures++; + System.err.println("For UNLIMITED math context subtract," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.subtract(zero2, longEnough)).equals(expected) ) { + failures++; + System.err.println("For longEnough math context subtract," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + } + } + + + // Test effect of adding zero to a nonzero value. + for (MathContext mc: contexts) { + for (BigDecimal zero: zeros) { + if (Math.abs((long)zero.scale()) < 100 ) { + + int preferredScale = Math.max(zero.scale(), element.scale()); + if (mc.getPrecision() != 0) { + if (preferredScale < -4 ) + preferredScale = -4; + else if (preferredScale > -(5 - mc.getPrecision())) { + preferredScale = -(5 - mc.getPrecision()); + } + } + + + /* + System.err.println("\n " + element + " +\t" + zero + " =\t" + result); + + System.err.println("scales" + element.scale() + " \t" + zero.scale() + + " \t " + result.scale() + "\t precison = " + mc.getPrecision()); + System.err.println("expected scale = " + preferredScale); + */ + + BigDecimal result = element.subtract(zero, mc); + if (result.scale() != preferredScale || + result.compareTo(element) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = zero.subtract(element, mc); + if (result.scale() != preferredScale || + result.compareTo(element.negate()) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = element.negate().subtract(zero, mc); + if (result.scale() != preferredScale || + result.compareTo(element.negate()) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + result = zero.subtract(element.negate(), mc); + if (result.scale() != preferredScale || + result.compareTo(element) != 0) { + failures++; + System.err.println("Expected scale " + preferredScale + + " result scale was " + result.scale() + + " ; value was " + result); + } + + } + } + } + + return failures; + } + + static int multiplyTests() { + int failures = 0; + + BigDecimal ones[] = { + BigDecimal.valueOf(1, 0), + BigDecimal.valueOf(10, 1), + BigDecimal.valueOf(1000, 3), + BigDecimal.valueOf(100000000, 8), + }; + + List values = new LinkedList(); + values.addAll(Arrays.asList(zeros)); + values.addAll(Arrays.asList(ones)); + + for(BigDecimal zero1: zeros) { + for(BigDecimal value: values) { + BigDecimal expected = new BigDecimal(BigInteger.ZERO, + (int)Math.min(Math.max((long)zero1.scale()+value.scale(), + Integer.MIN_VALUE ), + Integer.MAX_VALUE ) ); + BigDecimal result; + + if(! (result=zero1.multiply(value)).equals(expected) ) { + failures++; + System.err.println("For classic exact multiply, expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.multiply(value, MathContext.UNLIMITED)).equals(expected) ) { + failures++; + System.err.println("For UNLIMITED math context multiply," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero1.multiply(value, longEnough)).equals(expected) ) { + failures++; + System.err.println("For longEnough math context multiply," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + } + } + + return failures; + } + + static int divideTests() { + int failures = 0; + + BigDecimal [] ones = { + BigDecimal.valueOf(1, 0), + BigDecimal.valueOf(10, -1), + BigDecimal.valueOf(100, -2), + BigDecimal.valueOf(1000, -3), + BigDecimal.valueOf(1000000, -5), + }; + + for(BigDecimal one: ones) { + for(BigDecimal zero: zeros) { + BigDecimal expected = new BigDecimal(BigInteger.ZERO, + (int)Math.min(Math.max((long)zero.scale() - one.scale(), + Integer.MIN_VALUE ), + Integer.MAX_VALUE ) ); + BigDecimal result; + + if(! (result=zero.divide(one)).equals(expected) ) { + failures++; + System.err.println("For classic exact divide, expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero.divide(one, MathContext.UNLIMITED)).equals(expected) ) { + failures++; + System.err.println("For UNLIMITED math context divide," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + if(! (result=zero.divide(one, longEnough)).equals(expected) ) { + failures++; + System.err.println("For longEnough math context divide," + + " expected scale of " + + expected.scale() + "; got " + + result.scale() + "."); + } + + } + } + + return failures; + } + + static int setScaleTests() { + int failures = 0; + + int scales[] = { + Integer.MIN_VALUE, + Integer.MIN_VALUE+1, + -10000000, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 10, + 10000000, + Integer.MAX_VALUE-1, + Integer.MAX_VALUE + }; + + for(BigDecimal zero: zeros) { + for(int scale: scales) { + try { + BigDecimal bd = zero.setScale(scale); + } + catch (ArithmeticException e) { + failures++; + System.err.println("Exception when trying to set a scale of " + scale + + " on " + zero); + } + } + } + + return failures; + } + + static int toEngineeringStringTests() { + int failures = 0; + + String [][] testCases = { + {"0E+10", "0.00E+12"}, + {"0E+9", "0E+9"}, + {"0E+8", "0.0E+9"}, + {"0E+7", "0.00E+9"}, + + {"0E-10", "0.0E-9"}, + {"0E-9", "0E-9"}, + {"0E-8", "0.00E-6"}, + {"0E-7", "0.0E-6"}, + }; + + for(String[] testCase: testCases) { + BigDecimal bd = new BigDecimal(testCase[0]); + String result = bd.toEngineeringString(); + + if (!result.equals(testCase[1]) || + !bd.equals(new BigDecimal(result))) { + failures++; + System.err.println("From input ``" + testCase[0] + ",'' " + + " bad engineering string output ``" + result + + "''; expected ``" + testCase[1] + ".''"); + } + + } + + return failures; + } + + static int ulpTests() { + int failures = 0; + + for(BigDecimal zero: zeros) { + BigDecimal result; + BigDecimal expected = BigDecimal.valueOf(1, zero.scale()); + + if (! (result=zero.ulp()).equals(expected) ) { + failures++; + System.err.println("Unexpected ulp value for zero value " + + zero + "; expected " + expected + + ", got " + result); + } + } + + return failures; + } + + public static void main(String argv[]) { + int failures = 0; + + failures += addTests(); + failures += subtractTests(); + failures += multiplyTests(); + failures += divideTests(); + failures += setScaleTests(); + failures += toEngineeringStringTests(); + failures += ulpTests(); + + if (failures > 0 ) { + throw new RuntimeException("Incurred " + failures + " failures" + + " testing the preservation of zero scales."); + } + } +} diff --git a/jdk/test/java/math/BigInteger/BigIntegerTest.java b/jdk/test/java/math/BigInteger/BigIntegerTest.java new file mode 100644 index 00000000000..75ce0033779 --- /dev/null +++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java @@ -0,0 +1,792 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 + * @summary tests methods in BigInteger + * @run main/timeout=400 BigIntegerTest + * @author madbot + */ + +import java.util.Random; +import java.math.BigInteger; +import java.io.*; + +/** + * This is a simple test class created to ensure that the results + * generated by BigInteger adhere to certain identities. Passing + * this test is a strong assurance that the BigInteger operations + * are working correctly. + * + * Three arguments may be specified which give the number of + * decimal digits you desire in the three batches of test numbers. + * + * The tests are performed on arrays of random numbers which are + * generated by a Random class as well as special cases which + * throw in boundary numbers such as 0, 1, maximum sized, etc. + * + */ +public class BigIntegerTest { + static Random rnd = new Random(); + static int size = 1000; // numbers per batch + static boolean failure = false; + + // Some variables for sizing test numbers in bits + private static int order1 = 100; + private static int order2 = 60; + private static int order3 = 30; + + public static void pow() { + int failCount1 = 0; + + for (int i=0; i>= 1; + } + + if (bigX.bitCount() != bitCount) { + //System.err.println(x+": "+bitCount+", "+bigX.bitCount()); + failCount++; + } + } + report("Bit Count", failCount); + } + + public static void bitLength() { + int failCount = 0; + + for (int i=0; i0) + order1 = (int)((Integer.parseInt(args[0]))* 3.333); + if (args.length >1) + order2 = (int)((Integer.parseInt(args[1]))* 3.333); + if (args.length >2) + order3 = (int)((Integer.parseInt(args[2]))* 3.333); + + prime(); + nextProbablePrime(); + + arithmetic(); + divideAndRemainder(); + pow(); + + bitCount(); + bitLength(); + bitOps(); + bitwise(); + + shift(); + + byteArrayConv(); + + modInv(); + modExp(); + modExp2(); + + stringConv(); + serialize(); + + if (failure) + throw new RuntimeException("Failure in BigIntegerTest."); + } + + /* + * Get a random or boundary-case number. This is designed to provide + * a lot of numbers that will find failure points, such as max sized + * numbers, empty BigIntegers, etc. + * + * If order is less than 2, order is changed to 2. + */ + private static BigInteger fetchNumber(int order) { + boolean negative = rnd.nextBoolean(); + int numType = rnd.nextInt(6); + BigInteger result = null; + if (order < 2) order = 2; + + switch (numType) { + case 0: // Empty + result = BigInteger.ZERO; + break; + + case 1: // One + result = BigInteger.ONE; + break; + + case 2: // All bits set in number + int numBytes = (order+7)/8; + byte[] fullBits = new byte[numBytes]; + for(int i=0; i 0) + failure = true; + } +} diff --git a/jdk/test/java/math/BigInteger/ModPow.java b/jdk/test/java/math/BigInteger/ModPow.java new file mode 100644 index 00000000000..6f07c3df230 --- /dev/null +++ b/jdk/test/java/math/BigInteger/ModPow.java @@ -0,0 +1,52 @@ +/* + * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4181191 + * @summary test BigInteger modPow method + */ +import java.math.BigInteger; +import java.util.Random; + +public class ModPow { + public static void main(String[] args) { + Random rnd = new Random(1234); + + for (int i=0; i<2000; i++) { + BigInteger m = new BigInteger(800, rnd); + BigInteger base = new BigInteger(16, rnd); + if (rnd.nextInt() % 1 == 0) + base = base.negate(); + BigInteger exp = new BigInteger(8, rnd); + + BigInteger z = base.modPow(exp, m); + BigInteger w = base.pow(exp.intValue()).mod(m); + if (!z.equals(w)){ + System.err.println(base +" ** " + exp + " mod "+ m); + System.err.println("modPow : " + z); + System.err.println("pow.mod: " + w); + throw new RuntimeException("BigInteger modPow failure."); + } + } + } +} diff --git a/jdk/test/java/math/BigInteger/ModPow65537.java b/jdk/test/java/math/BigInteger/ModPow65537.java new file mode 100644 index 00000000000..18d11514962 --- /dev/null +++ b/jdk/test/java/math/BigInteger/ModPow65537.java @@ -0,0 +1,96 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4891312 + * @summary verify that modPow() not broken by the special case for 65537 + * @author Andreas Sterbenz + */ + +import java.math.BigInteger; +import java.util.*; + +import java.security.*; +import java.security.spec.*; + +public class ModPow65537 { + + public static void main(String[] args) throws Exception { + // SunRsaSign uses BigInteger internally + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "SunRsaSign"); + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65537))); + KeyPair kp = kpg.generateKeyPair(); + testSigning(kp); + + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(65539))); + kp = kpg.generateKeyPair(); + testSigning(kp); + + kpg.initialize(new RSAKeyGenParameterSpec(512, BigInteger.valueOf(3))); + kp = kpg.generateKeyPair(); + testSigning(kp); + + // basic known answer test + BigInteger base = new BigInteger("19058071224156864789844466979330892664777520457048234786139035643344145635582"); + BigInteger mod = new BigInteger("75554098474976067521257305210610421240510163914613117319380559667371251381587"); + BigInteger exp1 = BigInteger.valueOf(65537); + BigInteger exp2 = BigInteger.valueOf(75537); + BigInteger exp3 = new BigInteger("13456870775607312149"); + + BigInteger res1 = new BigInteger("5770048609366563851320890693196148833634112303472168971638730461010114147506"); + BigInteger res2 = new BigInteger("63446979364051087123350579021875958137036620431381329472348116892915461751531"); + BigInteger res3 = new BigInteger("39016891919893878823999350081191675846357272199067075794096200770872982089502"); + + if (base.modPow(exp1, mod).equals(res1) == false) { + throw new Exception("Error using " + exp1); + } + if (base.modPow(exp2, mod).equals(res2) == false) { + throw new Exception("Error using " + exp2); + } + if (base.modPow(exp3, mod).equals(res3) == false) { + throw new Exception("Error using " + exp3); + } + + System.out.println("Passed"); + } + + private static void testSigning(KeyPair kp) throws Exception { + System.out.println(kp.getPublic()); + byte[] data = new byte[1024]; + new Random().nextBytes(data); + + Signature sig = Signature.getInstance("SHA1withRSA", "SunRsaSign"); + sig.initSign(kp.getPrivate()); + sig.update(data); + byte[] sigBytes = sig.sign(); + + sig.initVerify(kp.getPublic()); + sig.update(data); + if (sig.verify(sigBytes) == false) { + throw new Exception("signature verification failed"); + } + System.out.println("OK"); + } + +} diff --git a/jdk/test/java/math/BigInteger/ModPowPowersof2.java b/jdk/test/java/math/BigInteger/ModPowPowersof2.java new file mode 100644 index 00000000000..7ba02661438 --- /dev/null +++ b/jdk/test/java/math/BigInteger/ModPowPowersof2.java @@ -0,0 +1,85 @@ +/* + * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 4098742 + @summary Test biginteger modpow method + @author Michael McCloskey + @run main/othervm ModPowPowersof2 +*/ + +import java.math.BigInteger; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.File; +import java.io.IOException; + +/** + * This class tests to see if using modPow on a power + * of two crashes the vm + * + */ +public class ModPowPowersof2 { + + public static void main(String args[]) throws Exception { + // Construct a command that runs the test in other vm + String[] command = new String[4]; + int n = 0; + + command[n++] = System.getProperty("java.home") + File.separator + + "bin" + File.separator + "java"; + if (System.getProperty("java.class.path") != null) { + command[n++] = "-classpath"; + command[n++] = System.getProperty("java.class.path"); + } + + command[n++] = "ModPowPowersof2$ModTester"; + + // Exec another vm to run test in + Process p = null; + p = Runtime.getRuntime().exec(command); + + // Read the result to determine if test failed + BufferedReader in = new BufferedReader(new InputStreamReader( + p.getInputStream())); + String s; + s = in.readLine(); + if (s == null) + throw new RuntimeException("ModPow causes vm crash"); + + } + + public static class ModTester { + public static void main(String [] args) { + BigInteger two = BigInteger.valueOf(2); + BigInteger four = BigInteger.valueOf(4); + + two.modPow(two, BigInteger.valueOf(4)); + two.modPow(two, BigInteger.valueOf(8)); + two.modPow(four, BigInteger.valueOf(8)); + + System.out.println("success"); + } + } + +} diff --git a/jdk/test/java/math/BigInteger/OperatorNpeTests.java b/jdk/test/java/math/BigInteger/OperatorNpeTests.java new file mode 100644 index 00000000000..6639dfa23e7 --- /dev/null +++ b/jdk/test/java/math/BigInteger/OperatorNpeTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6365176 + * @summary Get NullPointerExceptions when expected + * @author Joseph D. Darcy + */ + +import java.math.*; +import static java.math.BigInteger.*; + +public class OperatorNpeTests { + + public static void main(String... argv) { + BigInteger[] specialValues = {ZERO, ONE, TEN}; + + for (BigInteger bd : specialValues) { + BigInteger result; + try { + result = bd.multiply(null); + throw new RuntimeException("Instead of NPE got " + result); + } catch (NullPointerException npe) { + ; // Expected + } + + try { + result = bd.divide(null); + throw new RuntimeException("Instead of NPE got " + result); + } catch (NullPointerException npe) { + ; // Expected + } + + try { + result = bd.add(null); + throw new RuntimeException("Instead of NPE got " + result); + } catch (NullPointerException npe) { + ; // Expected + } + + try { + result = bd.subtract(null); + throw new RuntimeException("Instead of NPE got " + result); + } catch (NullPointerException npe) { + ; // Expected + } + + + } + } +} diff --git a/jdk/test/java/math/BigInteger/ProbablePrime.java b/jdk/test/java/math/BigInteger/ProbablePrime.java new file mode 100644 index 00000000000..44b129beffb --- /dev/null +++ b/jdk/test/java/math/BigInteger/ProbablePrime.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4654323 + * @summary Tests functionality of isProbablePrime(Integer.MAX_VALUE) + */ +import java.math.*; + +public class ProbablePrime { + public static void main(String [] argv) { + BigInteger num = new BigInteger("4"); + int certainties[] = {-1, 0, 1, 2, 100, Integer.MAX_VALUE-1, + Integer.MAX_VALUE}; + boolean expectations[] = {true, true, false, false, false, + false, false}; + + for(int i = 0; i < certainties.length; i++) { + boolean b; + if((b=num.isProbablePrime(certainties[i])) != + expectations[i]) + throw new RuntimeException("Unexpected answer " + b + + " for certainty " + + certainties[i]); + } + } +} diff --git a/jdk/test/java/math/BigInteger/StringConstructor.java b/jdk/test/java/math/BigInteger/StringConstructor.java new file mode 100644 index 00000000000..530d7f22439 --- /dev/null +++ b/jdk/test/java/math/BigInteger/StringConstructor.java @@ -0,0 +1,90 @@ +/* + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4489146 5017980 + * @summary tests String constructors of BigInteger + * @author Joseph D. Darcy + */ +import java.math.*; + +public class StringConstructor { + + + public static void main(String [] argv) { + // Good strings + constructWithoutError("0", 0L); + constructWithoutError("000000000000000000", 0L); + constructWithoutError("1", 1L); + constructWithoutError("-1", -1L); + constructWithoutError("+1", +1L); + constructWithoutError( "123456789123456789", 123456789123456789L); + constructWithoutError("+123456789123456789", 123456789123456789L); + constructWithoutError("-123456789123456789", -123456789123456789L); + constructWithoutError(Integer.toString(Integer.MIN_VALUE), + (long)Integer.MIN_VALUE); + constructWithoutError(Integer.toString(Integer.MAX_VALUE), + (long)Integer.MAX_VALUE); + constructWithoutError(Long.toString(Long.MIN_VALUE), + Long.MIN_VALUE); + constructWithoutError(Long.toString(Long.MAX_VALUE), + Long.MAX_VALUE); + + // Bad strings + constructWithError(""); + constructWithError("-"); + constructWithError("+"); + constructWithError("--"); + constructWithError("++"); + constructWithError("-000-0"); + constructWithError("+000+0"); + constructWithError("+000-0"); + constructWithError("--1234567890"); + constructWithError("++1234567890"); + constructWithError("-0-12345678"); + constructWithError("+0+12345678"); + constructWithError("--12345678-12345678-12345678"); + constructWithError("++12345678+12345678+12345678"); + constructWithError("12345-"); + constructWithError("12345+"); + } + + // this method adapted from ../BigDecimal/StringConstructor.java + private static void constructWithError(String badString) { + try { + BigInteger bi = new BigInteger(badString); + throw new RuntimeException(badString + " accepted"); + } catch(NumberFormatException e) { + } + } + + private static void constructWithoutError(String goodString, long value) { + BigInteger bi = new BigInteger(goodString); + if(bi.longValue() != value) { + System.err.printf("From ``%s'' expected %d, got %s.\n", goodString, value, bi); + throw new RuntimeException(); + } + } + +} diff --git a/jdk/test/java/math/BigInteger/UnicodeConstructor.java b/jdk/test/java/math/BigInteger/UnicodeConstructor.java new file mode 100644 index 00000000000..df00450d847 --- /dev/null +++ b/jdk/test/java/math/BigInteger/UnicodeConstructor.java @@ -0,0 +1,57 @@ +/* + * Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4040456 + * @summary Test biginteger constructor with i18n string + */ + +import java.math.*; + +/** + * This class tests to see if creating a biginteger with an + * unicode japanese zero and one succeeds + * + */ +public class UnicodeConstructor { + + public static void main(String args[]) { + + try { + // the code for japanese zero + BigInteger b1 = new BigInteger("\uff10"); + System.err.println(b1.toString()); + + // Japanese 1010 + BigInteger b2 = new BigInteger("\uff11\uff10\uff11\uff10"); + System.err.println(b2.toString()); + } + catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException( + "BigInteger is not accepting unicode initializers."); + } + + } + +} diff --git a/jdk/test/java/math/RoundingMode/RoundingModeTests.java b/jdk/test/java/math/RoundingMode/RoundingModeTests.java new file mode 100644 index 00000000000..03fd5e7ac80 --- /dev/null +++ b/jdk/test/java/math/RoundingMode/RoundingModeTests.java @@ -0,0 +1,85 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4851776 4891522 4905335 + * @summary Basic tests for the RoundingMode class. + * @author Joseph D. Darcy + * @compile -source 1.5 RoundingModeTests.java + * @run main RoundingModeTests + */ + +import java.math.RoundingMode; +import java.math.BigDecimal; + +public class RoundingModeTests { + public static void main(String [] argv) { + + // For each member of the family, make sure + // rm == valueOf(rm.toString()) + + for(RoundingMode rm: RoundingMode.values()) { + if (rm != RoundingMode.valueOf(rm.toString())) { + throw new RuntimeException("Bad roundtrip conversion of " + + rm.toString()); + } + } + + // Test that mapping of old integers to new values is correct + if (RoundingMode.valueOf(BigDecimal.ROUND_CEILING) != + RoundingMode.CEILING) { + throw new RuntimeException("Bad mapping for ROUND_CEILING"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_DOWN) != + RoundingMode.DOWN) { + throw new RuntimeException("Bad mapping for ROUND_DOWN"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_FLOOR) != + RoundingMode.FLOOR) { + throw new RuntimeException("Bad mapping for ROUND_FLOOR"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_DOWN) != + RoundingMode.HALF_DOWN) { + throw new RuntimeException("Bad mapping for ROUND_HALF_DOWN"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_EVEN) != + RoundingMode.HALF_EVEN) { + throw new RuntimeException("Bad mapping for ROUND_HALF_EVEN"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_HALF_UP) != + RoundingMode.HALF_UP) { + throw new RuntimeException("Bad mapping for ROUND_HALF_UP"); + } + + if (RoundingMode.valueOf(BigDecimal.ROUND_UNNECESSARY) != + RoundingMode.UNNECESSARY) { + throw new RuntimeException("Bad mapping for ROUND_UNNECESARY"); + } + } +} diff --git a/jdk/test/java/net/CookieHandler/B6791927.java b/jdk/test/java/net/CookieHandler/B6791927.java new file mode 100644 index 00000000000..f1e1f7f3991 --- /dev/null +++ b/jdk/test/java/net/CookieHandler/B6791927.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6791927 + * @summary Wrong Locale in HttpCookie::expiryDate2DeltaSeconds + */ + +import java.net.*; +import java.util.List; +import java.util.Locale; + +public class B6791927 { + public static final void main( String[] aaParamters ) throws Exception{ + // Forces a non US locale + Locale.setDefault(Locale.FRANCE); + List cookies = HttpCookie.parse("set-cookie: CUSTOMER=WILE_E_COYOTE; expires=Wednesday, 09-Nov-2019 23:12:40 GMT"); + if (cookies == null || cookies.isEmpty()) { + throw new RuntimeException("No cookie found"); + } + for (HttpCookie c : cookies) { + if (c.getMaxAge() == 0) { + throw new RuntimeException("Expiration date shouldn't be 0"); + } + } + } +} diff --git a/jdk/test/java/net/CookieHandler/TestHttpCookie.java b/jdk/test/java/net/CookieHandler/TestHttpCookie.java index 43d5484e27c..f1f89f8daab 100644 --- a/jdk/test/java/net/CookieHandler/TestHttpCookie.java +++ b/jdk/test/java/net/CookieHandler/TestHttpCookie.java @@ -24,7 +24,7 @@ /** * @test * @summary Unit test for java.net.HttpCookie - * @bug 6244040 6277796 6277801 6277808 6294071 6692802 + * @bug 6244040 6277796 6277801 6277808 6294071 6692802 6790677 * @author Edward Wang */ @@ -278,10 +278,6 @@ public class TestHttpCookie { .c("this is a coyote").cu("http://www.coyote.org").dsc(true) .d(".coyote.org").a(3600).port("80"); - // illegal characters in set-cookie header - test("Set-Cookie2:Customer=;Version#=\"1\";Path=&\"/acme\"") - .nil(); - // empty set-cookie string test("").nil(); @@ -311,6 +307,9 @@ public class TestHttpCookie { test("Set-Cookie2:C1=\"V1\";Domain=\".sun1.com\";path=\"/www1\";Max-Age=\"100\",C2=\"V2\";Domain=\".sun2.com\";path=\"/www2\";Max-Age=\"200\"") .n(0, "C1").v(0, "V1").p(0, "/www1").a(0, 100).d(0, ".sun1.com") .n(1, "C2").v(1, "V2").p(1, "/www2").a(1, 200).d(1, ".sun2.com"); + + // Bug 6790677: Should ignore bogus attributes + test("Set-Cookie2:C1=\"V1\";foobar").n(0, "C1").v(0, "V1"); } static void netscape() { diff --git a/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java b/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java new file mode 100644 index 00000000000..b0fdd577b42 --- /dev/null +++ b/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java @@ -0,0 +1,246 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 4167874 + * @library ../../../../com/sun/net/httpserver + * @build FileServerHandler + * @run shell build.sh + * @run main/othervm CloseTest + * @summary URL-downloaded jar files can consume all available file descriptors + */ + +import java.io.*; +import java.net.*; +import java.lang.reflect.*; +import java.util.concurrent.*; +import com.sun.net.httpserver.*; + +public class CloseTest { + + static void copyFile (String src, String dst) { + copyFile (new File(src), new File(dst)); + } + + static void copyDir (String src, String dst) { + copyDir (new File(src), new File(dst)); + } + + static void copyFile (File src, File dst) { + try { + if (!src.isFile()) { + throw new RuntimeException ("File not found: " + src.toString()); + } + dst.delete(); + dst.createNewFile(); + FileInputStream i = new FileInputStream (src); + FileOutputStream o = new FileOutputStream (dst); + byte[] buf = new byte [1024]; + int count; + while ((count=i.read(buf)) >= 0) { + o.write (buf, 0, count); + } + i.close(); + o.close(); + } catch (IOException e) { + throw new RuntimeException (e); + } + } + + static void rm_minus_rf (File path) { + if (!path.exists()) { + return; + } + if (path.isFile()) { + if (!path.delete()) { + throw new RuntimeException ("Could not delete " + path); + } + } else if (path.isDirectory ()) { + String[] names = path.list(); + File[] files = path.listFiles(); + for (int i=0; i result = listener.accept(); + + // shutdown group + group.shutdown(); + if (!group.isShutdown()) + throw new RuntimeException("Group should be shutdown"); + + // attempt to create another channel + try { + AsynchronousSocketChannel.open(group); + throw new RuntimeException("ShutdownChannelGroupException expected"); + } catch (ShutdownChannelGroupException x) { + } + try { + AsynchronousServerSocketChannel.open(group); + throw new RuntimeException("ShutdownChannelGroupException expected"); + } catch (ShutdownChannelGroupException x) { + } + + // attempt to create another channel by connecting. This should cause + // the accept operation to fail. + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)listener.getLocalAddress()).getPort(); + InetSocketAddress isa = new InetSocketAddress(lh, port); + ch.connect(isa).get(); + try { + result.get(); + throw new RuntimeException("Connection was accepted"); + } catch (ExecutionException x) { + Throwable cause = x.getCause(); + if (!(cause instanceof IOException)) + throw new RuntimeException("Cause should be IOException"); + cause = cause.getCause(); + if (!(cause instanceof ShutdownChannelGroupException)) + throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); + } + + // initiate another accept even though channel group is shutdown. + Future res = listener.accept(); + try { + res.get(3, TimeUnit.SECONDS); + throw new RuntimeException("TimeoutException expected"); + } catch (TimeoutException x) { + } + // connect to the listener which should cause the accept to complete + AsynchronousSocketChannel.open().connect(isa); + try { + res.get(); + throw new RuntimeException("Connection was accepted"); + } catch (ExecutionException x) { + Throwable cause = x.getCause(); + if (!(cause instanceof IOException)) + throw new RuntimeException("Cause should be IOException"); + cause = cause.getCause(); + if (!(cause instanceof ShutdownChannelGroupException)) + throw new RuntimeException("IOException cause should be ShutdownChannelGroupException"); + } + + // group should *not* terminate as channels are open + boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS); + if (terminated) + throw new RuntimeException("Group should not have terminated"); + + // close channel; group should terminate quickly + ch.close(); + listener.close(); + terminated = group.awaitTermination(3, TimeUnit.SECONDS); + if (!terminated) + throw new RuntimeException("Group should have terminated"); + } + + static void miscTests() throws Exception { + System.out.println("-- miscellenous tests --"); + try { + AsynchronousChannelGroup.withFixedThreadPool(1, null); + throw new RuntimeException("NPE expected"); + } catch (NullPointerException x) { + } + try { + AsynchronousChannelGroup.withFixedThreadPool(0, threadFactory); + throw new RuntimeException("IAE expected"); + } catch (IllegalArgumentException e) { + } + try { + AsynchronousChannelGroup.withCachedThreadPool(null, 0); + throw new RuntimeException("NPE expected"); + } catch (NullPointerException x) { + } + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java new file mode 100644 index 00000000000..b116245ceaf --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java @@ -0,0 +1,140 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousChannelGroup + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.util.concurrent.*; +import java.io.IOException; + +/** + * This test verifies that a channel or channel group can be closed from a + * completion handler when there are no threads available to handle I/O events. + */ + +public class GroupOfOne { + + public static void main(String[] args) throws Exception { + // create listener to accept connections + final AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + listener.accept(null, new CompletionHandler() { + public void completed(AsynchronousSocketChannel ch, Void att) { + listener.accept(null, this); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); + + test(sa, true, false); + test(sa, false, true); + test(sa, true, true); + } + + static void test(SocketAddress sa, + final boolean closeChannel, + final boolean shutdownGroup) + throws Exception + { + // group with 1 thread + final AsynchronousChannelGroup group = AsynchronousChannelGroup + .withFixedThreadPool(1, new ThreadFactory() { + @Override + public Thread newThread(final Runnable r) { + return new Thread(r); + }}); + final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); + + // the latch counts down when: + // 1. The read operation fails (expected) + // 2. the close/shutdown completes + final CountDownLatch latch = new CountDownLatch(2); + + ch.connect(sa, null, new CompletionHandler() { + public void completed(Void result, Void att) { + System.out.println("Connected"); + + // initiate I/O operation that does not complete (successfully) + ByteBuffer buf = ByteBuffer.allocate(100); + ch.read(buf, null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + throw new RuntimeException(); + } + public void failed(Throwable exc, Void att) { + if (!(exc instanceof AsynchronousCloseException)) + throw new RuntimeException(exc); + System.out.println("Read failed (expected)"); + latch.countDown(); + } + public void cancelled(Void att) { + throw new RuntimeException(); + } + }); + + // close channel or shutdown group + try { + if (closeChannel) { + System.out.print("Close channel ..."); + ch.close(); + System.out.println(" done."); + } + if (shutdownGroup) { + System.out.print("Shutdown group ..."); + group.shutdownNow(); + System.out.println(" done."); + } + latch.countDown(); + } catch (IOException e) { + throw new RuntimeException(); + } + } + public void failed(Throwable exc, Void att) { + throw new RuntimeException(exc); + } + public void cancelled(Void att) { + throw new RuntimeException(); + } + }); + + latch.await(); + + // clean-up + group.shutdown(); + boolean terminated = group.awaitTermination(5, TimeUnit.SECONDS); + if (!terminated) + throw new RuntimeException("Group did not terminate"); + + System.out.println("TEST OKAY"); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java new file mode 100644 index 00000000000..f41c12c807f --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java @@ -0,0 +1,166 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousChannelGroup + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +/** + * Tests that the completion handler is invoked by a thread with + * the expected identity. + */ + +public class Identity { + static final Random rand = new Random(); + static final CountDownLatch done = new CountDownLatch(1); + static final AtomicBoolean failed = new AtomicBoolean(false); + + static void fail(String msg) { + failed.set(true); + done.countDown(); + throw new RuntimeException(msg); + } + + // thread-local identifies the thread + private static final ThreadLocal myGroup = + new ThreadLocal() { + @Override protected Integer initialValue() { + return Integer.valueOf(-1); + } + }; + + // creates a ThreadFactory that constructs groups with the given identity + static final ThreadFactory createThreadFactory(final int groupId) { + return new ThreadFactory() { + @Override + public Thread newThread(final Runnable r) { + Thread t = new Thread(new Runnable() { + public void run() { + myGroup.set(groupId); + r.run(); + }}); + t.setDaemon(true); + return t; + } + }; + } + + public static void main(String[] args) throws Exception { + // create listener to accept connections + final AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + listener.accept(null, new CompletionHandler() { + public void completed(final AsynchronousSocketChannel ch, Void att) { + listener.accept(null, this); + + final ByteBuffer buf = ByteBuffer.allocate(100); + ch.read(buf, null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + buf.clear(); + ch.read(buf, null, this); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); + + // create 3-10 channels, each in its own group + final int groupCount = 3 + rand.nextInt(8); + final AsynchronousSocketChannel[] channel = new AsynchronousSocketChannel[groupCount]; + for (int i=0; i() { + public void completed(Integer bytesWritten, Integer groupId) { + if (bytesWritten != 1) + fail("Expected 1 byte to be written"); + if (!myGroup.get().equals(groupId)) + fail("Handler invoked by thread with the wrong identity"); + if (writeCount.decrementAndGet() > 0) { + int id = rand.nextInt(groupCount); + channel[id].write(getBuffer(), id, this); + } else { + done.countDown(); + } + } + public void failed(Throwable exc, Integer groupId) { + fail(exc.getMessage()); + } + public void cancelled(Integer groupId) { + fail("I/O operation was cancelled"); + } + }); + + // wait until + done.await(); + if (failed.get()) + throw new RuntimeException("Test failed - see log for details"); + } + + static ByteBuffer getBuffer() { + ByteBuffer buf; + if (rand.nextBoolean()) { + buf = ByteBuffer.allocateDirect(1); + } else { + buf = ByteBuffer.allocate(1); + } + buf.put((byte)0); + buf.flip(); + return buf; + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java new file mode 100644 index 00000000000..e2c4575c72d --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java @@ -0,0 +1,50 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.concurrent.ThreadFactory; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * The "privileged" ThreadFactory used by the AsExecutor test. + */ + +public class PrivilegedThreadFactory implements ThreadFactory { + public void PrivilegedThreadPoolFactory() { + // check class is on boot class path + if (PrivilegedThreadFactory.class.getClassLoader() != null) + throw new RuntimeException("PrivilegedThreadFactory class not on boot class path"); + } + + @Override + public Thread newThread(final Runnable r) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Thread run() { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + } + }); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java new file mode 100644 index 00000000000..567321e3008 --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java @@ -0,0 +1,133 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousChannelGroup + * @build Restart + * @run main/othervm -XX:-UseVMInterruptibleIO Restart + */ + +import java.nio.channels.*; +import java.net.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import java.io.IOException; + +/** + * Exercise replacement of threads in the thread pool when completion handlers + * terminate due to errors or runtime exceptions. + */ + +public class Restart { + static final Random rand = new Random(); + + public static void main(String[] args) throws Exception { + // thread group for thread pools + final ThreadGroup tg = new ThreadGroup("test"); + + // keep track of the number of threads that terminate + final AtomicInteger exceptionCount = new AtomicInteger(0); + final Thread.UncaughtExceptionHandler ueh = + new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + exceptionCount.incrementAndGet(); + } + }; + ThreadFactory factory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(tg, r); + t.setUncaughtExceptionHandler(ueh); + return t; + } + }; + + // group with fixed thread pool + int nThreads = 1 + rand.nextInt(4); + AsynchronousChannelGroup group = + AsynchronousChannelGroup.withFixedThreadPool(nThreads, factory); + testRestart(group, 100); + group.shutdown(); + + // group with custom thread pool + ExecutorService pool = Executors.newCachedThreadPool(factory); + group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5)); + testRestart(group, 100); + group.shutdown(); + + // give time for threads to terminate + Thread.sleep(3000); + int actual = exceptionCount.get(); + if (actual != 200) + throw new RuntimeException(actual + " exceptions, expected: " + 200); + } + + static void testRestart(AsynchronousChannelGroup group, int count) + throws Exception + { + AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open(group) + .bind(new InetSocketAddress(0)); + + for (int i=0; i() { + public void completed(AsynchronousSocketChannel ch, Void att) { + try { + ch.close(); + } catch (IOException ignore) { } + + latch.countDown(); + + // throw error or runtime exception + if (rand.nextBoolean()) { + throw new Error(); + } else { + throw new RuntimeException(); + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // establish loopback connection which should cause completion + // handler to be invoked. + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + InetAddress lh = InetAddress.getLocalHost(); + ch.connect(new InetSocketAddress(lh, port)).get(); + ch.close(); + + // wait for handler to be invoked + latch.await(); + } + + // clean-up + listener.close(); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java new file mode 100644 index 00000000000..f615c3c5063 --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java @@ -0,0 +1,120 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousChannelGroup + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.util.concurrent.*; +import java.io.IOException; + +public class Unbounded { + // number of concurrent completion handlers + static final int CONCURRENCY_COUNT = 512; + + public static void main(String[] args) throws Exception { + // all accepted connections are added to a queue + final ArrayBlockingQueue queue = + new ArrayBlockingQueue(CONCURRENCY_COUNT); + + // create listener to accept connections + final AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + listener.accept(null, new CompletionHandler() { + public void completed(AsynchronousSocketChannel ch, Void att) { + queue.add(ch); + listener.accept(null, this); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + System.out.println("Listener created."); + + // establish lots of connections + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port); + AsynchronousSocketChannel[] channels = + new AsynchronousSocketChannel[CONCURRENCY_COUNT]; + for (int i=0; i= 3) + throw x; + Thread.sleep(50); + } + } + } + System.out.println("All connection established."); + + // the barrier where all threads (plus the main thread) wait + final CyclicBarrier barrier = new CyclicBarrier(CONCURRENCY_COUNT+1); + + // initiate a read operation on each channel. + for (int i=0; i() { + public void completed(Integer bytesRead, AsynchronousSocketChannel ch) { + try { + ch.close(); + barrier.await(); + } catch (Exception x) { + throw new AssertionError(x); + } + } + public void failed(Throwable exc, AsynchronousSocketChannel ch) { + } + public void cancelled(AsynchronousSocketChannel ch) { + } + }); + } + System.out.println("All read operations outstanding."); + + // write data to each of the accepted connections + int remaining = CONCURRENCY_COUNT; + while (remaining > 0) { + AsynchronousSocketChannel ch = queue.take(); + ch.write(ByteBuffer.wrap("welcome".getBytes())).get(); + ch.close(); + remaining--; + } + + // wait for all threads to reach the barrier + System.out.println("Waiting for all threads to reach barrier"); + barrier.await(); + listener.close(); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh b/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh new file mode 100644 index 00000000000..97f4f968a76 --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh @@ -0,0 +1,52 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4607272 +# @summary Unit test for AsynchronousChannelGrou#execute +# @build AsExecutor PrivilegedThreadFactory Attack +# @run shell run_any_task.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java + JAR=jar +else + JAVA="${TESTJAVA}/bin/java" + JAR="${TESTJAVA}/bin/jar" +fi + +echo "Creating JAR file ..." +$JAR -cf "${TESTCLASSES}/Privileged.jar" \ + -C "${TESTCLASSES}" PrivilegedThreadFactory.class \ + -C "${TESTCLASSES}" PrivilegedThreadFactory\$1.class \ + -C "${TESTCLASSES}" Attack.class + +echo "Running test ..." +$JAVA -XX:-UseVMInterruptibleIO \ + -Xbootclasspath/a:"${TESTCLASSES}/Privileged.jar" \ + -classpath "${TESTCLASSES}" \ + AsExecutor diff --git a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java new file mode 100644 index 00000000000..5ed3d83a90d --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java @@ -0,0 +1,448 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4527345 + * @summary Unit test for AsynchronousDatagramChannel + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.net.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +public class Basic { + + public static void main(String[] args) throws Exception { + doReceiveTests(); + doReadTests(); + doSendTests(); + doWriteTests(); + doCancelTests(); + doMulticastTests(); + } + + // basic receive tests + static void doReceiveTests() throws Exception { + final byte[] msg = "hello".getBytes(); + + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open() + .bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); + InetAddress rh = InetAddress.getLocalHost(); + final SocketAddress sa = new InetSocketAddress(rh, port); + + DatagramChannel sender = DatagramChannel.open(); + ByteBuffer dst = ByteBuffer.allocateDirect(100); + + // Test: datagram packet received immediately + sender.send(ByteBuffer.wrap(msg), sa); + dst.clear(); + ch.receive(dst).get(1, TimeUnit.SECONDS); + if (dst.flip().remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes read"); + + // Test: datagram packet not received immediately + dst.clear(); + final CountDownLatch latch = new CountDownLatch(1); + ch.receive(dst, null, new CompletionHandler() { + public void completed(SocketAddress source, Void att) { + latch.countDown(); + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + Thread.sleep(2000); + sender.send(ByteBuffer.wrap(msg), sa); + latch.await(2, TimeUnit.SECONDS); // wait for completion handler + + // Test: timeout + dst.clear(); + final AtomicReference exception = new AtomicReference(); + ch.receive(dst, 2, TimeUnit.SECONDS, null, new CompletionHandler() { + public void completed(SocketAddress source, Void att) { + } + public void failed (Throwable exc, Void att) { + exception.set(exc); + } + public void cancelled(Void att) { + } + }); + Throwable result; + while ((result = exception.get()) == null) { + Thread.sleep(100); + } + if (!(result instanceof InterruptedByTimeoutException)) + throw new RuntimeException("InterruptedByTimeoutException expected"); + + // AsynchronousCloseException + dst = ByteBuffer.allocateDirect(100); + exception.set(null); + ch.receive(dst, null, new CompletionHandler() { + public void completed(SocketAddress source, Void att) { + } + public void failed (Throwable exc, Void att) { + exception.set(exc); + } + public void cancelled(Void att) { + } + }); + ch.close(); + while ((result = exception.get()) == null) { + Thread.sleep(100); + } + if (!(result instanceof AsynchronousCloseException)) + throw new RuntimeException("AsynchronousCloseException expected"); + + // done + sender.close(); + } + + // basic read tests + static void doReadTests() throws Exception { + final byte[] msg = "hello".getBytes(); + + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open() + .bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); + InetAddress lh = InetAddress.getLocalHost(); + final SocketAddress sa = new InetSocketAddress(lh, port); + + DatagramChannel sender = DatagramChannel.open(); + ByteBuffer dst = ByteBuffer.allocateDirect(100); + + // Test: not connected + try { + ch.read(dst); + throw new RuntimeException("NotYetConnectedException expected"); + } catch (NotYetConnectedException e) { + } + + // connect the channel + sender.bind(new InetSocketAddress(0)); + ch.connect(new InetSocketAddress(lh, + ((InetSocketAddress)(sender.getLocalAddress())).getPort())); + + // Test: datagram packet received immediately + sender.send(ByteBuffer.wrap(msg), sa); + dst.clear(); + ch.read(dst).get(1, TimeUnit.SECONDS); + if (dst.flip().remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes read"); + + // Test: datagram packet not received immediately + dst.clear(); + final CountDownLatch l1 = new CountDownLatch(1); + ch.read(dst, null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + l1.countDown(); + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + Thread.sleep(2000); + sender.send(ByteBuffer.wrap(msg), sa); + l1.await(2, TimeUnit.SECONDS); + + // Test: timeout + dst.clear(); + final AtomicReference exception = new AtomicReference(); + ch.read(dst, 2, TimeUnit.SECONDS, null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + } + public void failed (Throwable exc, Void att) { + exception.set(exc); + } + public void cancelled(Void att) { + } + }); + Throwable result; + while ((result = exception.get()) == null) { + Thread.sleep(100); + } + if (!(result instanceof InterruptedByTimeoutException)) + throw new RuntimeException("InterruptedByTimeoutException expected"); + + // AsynchronousCloseException + dst.clear(); + exception.set(null); + ch.read(dst, null, new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + } + public void failed (Throwable exc, Void att) { + exception.set(exc); + } + public void cancelled(Void att) { + } + }); + ch.close(); + while ((result = exception.get()) == null) { + Thread.sleep(100); + } + if (!(result instanceof AsynchronousCloseException)) + throw new RuntimeException("AsynchronousCloseException expected"); + + // done + sender.close(); + } + + // basic send tests + static void doSendTests() throws Exception { + final byte[] msg = "hello".getBytes(); + + DatagramChannel reader = DatagramChannel.open() + .bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort(); + InetAddress rh = InetAddress.getLocalHost(); + SocketAddress sa = new InetSocketAddress(rh, port); + + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open(); + + // Test: send datagram packet to reader + int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get(); + if (bytesSent != msg.length) + throw new RuntimeException("Unexpected number of bytes sent"); + + // check received + ByteBuffer dst = ByteBuffer.allocateDirect(100); + reader.receive(dst); + dst.flip(); + if (dst.remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + + // Test: send datagram packet to reader and check completion handler + // is invoked + final CountDownLatch l2 = new CountDownLatch(1); + ch.send(ByteBuffer.wrap(msg), sa, null, new CompletionHandler() { + public void completed(Integer bytesSent, Void att) { + if (bytesSent != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + l2.countDown(); + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + l2.await(5, TimeUnit.SECONDS); + + // check received + dst.clear(); + reader.receive(dst); + dst.flip(); + if (dst.remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + + // Test: check that failed method is invoked + ch.close(); + final CountDownLatch l3 = new CountDownLatch(1); + ch.send(ByteBuffer.wrap(msg), sa, null, new CompletionHandler() { + public void completed(Integer bytesSent, Void att) { + throw new RuntimeException("completed method invoked"); + } + public void failed (Throwable exc, Void att) { + if (exc instanceof ClosedChannelException) { + l3.countDown(); + } else { + throw new RuntimeException(exc); + } + } + public void cancelled(Void att) { + } + }); + l3.await(5, TimeUnit.SECONDS); + + // done + reader.close(); + } + + // basic write tests + static void doWriteTests() throws Exception { + final byte[] msg = "hello".getBytes(); + + DatagramChannel reader = DatagramChannel.open() + .bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort(); + InetAddress rh = InetAddress.getLocalHost(); + SocketAddress sa = new InetSocketAddress(rh, port); + + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open(); + + // Test: unconnected + try { + ch.write(ByteBuffer.wrap(msg)).get(); + throw new RuntimeException("NotYetConnectedException expected"); + } catch (NotYetConnectedException e) { + } + + // Test: connect, and write datagram + ch.connect(sa); + int bytesSent = ch.write(ByteBuffer.wrap(msg)).get(); + if (bytesSent != msg.length) + throw new RuntimeException("Unexpected number of bytes sent"); + + // check received + ByteBuffer dst = ByteBuffer.allocateDirect(100); + reader.receive(dst); + dst.flip(); + if (dst.remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + + // Test: write datagram and check completion handler is invoked + final CountDownLatch l2 = new CountDownLatch(1); + ch.write(ByteBuffer.wrap(msg), null, new CompletionHandler() { + public void completed(Integer bytesSent, Void att) { + if (bytesSent != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + l2.countDown(); + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + l2.await(5, TimeUnit.SECONDS); + + // check received + dst.clear(); + reader.receive(dst); + dst.flip(); + if (dst.remaining() != msg.length) + throw new RuntimeException("Unexpected number of bytes received"); + + // done + ch.close(); + reader.close(); + } + + static void cancelAndCheck(Future result, CountDownLatch latch) + throws InterruptedException + { + boolean cancelled = result.cancel(false); + if (!cancelled) + throw new RuntimeException("Not cancelled"); + if (!result.isDone()) + throw new RuntimeException("Should be done"); + try { + result.get(); + throw new RuntimeException("Result not expected"); + } catch (CancellationException e) { + // expected + } catch (ExecutionException e) { + throw new RuntimeException("Should not fail"); + } + + // make sure that completion handler is invoked + latch.await(); + } + + // basic cancel tests + static void doCancelTests() throws Exception { + InetAddress lh = InetAddress.getLocalHost(); + + // timed and non-timed receive + for (int i=0; i<2; i++) { + AsynchronousDatagramChannel ch = + AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0)); + final CountDownLatch latch = new CountDownLatch(1); + long timeout = (i == 0) ? 0L : 60L; + Future remote = ch + .receive(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, null, + new CompletionHandler() { + public void completed(SocketAddress source, Void att) { + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + latch.countDown(); + } + }); + cancelAndCheck(remote, latch); + ch.close(); + } + + // timed and non-timed read + for (int i=0; i<2; i++) { + AsynchronousDatagramChannel ch = + AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0)); + ch.connect(new InetSocketAddress(lh, + ((InetSocketAddress)(ch.getLocalAddress())).getPort())); + final CountDownLatch latch = new CountDownLatch(1); + long timeout = (i == 0) ? 0L : 60L; + Future result = ch + .read(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, null, + new CompletionHandler() { + public void completed(Integer bytesRead, Void att) { + } + public void failed (Throwable exc, Void att) { + } + public void cancelled(Void att) { + latch.countDown(); + } + }); + cancelAndCheck(result, latch); + ch.close(); + } + } + + // basic multicast test + static void doMulticastTests() throws Exception { + final byte[] msg = "hello".getBytes(); + + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel + .open(StandardProtocolFamily.INET, null) + .setOption(StandardSocketOption.SO_REUSEADDR, true) + .bind(new InetSocketAddress(0)); + + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); + + // join group + InetAddress group = InetAddress.getByName("225.4.5.6"); + NetworkInterface interf = NetworkInterface.getByInetAddress(lh); + MembershipKey key = ch.join(group, interf); + + // check key + if (key.channel() != ch) + throw new RuntimeException("Not the expected channel"); + + // send message to group + DatagramChannel sender = DatagramChannel.open(); + sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port)); + sender.close(); + + // check message received + ByteBuffer dst = ByteBuffer.allocate(200); + SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS); + if (!((InetSocketAddress)source).getAddress().equals(lh)) + throw new RuntimeException("Unexpected source"); + + // done + ch.close(); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java new file mode 100644 index 00000000000..5ffb42c0b8b --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java @@ -0,0 +1,585 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousFileChannel + */ + +import java.nio.file.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; +import static java.nio.file.StandardOpenOption.*; + +public class Basic { + + private static final Random rand = new Random(); + + public static void main(String[] args) throws IOException { + // create temporary file + File blah = File.createTempFile("blah", null); + blah.deleteOnExit(); + + final AsynchronousFileChannel ch = AsynchronousFileChannel + .open(blah.toPath(), READ, WRITE); + + // run tests + testUsingCompletionHandlers(ch); + testUsingWaitOnResult(ch); + testLocking(ch); + testInterruptHandlerThread(ch); + + // close channel and invoke test that expects channel to be closed + ch.close(); + testClosedChannel(ch); + + // these tests open the file themselves + testCustomThreadPool(blah.toPath()); + testAsynchronousClose(blah.toPath()); + testCancel(blah.toPath()); + testTruncate(blah.toPath()); + } + + /* + * Generate buffer with random contents + * Writes buffer to file using a CompletionHandler to consume the result + * of each write operation + * Reads file to EOF to a new buffer using a CompletionHandler to consume + * the result of each read operation + * Compares buffer contents + */ + static void testUsingCompletionHandlers(AsynchronousFileChannel ch) + throws IOException + { + System.out.println("testUsingCompletionHandlers"); + + ch.truncate(0L); + + // generate buffer with random elements and write it to file + ByteBuffer src = genBuffer(); + writeFully(ch, src, 0L); + + // read to EOF or buffer is full + ByteBuffer dst = (rand.nextBoolean()) ? + ByteBuffer.allocateDirect(src.capacity()) : + ByteBuffer.allocate(src.capacity()); + readAll(ch, dst, 0L); + + // check buffers are the same + src.flip(); + dst.flip(); + if (!src.equals(dst)) { + throw new RuntimeException("Contents differ"); + } + } + + /* + * Generate buffer with random contents + * Writes buffer to file, invoking the Future's get method to wait for + * each write operation to complete + * Reads file to EOF to a new buffer, invoking the Future's get method to + * wait for each write operation to complete + * Compares buffer contents + */ + static void testUsingWaitOnResult(AsynchronousFileChannel ch) + throws IOException + { + System.out.println("testUsingWaitOnResult"); + + ch.truncate(0L); + + // generate buffer + ByteBuffer src = genBuffer(); + + // write buffer completely to file + long position = 0L; + while (src.hasRemaining()) { + Future result = ch.write(src, position); + try { + int n = result.get(); + // update position + position += n; + } catch (ExecutionException x) { + throw new RuntimeException(x.getCause()); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + } + + // read file into new buffer + ByteBuffer dst = (rand.nextBoolean()) ? + ByteBuffer.allocateDirect(src.capacity()) : + ByteBuffer.allocate(src.capacity()); + position = 0L; + int n; + do { + Future result = ch.read(dst, position); + try { + n = result.get(); + + // update position + if (n > 0) position += n; + } catch (ExecutionException x) { + throw new RuntimeException(x.getCause()); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + } while (n > 0); + + // check buffers are the same + src.flip(); + dst.flip(); + if (!src.equals(dst)) { + throw new RuntimeException("Contents differ"); + } + } + + // exercise lock methods + static void testLocking(AsynchronousFileChannel ch) + throws IOException + { + System.out.println("testLocking"); + + // test 1 - acquire lock and check that tryLock throws + // OverlappingFileLockException + FileLock fl; + try { + fl = ch.lock().get(); + } catch (ExecutionException x) { + throw new RuntimeException(x); + } catch (InterruptedException x) { + throw new RuntimeException("Should not be interrupted"); + } + if (!fl.acquiredBy().equals(ch)) + throw new RuntimeException("FileLock#acquiredBy returned incorrect channel"); + try { + ch.tryLock(); + throw new RuntimeException("OverlappingFileLockException expected"); + } catch (OverlappingFileLockException x) { + } + fl.release(); + + // test 2 - acquire try and check that lock throws OverlappingFileLockException + fl = ch.tryLock(); + if (fl == null) + throw new RuntimeException("Unable to acquire lock"); + try { + ch.lock(null, new CompletionHandler () { + public void completed(FileLock result, Void att) { + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + throw new RuntimeException("OverlappingFileLockException expected"); + } catch (OverlappingFileLockException x) { + } + fl.release(); + } + + // interrupt should not close channel + static void testInterruptHandlerThread(final AsynchronousFileChannel ch) { + System.out.println("testInterruptHandlerThread"); + + ByteBuffer buf = ByteBuffer.allocateDirect(100); + final CountDownLatch latch = new CountDownLatch(1); + + ch.read(buf, 0L, null, new CompletionHandler() { + public void completed(Integer result, Void att) { + try { + Thread.currentThread().interrupt(); + long size = ch.size(); + latch.countDown(); + } catch (IOException x) { + x.printStackTrace(); + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // wait for handler to complete + await(latch); + } + + // invoke method on closed channel + static void testClosedChannel(AsynchronousFileChannel ch) { + System.out.println("testClosedChannel"); + + if (ch.isOpen()) + throw new RuntimeException("Channel should be closed"); + + ByteBuffer buf = ByteBuffer.allocateDirect(100); + + // check read fails with ClosedChannelException + try { + ch.read(buf, 0L).get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } catch (InterruptedException x) { + } + + // check write fails with ClosedChannelException + try { + ch.write(buf, 0L).get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } catch (InterruptedException x) { + } + + // check lock fails with ClosedChannelException + try { + ch.lock().get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } catch (InterruptedException x) { + } + } + + + // exercise custom thread pool + static void testCustomThreadPool(Path file) throws IOException { + System.out.println("testCustomThreadPool"); + + // records threads that are created + final List threads = new ArrayList(); + + ThreadFactory threadFactory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setDaemon(true); + synchronized (threads) { + threads.add(t); + } + return t; + } + }; + + // exercise tests with varied number of threads + for (int nThreads=1; nThreads<=5; nThreads++) { + synchronized (threads) { + threads.clear(); + } + ExecutorService executor = Executors.newFixedThreadPool(nThreads, threadFactory); + Set opts = EnumSet.of(WRITE); + AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor); + try { + for (int i=0; i<10; i++) { + // do I/O operation to see which thread invokes the completion handler + final AtomicReference invoker = new AtomicReference(); + final CountDownLatch latch = new CountDownLatch(1); + + ch.write(genBuffer(), 0L, null, new CompletionHandler() { + public void completed(Integer result, Void att) { + invoker.set(Thread.currentThread()); + latch.countDown(); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + await(latch); + + // check invoker + boolean found = false; + synchronized (threads) { + for (Thread t: threads) { + if (t == invoker.get()) { + found = true; + break; + } + } + } + if (!found) + throw new RuntimeException("Invoker thread not found"); + } + } finally { + ch.close(); + } + } + } + + // exercise asynchronous close + static void testAsynchronousClose(Path file) throws IOException { + System.out.println("testAsynchronousClose"); + + // create file + AsynchronousFileChannel ch = AsynchronousFileChannel + .open(file, WRITE, TRUNCATE_EXISTING); + long size = 0L; + do { + ByteBuffer buf = genBuffer(); + int n = buf.remaining(); + writeFully(ch, buf, size); + size += n; + } while (size < (50L * 1024L * 1024L)); + + ch.close(); + + ch = AsynchronousFileChannel.open(file, WRITE, SYNC); + + // randomize number of writers, buffer size, and positions + + int nwriters = 1 + rand.nextInt(8); + ByteBuffer[] buf = new ByteBuffer[nwriters]; + long[] position = new long[nwriters]; + for (int i=0; i res = ch.write(genBuffer(), 0L, null, + new CompletionHandler() { + public void completed(Integer result, Void att) { + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + latch.countDown(); + } + }); + + // cancel operation + boolean cancelled = res.cancel(mayInterruptIfRunning); + + // check post-conditions + if (!res.isDone()) + throw new RuntimeException("isDone should return true"); + if (res.isCancelled() != cancelled) + throw new RuntimeException("isCancelled not consistent"); + try { + res.get(); + if (!cancelled) + throw new RuntimeException("CancellationException expected"); + } catch (CancellationException x) { + // expected + } catch (ExecutionException x) { + throw new RuntimeException(x); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + try { + res.get(1, TimeUnit.SECONDS); + throw new RuntimeException("CancellationException expected"); + } catch (CancellationException x) { + // expected + } catch (ExecutionException x) { + throw new RuntimeException(x); + } catch (TimeoutException x) { + throw new RuntimeException(x); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + + // check that cancelled method is invoked + if (cancelled) + await(latch); + + ch.close(); + } + } + + // exercise truncate method + static void testTruncate(Path file) throws IOException { + System.out.println("testTruncate"); + + // basic tests + AsynchronousFileChannel ch = AsynchronousFileChannel + .open(file, CREATE, WRITE, TRUNCATE_EXISTING); + try { + writeFully(ch, genBuffer(), 0L); + long size = ch.size(); + + // attempt to truncate to a size greater than the current size + if (ch.truncate(size + 1L).size() != size) + throw new RuntimeException("Unexpected size after truncation"); + + // truncate file + if (ch.truncate(size - 1L).size() != (size - 1L)) + throw new RuntimeException("Unexpected size after truncation"); + + // invalid size + try { + ch.truncate(-1L); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException e) { } + + } finally { + ch.close(); + } + + // channel is closed + try { + ch.truncate(0L); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ClosedChannelException e) { } + + // channel is read-only + ch = AsynchronousFileChannel.open(file, READ); + try { + try { + ch.truncate(0L); + throw new RuntimeException("NonWritableChannelException expected"); + } catch (NonWritableChannelException e) { } + } finally { + ch.close(); + } + } + + // returns ByteBuffer with random bytes + static ByteBuffer genBuffer() { + int size = 1024 + rand.nextInt(16000); + byte[] buf = new byte[size]; + boolean useDirect = rand.nextBoolean(); + if (useDirect) { + ByteBuffer bb = ByteBuffer.allocateDirect(buf.length); + bb.put(buf); + bb.flip(); + return bb; + } else { + return ByteBuffer.wrap(buf); + } + } + + // writes all remaining bytes in the buffer to the given channel at the + // given position + static void writeFully(final AsynchronousFileChannel ch, + final ByteBuffer src, + long position) + { + final CountDownLatch latch = new CountDownLatch(1); + + // use position as attachment + ch.write(src, position, position, new CompletionHandler() { + public void completed(Integer result, Long position) { + int n = result; + if (src.hasRemaining()) { + long p = position + n; + ch.write(src, p, p, this); + } else { + latch.countDown(); + } + } + public void failed(Throwable exc, Long position) { + } + public void cancelled(Long position) { + } + }); + + // wait for writes to complete + await(latch); + } + + static void readAll(final AsynchronousFileChannel ch, + final ByteBuffer dst, + long position) + { + final CountDownLatch latch = new CountDownLatch(1); + + // use position as attachment + ch.read(dst, position, position, new CompletionHandler() { + public void completed(Integer result, Long position) { + int n = result; + if (n > 0) { + long p = position + n; + ch.read(dst, p, p, this); + } else { + latch.countDown(); + } + } + public void failed(Throwable exc, Long position) { + } + public void cancelled(Long position) { + } + }); + + // wait for reads to complete + await(latch); + } + + static void await(CountDownLatch latch) { + // wait until done + boolean done = false; + while (!done) { + try { + latch.await(); + done = true; + } catch (InterruptedException x) { } + } + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java b/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java new file mode 100644 index 00000000000..9f9025dd232 --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java @@ -0,0 +1,67 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for java.nio.channels.AsynchronousFileChannel + * @build CustomThreadPool MyThreadFactory + * @run main/othervm -Djava.nio.channels.DefaultThreadPool.threadFactory=MyThreadFactory CustomThreadPool + */ + +import java.io.File; +import static java.nio.file.StandardOpenOption.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.util.concurrent.atomic.AtomicReference; + +public class CustomThreadPool { + + public static void main(String[] args) throws Exception { + File blah = File.createTempFile("blah", null); + blah.deleteOnExit(); + AsynchronousFileChannel ch = + AsynchronousFileChannel.open(blah.toPath(), READ, WRITE); + ByteBuffer src = ByteBuffer.wrap("Scooby Snacks".getBytes()); + + final AtomicReference invoker = new AtomicReference(); + ch.write(src, 0, invoker, + new CompletionHandler>() { + public void completed(Integer result, AtomicReference invoker) { + invoker.set(Thread.currentThread()); + } + public void failed(Throwable exc, AtomicReference invoker) { + } + public void cancelled(AtomicReference invoker) { + } + }); + Thread t; + while ((t = invoker.get()) == null) { + Thread.sleep(100); + } + ch.close(); + + // check handler was run by known thread + if (!MyThreadFactory.created(t)) + throw new RuntimeException("Handler invoked by unknown thread"); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java new file mode 100644 index 00000000000..38c0f7d0c6e --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java @@ -0,0 +1,340 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousFileChannel#lock method + */ + +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.channels.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Random; +import java.util.concurrent.*; + +public class Lock { + + static final Random rand = new Random(); + + public static void main(String[] args) throws Exception { + if (args.length > 0 && args[0].equals("-lockslave")) { + int port = Integer.parseInt(args[1]); + runLockSlave(port); + System.exit(0); + } + + LockSlaveMirror slave = startLockSlave(); + try { + + // create temporary file + File blah = File.createTempFile("blah", null); + blah.deleteOnExit(); + + testLockProtocol(blah, slave); + testAsyncClose(blah, slave); + + } finally { + slave.shutdown(); + } + } + + // test locking protocol + static void testLockProtocol(File file, LockSlaveMirror slave) + throws Exception + { + FileLock fl; + + // slave VM opens file and acquires exclusive lock + slave.open(file.getPath()).lock(); + + AsynchronousFileChannel ch = AsynchronousFileChannel + .open(file.toPath(), READ, WRITE); + + // this VM tries to acquire lock + // (lock should not be acquire until released by slave VM) + Future result = ch.lock(); + try { + result.get(2, TimeUnit.SECONDS); + throw new RuntimeException("Timeout expected"); + } catch (TimeoutException x) { + } + + // slave VM releases lock + slave.unlock(); + + // this VM should now acquire lock + fl = result.get(); + fl.release(); + + // slave VM acquires lock on range + slave.lock(0, 10, false); + + // this VM acquires lock on non-overlapping range + fl = ch.lock(10, 10, false, null, null).get(); + fl.release(); + + // done + ch.close(); + slave.close(); + } + + // test close of channel with outstanding lock operation + static void testAsyncClose(File file, LockSlaveMirror slave) throws Exception { + // slave VM opens file and acquires exclusive lock + slave.open(file.getPath()).lock(); + + for (int i=0; i<100; i++) { + AsynchronousFileChannel ch = AsynchronousFileChannel + .open(file.toPath(), READ, WRITE); + + // try to lock file (should not complete because file is locked by slave) + Future result = ch.lock(); + try { + result.get(rand.nextInt(100), TimeUnit.MILLISECONDS); + throw new RuntimeException("Timeout expected"); + } catch (TimeoutException x) { + } + + // close channel with lock operation outstanding + ch.close(); + + // operation should complete with AsynchronousCloseException + try { + result.get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof AsynchronousCloseException)) { + x.getCause().printStackTrace(); + throw new RuntimeException("AsynchronousCloseException expected"); + } + } + } + + slave.close(); + } + + // starts a "lock slave" in another process, returning a mirror object to + // control the slave + static LockSlaveMirror startLockSlave() throws Exception { + ServerSocketChannel ssc = ServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); + + String sep = FileSystems.getDefault().getSeparator(); + + String command = System.getProperty("java.home") + + sep + "bin" + sep + "java Lock -lockslave " + port; + Process p = Runtime.getRuntime().exec(command); + IOHandler.handle(p.getInputStream()); + IOHandler.handle(p.getErrorStream()); + + // wait for slave to connect + SocketChannel sc = ssc.accept(); + return new LockSlaveMirror(sc); + } + + // commands that the slave understands + static final String OPEN_CMD = "open"; + static final String CLOSE_CMD = "close"; + static final String LOCK_CMD = "lock"; + static final String UNLOCK_CMD = "unlock"; + static final char TERMINATOR = ';'; + + // provides a proxy to a "lock slave" + static class LockSlaveMirror { + private final SocketChannel sc; + + LockSlaveMirror(SocketChannel sc) { + this.sc = sc; + } + + private void sendCommand(String cmd, String... params) + throws IOException + { + for (String s: params) { + cmd += " " + s; + } + cmd += TERMINATOR; + + ByteBuffer buf = Charset.defaultCharset().encode(cmd); + while (buf.hasRemaining()) { + sc.write(buf); + } + + // wait for ack + buf = ByteBuffer.allocate(1); + int n = sc.read(buf); + if (n != 1) + throw new RuntimeException("Reply expected"); + if (buf.get(0) != TERMINATOR) + throw new RuntimeException("Terminated expected"); + } + + LockSlaveMirror open(String file) throws IOException { + sendCommand(OPEN_CMD, file); + return this; + } + + void close() throws IOException { + sendCommand(CLOSE_CMD); + } + + LockSlaveMirror lock() throws IOException { + sendCommand(LOCK_CMD); + return this; + } + + + LockSlaveMirror lock(long position, long size, boolean shared) + throws IOException + { + sendCommand(LOCK_CMD, position + "," + size + "," + shared); + return this; + } + + LockSlaveMirror unlock() throws IOException { + sendCommand(UNLOCK_CMD); + return this; + } + + void shutdown() throws IOException { + sc.close(); + } + } + + // Helper class to direct process output to the parent System.out + static class IOHandler implements Runnable { + private final InputStream in; + + IOHandler(InputStream in) { + this.in = in; + } + + static void handle(InputStream in) { + IOHandler handler = new IOHandler(in); + Thread thr = new Thread(handler); + thr.setDaemon(true); + thr.start(); + } + + public void run() { + try { + byte b[] = new byte[100]; + for (;;) { + int n = in.read(b); + if (n < 0) return; + for (int i=0; i threads = new HashSet(); + + static boolean created(Thread t) { + synchronized (threads) { + return threads.contains(t); + } + } + + public MyThreadFactory() { + } + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(r); + t.setDaemon(true); + synchronized (threads) { + threads.add(t); + } + return t; + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java new file mode 100644 index 00000000000..e0965fb6e74 --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -0,0 +1,136 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousServerSocketChannel + * @run main/timeout=180 Basic + */ + +import java.nio.channels.*; +import java.net.*; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +public class Basic { + + public static void main(String[] args) throws Exception { + testBind(); + testAccept(); + } + + static void testBind() throws Exception { + System.out.println("-- bind --"); + + AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open(); + if (ch.getLocalAddress() != null) + throw new RuntimeException("Local address should be 'null'"); + ch.bind(new InetSocketAddress(0), 20); + + // check local address after binding + InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress(); + if (local.getPort() == 0) + throw new RuntimeException("Unexpected port"); + if (!local.getAddress().isAnyLocalAddress()) + throw new RuntimeException("Not bound to a wildcard address"); + + // try to re-bind + try { + ch.bind(new InetSocketAddress(0)); + throw new RuntimeException("AlreadyBoundException expected"); + } catch (AlreadyBoundException x) { + } + ch.close(); + + // check ClosedChannelException + ch = AsynchronousServerSocketChannel.open(); + ch.close(); + try { + ch.bind(new InetSocketAddress(0)); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ClosedChannelException x) { + } + } + + static void testAccept() throws Exception { + System.out.println("-- accept --"); + + final AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0)); + + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + final InetSocketAddress isa = new InetSocketAddress(lh, port); + + // establish a few loopback connections + for (int i=0; i<100; i++) { + SocketChannel sc = SocketChannel.open(isa); + AsynchronousSocketChannel ch = listener.accept().get(); + sc.close(); + ch.close(); + } + + final AtomicReference exception = new AtomicReference(); + + // start accepting + listener.accept(null, new CompletionHandler() { + public void completed(AsynchronousSocketChannel ch, Void att) { + try { + ch.close(); + } catch (IOException ignore) { } + } + public void failed(Throwable exc, Void att) { + exception.set(exc); + } + public void cancelled(Void att) { + } + }); + + // check AcceptPendingException + try { + listener.accept(); + throw new RuntimeException("AcceptPendingException expected"); + } catch (AcceptPendingException x) { + } + + // asynchronous close + listener.close(); + while (exception.get() == null) + Thread.sleep(100); + if (!(exception.get() instanceof AsynchronousCloseException)) + throw new RuntimeException("AsynchronousCloseException expected"); + + // once closed when a further attemt should throw ClosedChannelException + try { + listener.accept().get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } catch (InterruptedException x) { + } + + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java new file mode 100644 index 00000000000..86c76cf1dda --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousServerServerSocketChannel + * @build WithSecurityManager + * @run main/othervm WithSecurityManager allow + * @run main/othervm WithSecurityManager deny + */ + +import java.nio.file.Paths; +import java.nio.channels.*; +import java.net.*; +import java.util.concurrent.*; + +public class WithSecurityManager { + public static void main(String[] args) throws Exception { + boolean allow = false; + String policy = (args[0].equals("allow")) ? "java.policy.allow" : + "java.policy.deny"; + + String testSrc = System.getProperty("test.src"); + if (testSrc == null) + testSrc = "."; + + System.setProperty("java.security.policy", + Paths.get(testSrc).resolve(policy).toString()); + System.setSecurityManager(new SecurityManager()); + + AsynchronousServerSocketChannel listener = + AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0)); + + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort(); + + // establish and accept connection + SocketChannel sc = SocketChannel.open(new InetSocketAddress(lh, port)); + Future result = listener.accept(); + + if (allow) { + // no security exception + result.get().close(); + } else { + try { + result.get(); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof SecurityException)) + throw new RuntimeException("SecurityException expected"); + } + } + + sc.close(); + listener.close(); + } +} diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow new file mode 100644 index 00000000000..73da4b089ec --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow @@ -0,0 +1,3 @@ +grant { + permission java.net.SocketPermission "*:1024-", "accept,connect,resolve"; +}; diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny new file mode 100644 index 00000000000..00b9cb0685d --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny @@ -0,0 +1,3 @@ +grant { + permission java.net.SocketPermission "*:1024-", "connect,resolve"; +}; diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java new file mode 100644 index 00000000000..8b140f17bbf --- /dev/null +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -0,0 +1,805 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4607272 + * @summary Unit test for AsynchronousSocketChannel + * @run main/timeout=600 Basic + */ + +import java.nio.ByteBuffer; +import java.nio.channels.*; +import static java.net.StandardSocketOption.*; +import java.net.*; +import java.util.Random; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; +import java.io.IOException; + +public class Basic { + static final Random rand = new Random(); + + public static void main(String[] args) throws Exception { + testBind(); + testSocketOptions(); + testConnect(); + testCloseWhenPending(); + testCancel(); + testRead1(); + testRead2(); + testRead3(); + testWrite1(); + testWrite2(); + testTimeout(); + testShutdown(); + } + + static class Server { + private final ServerSocketChannel ssc; + private final InetSocketAddress address; + + Server() throws IOException { + ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0)); + + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); + address = new InetSocketAddress(lh, port); + } + + InetSocketAddress address() { + return address; + } + + SocketChannel accept() throws IOException { + return ssc.accept(); + } + + void close() { + try { + ssc.close(); + } catch (IOException ignore) { } + } + + } + + static void testBind() throws Exception { + System.out.println("-- bind --"); + + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + if (ch.getLocalAddress() != null) + throw new RuntimeException("Local address should be 'null'"); + ch.bind(new InetSocketAddress(0)); + + // check local address after binding + InetSocketAddress local = (InetSocketAddress)ch.getLocalAddress(); + if (local.getPort() == 0) + throw new RuntimeException("Unexpected port"); + if (!local.getAddress().isAnyLocalAddress()) + throw new RuntimeException("Not bound to a wildcard address"); + + // try to re-bind + try { + ch.bind(new InetSocketAddress(0)); + throw new RuntimeException("AlreadyBoundException expected"); + } catch (AlreadyBoundException x) { + } + ch.close(); + + // check ClosedChannelException + ch = AsynchronousSocketChannel.open(); + ch.close(); + try { + ch.bind(new InetSocketAddress(0)); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ClosedChannelException x) { + } + } + + static void testSocketOptions() throws Exception { + System.out.println("-- socket options --"); + + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open() + .setOption(SO_RCVBUF, 128*1024) + .setOption(SO_SNDBUF, 128*1024) + .setOption(SO_REUSEADDR, true) + .bind(new InetSocketAddress(0)); + + // default values + if ((Boolean)ch.getOption(SO_KEEPALIVE)) + throw new RuntimeException("Default of SO_KEEPALIVE should be 'false'"); + if ((Boolean)ch.getOption(TCP_NODELAY)) + throw new RuntimeException("Default of TCP_NODELAY should be 'false'"); + + // set and check + if (!(Boolean)ch.setOption(SO_KEEPALIVE, true).getOption(SO_KEEPALIVE)) + throw new RuntimeException("SO_KEEPALIVE did not change"); + if (!(Boolean)ch.setOption(TCP_NODELAY, true).getOption(TCP_NODELAY)) + throw new RuntimeException("SO_KEEPALIVE did not change"); + + // read others (can't check as actual value is implementation dependent) + ch.getOption(SO_RCVBUF); + ch.getOption(SO_SNDBUF); + + ch.close(); + } + + static void testConnect() throws Exception { + System.out.println("-- connect --"); + + Server server = new Server(); + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + + // check local address + if (ch.getLocalAddress() == null) + throw new RuntimeException("Not bound to local address"); + + // check remote address + InetSocketAddress remote = (InetSocketAddress)ch.getRemoteAddress(); + if (remote.getPort() != server.address().getPort()) + throw new RuntimeException("Connected to unexpected port"); + if (!remote.getAddress().equals(server.address().getAddress())) + throw new RuntimeException("Connected to unexpected address"); + + // try to connect again + try { + ch.connect(server.address()).get(); + throw new RuntimeException("AlreadyConnectedException expected"); + } catch (AlreadyConnectedException x) { + } + ch.close(); + + // check that connect fails with ClosedChannelException) + ch = AsynchronousSocketChannel.open(); + ch.close(); + try { + ch.connect(server.address()).get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } + final AtomicReference connectException = + new AtomicReference(); + ch.connect(server.address(), null, new CompletionHandler() { + public void completed(Void result, Void att) { + } + public void failed(Throwable exc, Void att) { + connectException.set(exc); + } + public void cancelled(Void att) { + } + }); + while (connectException.get() == null) { + Thread.sleep(100); + } + if (!(connectException.get() instanceof ClosedChannelException)) + throw new RuntimeException("ClosedChannelException expected"); + + System.out.println("-- connect to non-existent host --"); + + // test failure + InetAddress badHost = InetAddress.getByName("1.2.3.4"); + if (!badHost.isReachable(10*1000)) { + + ch = AsynchronousSocketChannel.open(); + try { + ch.connect(new InetSocketAddress(badHost, 9876)).get(); + throw new RuntimeException("Connection should not be established"); + } catch (ExecutionException x) { + } + if (ch.isOpen()) + throw new RuntimeException("Channel should be closed"); + } + + server.close(); + } + + static void testCloseWhenPending() throws Exception { + System.out.println("-- asynchronous close when connecting --"); + + AsynchronousSocketChannel ch; + + // asynchronous close while connecting + InetAddress rh = InetAddress.getByName("1.2.3.4"); + if (!rh.isReachable(3000)) { + InetSocketAddress isa = new InetSocketAddress(rh, 1234); + + ch = AsynchronousSocketChannel.open(); + Future result = ch.connect(isa); + + // give time to initiate the connect (SYN) + Thread.sleep(50); + + // close + ch.close(); + + // check that AsynchronousCloseException is thrown + try { + result.get(); + throw new RuntimeException("Should not connect"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof AsynchronousCloseException)) + throw new RuntimeException(x); + } + } + + System.out.println("-- asynchronous close when reading --"); + + Server server = new Server(); + ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + + ByteBuffer dst = ByteBuffer.allocateDirect(100); + Future result = ch.read(dst); + + // attempt a second read - should fail with ReadPendingException + ByteBuffer buf = ByteBuffer.allocateDirect(100); + try { + ch.read(buf); + throw new RuntimeException("ReadPendingException expected"); + } catch (ReadPendingException x) { + } + + // close channel (should cause initial read to complete) + ch.close(); + + // check that AsynchronousCloseException is thrown + try { + result.get(); + throw new RuntimeException("Should not read"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof AsynchronousCloseException)) + throw new RuntimeException(x); + } + + System.out.println("-- asynchronous close when writing --"); + + ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + + final AtomicReference writeException = + new AtomicReference(); + + // write bytes to fill socket buffer + ch.write(genBuffer(), ch, new CompletionHandler() { + public void completed(Integer result, AsynchronousSocketChannel ch) { + ch.write(genBuffer(), ch, this); + } + public void failed(Throwable x, AsynchronousSocketChannel ch) { + writeException.set(x); + } + public void cancelled(AsynchronousSocketChannel ch) { + } + }); + + // give time for socket buffer to fill up. + Thread.sleep(5*1000); + + // attempt a concurrent write - should fail with WritePendingException + try { + ch.write(genBuffer()); + throw new RuntimeException("WritePendingException expected"); + } catch (WritePendingException x) { + } + + // close channel - should cause initial write to complete + ch.close(); + + // wait for exception + while (writeException.get() == null) { + Thread.sleep(100); + } + if (!(writeException.get() instanceof AsynchronousCloseException)) + throw new RuntimeException("AsynchronousCloseException expected"); + + server.close(); + } + + static void testCancel() throws Exception { + System.out.println("-- cancel --"); + + Server server = new Server(); + + for (int i=0; i<2; i++) { + boolean mayInterruptIfRunning = (i == 0) ? false : true; + + // establish loopback connection + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + SocketChannel peer = server.accept(); + + // start read operation + final CountDownLatch latch = new CountDownLatch(1); + ByteBuffer buf = ByteBuffer.allocate(1); + Future res = ch.read(buf, null, + new CompletionHandler() { + public void completed(Integer result, Void att) { + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + latch.countDown(); + } + }); + + // cancel operation + boolean cancelled = res.cancel(mayInterruptIfRunning); + + // check post-conditions + if (!res.isDone()) + throw new RuntimeException("isDone should return true"); + if (res.isCancelled() != cancelled) + throw new RuntimeException("isCancelled not consistent"); + try { + res.get(); + throw new RuntimeException("CancellationException expected"); + } catch (CancellationException x) { + } + try { + res.get(1, TimeUnit.SECONDS); + throw new RuntimeException("CancellationException expected"); + } catch (CancellationException x) { + } + + // check that completion handler executed. + latch.await(); + + ch.close(); + peer.close(); + } + + server.close(); + } + + static void testRead1() throws Exception { + System.out.println("-- read (1) --"); + + Server server = new Server(); + final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + + // read with 0 bytes remaining should complete immediately + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte)0); + int n = ch.read(buf).get(); + if (n != 0) + throw new RuntimeException("0 expected"); + + // write bytes and close connection + SocketChannel sc = server.accept(); + ByteBuffer src = genBuffer(); + sc.setOption(StandardSocketOption.SO_SNDBUF, src.remaining()); + while (src.hasRemaining()) + sc.write(src); + sc.close(); + + // reads should complete immediately + final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100); + final CountDownLatch latch = new CountDownLatch(1); + ch.read(dst, null, new CompletionHandler() { + public void completed(Integer result, Void att) { + int n = result; + if (n > 0) { + ch.read(dst, null, this); + } else { + latch.countDown(); + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + latch.await(); + + // check buffers + src.flip(); + dst.flip(); + if (!src.equals(dst)) { + throw new RuntimeException("Contents differ"); + } + + // close channel + ch.close(); + + // check read fails with ClosedChannelException + try { + ch.read(dst).get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } + + server.close(); + } + + static void testRead2() throws Exception { + System.out.println("-- read (2) --"); + + Server server = new Server(); + + final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + SocketChannel sc = server.accept(); + + ByteBuffer src = genBuffer(); + + // read until the buffer is full + final ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity()); + final CountDownLatch latch = new CountDownLatch(1); + ch.read(dst, null, new CompletionHandler() { + public void completed(Integer result, Void att) { + if (dst.hasRemaining()) { + ch.read(dst, null, this); + } else { + latch.countDown(); + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // trickle the writing + do { + int rem = src.remaining(); + int size = (rem <= 100) ? rem : 50 + rand.nextInt(rem - 100); + ByteBuffer buf = ByteBuffer.allocate(size); + for (int i=0; i() { + public void completed(Long result, Void att) { + long n = result; + if (n <= 0) + throw new RuntimeException("No bytes read"); + latch.countDown(); + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // write some bytes + sc.write(genBuffer()); + + // read should now complete + latch.await(); + + // write more bytes + sc.write(genBuffer()); + + // read should complete immediately + for (int i=0; i() { + public void completed(Integer result, Void att) { + if (src.hasRemaining()) { + ch.write(src, null, this); + } else { + try { + ch.close(); + } catch (IOException ignore) { } + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // read to EOF or buffer full + ByteBuffer dst = ByteBuffer.allocateDirect(src.capacity() + 100); + do { + n = sc.read(dst); + } while (n > 0); + sc.close(); + + // check buffers + src.flip(); + dst.flip(); + if (!src.equals(dst)) { + throw new RuntimeException("Contents differ"); + } + + // check write fails with ClosedChannelException + try { + ch.read(dst).get(); + throw new RuntimeException("ExecutionException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("Cause of ClosedChannelException expected"); + } + + server.close(); + } + + // exercise gathering write + static void testWrite2() throws Exception { + System.out.println("-- write (2) --"); + + Server server = new Server(); + final AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + SocketChannel sc = server.accept(); + + // write buffers (should complete immediately) + ByteBuffer[] srcs = genBuffers(1); + long n = ch + .write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null, null).get(); + if (n <= 0) + throw new RuntimeException("No bytes written"); + + // set to true to signal that no more buffers should be written + final AtomicBoolean continueWriting = new AtomicBoolean(true); + + // number of bytes written + final AtomicLong bytesWritten = new AtomicLong(n); + + // write until socket buffer is full so as to create the conditions + // for when a write does not complete immediately + srcs = genBuffers(1); + ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, null, + new CompletionHandler() { + public void completed(Long result, Void att) { + long n = result; + if (n <= 0) + throw new RuntimeException("No bytes written"); + bytesWritten.addAndGet(n); + if (continueWriting.get()) { + ByteBuffer[] srcs = genBuffers(8); + ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, + null, this); + } + } + public void failed(Throwable exc, Void att) { + } + public void cancelled(Void att) { + } + }); + + // give time for socket buffer to fill up. + Thread.sleep(5*1000); + + // signal handler to stop further writing + continueWriting.set(false); + + // read until done + ByteBuffer buf = ByteBuffer.allocateDirect(4096); + long total = 0L; + do { + n = sc.read(buf); + if (n <= 0) + throw new RuntimeException("No bytes read"); + buf.rewind(); + total += n; + } while (total < bytesWritten.get()); + + ch.close(); + sc.close(); + server.close(); + } + + static void testShutdown() throws Exception { + System.out.println("-- shutdown--"); + + Server server = new Server(); + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + SocketChannel sc = server.accept(); + + ByteBuffer buf = ByteBuffer.allocateDirect(1000); + int n; + + // check read + ch.shutdownInput(); + n = ch.read(buf).get(); + if (n != -1) + throw new RuntimeException("-1 expected"); + // check full with full buffer + buf.put(new byte[100]); + n = ch.read(buf).get(); + if (n != -1) + throw new RuntimeException("-1 expected"); + + // check write + ch.shutdownOutput(); + try { + ch.write(buf).get(); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof ClosedChannelException)) + throw new RuntimeException("ClosedChannelException expected"); + } + + sc.close(); + ch.close(); + server.close(); + } + + static void testTimeout() throws Exception { + Server server = new Server(); + AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(); + ch.connect(server.address()).get(); + + System.out.println("-- timeout when reading --"); + + // this read should timeout + ByteBuffer dst = ByteBuffer.allocate(512); + try { + ch.read(dst, 3, TimeUnit.SECONDS, null, null).get(); + throw new RuntimeException("Read did not timeout"); + } catch (ExecutionException x) { + if (!(x.getCause() instanceof InterruptedByTimeoutException)) + throw new RuntimeException("InterruptedByTimeoutException expected"); + } + + // after a timeout then further reading should throw unspecified runtime exception + boolean exceptionThrown = false; + try { + ch.read(dst); + } catch (RuntimeException x) { + exceptionThrown = true; + } + if (!exceptionThrown) + throw new RuntimeException("RuntimeException expected after timeout."); + + + System.out.println("-- timeout when writing --"); + + final AtomicReference writeException = new AtomicReference(); + + final long timeout = 5; + final TimeUnit unit = TimeUnit.SECONDS; + + // write bytes to fill socket buffer + ch.write(genBuffer(), timeout, unit, ch, + new CompletionHandler() + { + public void completed(Integer result, AsynchronousSocketChannel ch) { + ch.write(genBuffer(), timeout, unit, ch, this); + } + public void failed(Throwable exc, AsynchronousSocketChannel ch) { + writeException.set(exc); + } + public void cancelled(AsynchronousSocketChannel ch) { + } + }); + + // wait for exception + while (writeException.get() == null) { + Thread.sleep(100); + } + if (!(writeException.get() instanceof InterruptedByTimeoutException)) + throw new RuntimeException("InterruptedByTimeoutException expected"); + + // after a timeout then further writing should throw unspecified runtime exception + exceptionThrown = false; + try { + ch.write(genBuffer()); + } catch (RuntimeException x) { + exceptionThrown = true; + } + if (!exceptionThrown) + throw new RuntimeException("RuntimeException expected after timeout."); + + ch.close(); + } + + // returns ByteBuffer with random bytes + static ByteBuffer genBuffer() { + int size = 1024 + rand.nextInt(16000); + byte[] buf = new byte[size]; + rand.nextBytes(buf); + boolean useDirect = rand.nextBoolean(); + if (useDirect) { + ByteBuffer bb = ByteBuffer.allocateDirect(buf.length); + bb.put(buf); + bb.flip(); + return bb; + } else { + return ByteBuffer.wrap(buf); + } + } + + // return ByteBuffer[] with random bytes + static ByteBuffer[] genBuffers(int max) { + int len = 1; + if (max > 1) + len += rand.nextInt(max); + ByteBuffer[] bufs = new ByteBuffer[len]; + for (int i=0; i readResult; + + Connection() throws Exception { + ServerSocketChannel ssc = + ServerSocketChannel.open().bind(new InetSocketAddress(0)); + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); + SocketAddress remote = new InetSocketAddress(lh, port); + client = AsynchronousSocketChannel.open(); + client.connect(remote).get(); + peer = ssc.accept(); + ssc.close(); + dst = ByteBuffer.allocate(K*K); + } + + void startRead() { + dst.clear(); + readResult = client.read(dst); + } + + void write() throws Exception { + peer.write(ByteBuffer.wrap("X".getBytes())); + } + + void finishRead() throws Exception { + readResult.get(); + } + } + + public static void main(String[] args) throws Exception { + + final int CONNECTION_COUNT = 10; + Connection[] connections = new Connection[CONNECTION_COUNT]; + for (int i=0; i len) + throw new RuntimeException("Too many bytes read"); + if (n > 0) { + total += n; + for (int i=0; i 0); + in.close(); + + } catch (IOException x) { + x.printStackTrace(); + } + } + + int total() { return total; } + int hash() { return hash; } + } + + static class Writer implements Runnable { + private final OutputStream out; + private final int total; + private volatile int hash; + + Writer(OutputStream out) { + this.out = out; + this.total = 50*1000 + rand.nextInt(50*1000); + } + + public void run() { + hash = 0; + int rem = total; + try { + do { + byte[] buf = new byte[1 + rand.nextInt(rem)]; + int off, len; + + // write random bytes + if (rand.nextBoolean()) { + off = 0; + len = buf.length; + } else { + off = rand.nextInt(buf.length); + int r = buf.length - off; + len = (r <= 1) ? 1 : (1 + rand.nextInt(r)); + } + for (int i=0; i 0); + + // close stream when done + out.close(); + + } catch (IOException x) { + x.printStackTrace(); + } + } + + int total() { return total; } + int hash() { return hash; } + } +} diff --git a/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java b/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java index 03b5daa68f1..6928bcded3e 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,11 +64,11 @@ public class BasicMulticastTests { // check key if (!key.isValid()) throw new RuntimeException("key is not valid"); - if (!key.getGroup().equals(group)) + if (!key.group().equals(group)) throw new RuntimeException("group is incorrect"); - if (!key.getNetworkInterface().equals(nif)) + if (!key.networkInterface().equals(nif)) throw new RuntimeException("network interface is incorrect"); - if (key.getSourceAddress() != null) + if (key.sourceAddress() != null) throw new RuntimeException("key is source specific"); // drop membership @@ -86,11 +86,11 @@ public class BasicMulticastTests { } if (!key.isValid()) throw new RuntimeException("key is not valid"); - if (!key.getGroup().equals(group)) + if (!key.group().equals(group)) throw new RuntimeException("group is incorrect"); - if (!key.getNetworkInterface().equals(nif)) + if (!key.networkInterface().equals(nif)) throw new RuntimeException("network interface is incorrect"); - if (!key.getSourceAddress().equals(source)) + if (!key.sourceAddress().equals(source)) throw new RuntimeException("key's source address incorrect"); // drop membership diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index e4e85b11fb4..3df7bbbda45 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ public class SocketOptionTests { DatagramChannel dc = DatagramChannel.open(); // check supported options - Set> options = dc.options(); + Set> options = dc.supportedOptions(); List> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP); diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index 6c4a443ed0a..cba99e0f285 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ public class SocketOptionTests { ServerSocketChannel ssc = ServerSocketChannel.open(); // check supported options - Set> options = ssc.options(); + Set> options = ssc.supportedOptions(); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); if (!options.contains(SO_RCVBUF)) diff --git a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java index b6fadced8e2..abcb97476ef 100644 --- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ public class SocketOptionTests { SocketChannel sc = SocketChannel.open(); // check supported options - Set> options = sc.options(); + Set> options = sc.supportedOptions(); List expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE, SO_REUSEADDR, SO_LINGER, TCP_NODELAY); for (SocketOption opt: expected) { diff --git a/jdk/test/java/nio/channels/etc/NetworkChannelTests.java b/jdk/test/java/nio/channels/etc/NetworkChannelTests.java index 5f03453ca11..2a29bcebbd6 100644 --- a/jdk/test/java/nio/channels/etc/NetworkChannelTests.java +++ b/jdk/test/java/nio/channels/etc/NetworkChannelTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,13 +103,14 @@ public class NetworkChannelTests { // closed ch.close(); - if (ch.getLocalAddress() != null) { - throw new RuntimeException("Local address return when closed"); - } + try { + ch.getLocalAddress(); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ClosedChannelException e) { } } /** - * Exercise getConnectedAddress method (SocketChannel only) + * Exercise getRemoteAddress method (SocketChannel only) */ static void connectedAddressTests() throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open() @@ -121,19 +122,21 @@ public class NetworkChannelTests { SocketChannel sc = SocketChannel.open(); // not connected - if (sc.getConnectedAddress() != null) - throw new RuntimeException("getConnectedAddress returned address when not connected"); + if (sc.getRemoteAddress() != null) + throw new RuntimeException("getRemoteAddress returned address when not connected"); // connected sc.connect(server); - SocketAddress remote = sc.getConnectedAddress(); + SocketAddress remote = sc.getRemoteAddress(); if (!remote.equals(server)) - throw new RuntimeException("getConnectedAddress returned incorrect address"); + throw new RuntimeException("getRemoteAddress returned incorrect address"); // closed sc.close(); - if (sc.getConnectedAddress() != null) - throw new RuntimeException("getConnectedAddress returned address when closed"); + try { + sc.getRemoteAddress(); + throw new RuntimeException("ClosedChannelException expected"); + } catch (ClosedChannelException e) { } ssc.close(); } diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java new file mode 100644 index 00000000000..4f6d8483807 --- /dev/null +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.channels.spi.AsynchronousChannelProvider; + +public class CheckProvider { + public static void main(String[] args) { + Class c = AsynchronousChannelProvider.provider().getClass(); + + String expected = args[0]; + String actual = c.getName(); + + if (!actual.equals(expected)) + throw new RuntimeException("Provider is of type '" + actual + + "', expected '" + expected + "'"); + + } +} diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider new file mode 100644 index 00000000000..6b3e87eb404 --- /dev/null +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider @@ -0,0 +1 @@ +Provider1 diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java new file mode 100644 index 00000000000..fc6036a1ea9 --- /dev/null +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.nio.channels.*; +import java.net.ProtocolFamily; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.io.IOException; + +public class Provider1 extends AsynchronousChannelProvider { + public Provider1() { + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factorry) + throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) + throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousSocketChannel openAsynchronousSocketChannel + (AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel + (AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousDatagramChannel openAsynchronousDatagramChannel + (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } +} diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java new file mode 100644 index 00000000000..a42c12ff9de --- /dev/null +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.channels.spi.AsynchronousChannelProvider; +import java.nio.channels.*; +import java.net.ProtocolFamily; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.io.IOException; + +public class Provider2 extends AsynchronousChannelProvider { + public Provider2() { + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup + (int nThreads, ThreadFactory threadFactory) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousChannelGroup openAsynchronousChannelGroup + (ExecutorService executor, int initialSize) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousSocketChannel openAsynchronousSocketChannel + (AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel + (AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } + + @Override + public AsynchronousDatagramChannel openAsynchronousDatagramChannel + (ProtocolFamily family, AsynchronousChannelGroup group) throws IOException + { + throw new RuntimeException(); + } +} diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh new file mode 100644 index 00000000000..13fb2a2fae0 --- /dev/null +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh @@ -0,0 +1,71 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @summary Unit test for java.nio.channels.spi.AsynchronousChannelProvider +# @build Provider1 Provider2 CheckProvider +# @run shell custom_provider.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java +else + JAVA="${TESTJAVA}/bin/java" +fi + +OS=`uname -s` +case "$OS" in + Windows_* ) + CLASSPATH="${TESTCLASSES};${TESTSRC}" + ;; + * ) + CLASSPATH=${TESTCLASSES}:${TESTSRC} + ;; +esac +export CLASSPATH + +failures=0 + +go() { + echo '' + $JAVA $1 $2 $3 2>&1 + if [ $? != 0 ]; then failures=`expr $failures + 1`; fi +} + +# Run the tests + +go CheckProvider Provider1 +go -Djava.nio.channels.spi.AsynchronousChannelProvider=Provider2 CheckProvider \ + Provider2 + +# +# Results +# +echo '' +if [ $failures -gt 0 ]; + then echo "$failures test(s) failed"; + else echo "All test(s) passed"; fi +exit $failures diff --git a/jdk/test/java/nio/file/DirectoryStream/Basic.java b/jdk/test/java/nio/file/DirectoryStream/Basic.java new file mode 100644 index 00000000000..b92447d70f6 --- /dev/null +++ b/jdk/test/java/nio/file/DirectoryStream/Basic.java @@ -0,0 +1,168 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.DirectoryStream + * @library .. + */ + +import java.nio.file.*; +import java.util.*; +import java.io.IOException; + +public class Basic { + static boolean found; + + static void doTest(final Path dir) throws IOException { + DirectoryStream stream; + + // test that directory is empty + Files.withDirectory(dir, new FileAction() { + public void invoke(FileRef entry) { + throw new RuntimeException("directory not empty"); + } + }); + + // create file in directory + final Path foo = Paths.get("foo"); + dir.resolve(foo).createFile(); + + // iterate over directory and check there is one entry + found = false; + Files.withDirectory(dir, new FileAction() { + public void invoke(Path entry) { + if (entry.getName().equals(foo)) { + if (found) + throw new RuntimeException("entry already found"); + found = true; + } else { + throw new RuntimeException("entry " + entry.getName() + + " not expected"); + } + } + }); + if (!found) + throw new RuntimeException("entry not found"); + + // check filtering: f* should match foo + DirectoryStream.Filter filter = new DirectoryStream.Filter() { + private PathMatcher matcher = + dir.getFileSystem().getPathMatcher("glob:f*"); + public boolean accept(Path file) { + return matcher.matches(file); + } + }; + Files.withDirectory(dir, filter, new FileAction() { + public void invoke(Path entry) { + if (!entry.getName().equals(foo)) + throw new RuntimeException("entry not expected"); + } + }); + + // check filtering: z* should not match any files + filter = new DirectoryStream.Filter() { + private PathMatcher matcher = + dir.getFileSystem().getPathMatcher("glob:z*"); + public boolean accept(Path file) { + return matcher.matches(file); + } + }; + Files.withDirectory(dir, filter, new FileAction() { + public void invoke(FileRef entry) { + throw new RuntimeException("no matching entries expected"); + } + }); + + // check that exception or error thrown by filter is not thrown + // by newDirectoryStream or iterator method. + stream = dir.newDirectoryStream(new DirectoryStream.Filter() { + public boolean accept(Path file) { + throw new RuntimeException("Should not be visible"); + } + }); + try { + stream.iterator(); + } finally { + stream.close(); + } + + // test NotDirectoryException + try { + dir.resolve(foo).newDirectoryStream(); + throw new RuntimeException("NotDirectoryException not thrown"); + } catch (NotDirectoryException x) { + } + + // test iterator remove method + stream = dir.newDirectoryStream(); + Iterator i = stream.iterator(); + while (i.hasNext()) { + Path entry = i.next(); + if (!entry.getName().equals(foo)) + throw new RuntimeException("entry not expected"); + i.remove(); + } + stream.close(); + + // test IllegalStateException + stream = dir.newDirectoryStream(); + i = stream.iterator(); + try { + stream.iterator(); + throw new RuntimeException("IllegalStateException not thrown as expected"); + } catch (IllegalStateException x) { + } + stream.close(); + try { + stream.iterator(); + throw new RuntimeException("IllegalStateException not thrown as expected"); + } catch (IllegalStateException x) { + } + try { + i.hasNext(); + throw new RuntimeException("ConcurrentModificationException not thrown as expected"); + } catch (ConcurrentModificationException x) { + Throwable t = x.getCause(); + if (!(t instanceof IllegalStateException)) + throw new RuntimeException("Cause is not IllegalStateException as expected"); + } + try { + i.next(); + throw new RuntimeException("IllegalStateException not thrown as expected"); + } catch (ConcurrentModificationException x) { + Throwable t = x.getCause(); + if (!(t instanceof IllegalStateException)) + throw new RuntimeException("Cause is not IllegalStateException as expected"); + } + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTest(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java b/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java new file mode 100644 index 00000000000..92159f5df5f --- /dev/null +++ b/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java @@ -0,0 +1,73 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6808647 + * @summary Checks that a DirectoryStream's iterator returns the expected + * path when opening a directory by specifying only the drive letter. + * @library .. + */ + +import java.nio.file.*; +import java.io.File; +import java.io.IOException; + +public class DriveLetter { + + public static void main(String[] args) throws IOException { + String os = System.getProperty("os.name"); + if (!os.startsWith("Windows")) { + System.out.println("This is Windows specific test"); + return; + } + String here = System.getProperty("user.dir"); + if (here.length() < 2 || here.charAt(1) != ':') + throw new RuntimeException("Unable to determine drive letter"); + + // create temporary file in current directory + File tempFile = File.createTempFile("foo", "tmp", new File(here)); + try { + // we should expect C:foo.tmp to be returned by iterator + String drive = here.substring(0, 2); + Path expected = Paths.get(drive).resolve(tempFile.getName()); + + boolean found = false; + DirectoryStream stream = Paths.get(drive).newDirectoryStream(); + try { + for (Path file : stream) { + if (file.equals(expected)) { + found = true; + break; + } + } + } finally { + stream.close(); + } + if (!found) + throw new RuntimeException("Temporary file not found???"); + + } finally { + tempFile.delete(); + } + } +} diff --git a/jdk/test/java/nio/file/DirectoryStream/Filters.java b/jdk/test/java/nio/file/DirectoryStream/Filters.java new file mode 100644 index 00000000000..ea539c95df3 --- /dev/null +++ b/jdk/test/java/nio/file/DirectoryStream/Filters.java @@ -0,0 +1,241 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.DirectoryStreamFilters + * @library .. + */ + +import java.nio.file.*; +import static java.nio.file.DirectoryStreamFilters.*; +import java.nio.file.attribute.Attributes; +import java.io.*; +import java.util.*; + +public class Filters { + static final Random rand = new Random(); + + // returns a filter that only accepts files that are larger than a given size + static DirectoryStream.Filter newMinimumSizeFilter(final long min) { + return new DirectoryStream.Filter() { + public boolean accept(FileRef file) { + try { + long size = Attributes.readBasicFileAttributes(file).size(); + return size >= min; + } catch (IOException e) { + throw new IOError(e); + } + } + }; + } + + // returns a filter that only accepts files that are matched by a given glob + static DirectoryStream.Filter newGlobFilter(final String glob) { + return new DirectoryStream.Filter() { + PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:"+ glob); + public boolean accept(Path file) { + return matcher.matches(file.getName()); + } + }; + } + + static final int BIG_FILE_THRESHOLD = 8192; + + static int totalCount; + static int htmlCount; + static int bigAndHtmlCount; + static int bigOrHtmlCount; + + // generates random files in the test directory and initializes the counts + static void setup(Path dir) throws IOException { + // create 10-26 files. + totalCount = 10 + rand.nextInt(17); + char firstChar = 'A'; + for (int i=0; i 0) + out.write(new byte[size]); + } finally { + out.close(); + } + System.out.format("Created %s, size %d byte(s)\n", name, size); + } + } + + static boolean isHtml(Path file) { + return file.toString().endsWith(".html"); + } + + static boolean isBig(Path file) throws IOException { + long size = Attributes.readBasicFileAttributes(file).size(); + return size >= BIG_FILE_THRESHOLD; + } + + static void checkCount(int expected, int actual) { + if (actual != expected) + throw new RuntimeException("'" + expected + + "' entries expected, actual: " + actual); + } + + static void doTests(Path dir) throws IOException { + final List> emptyList = Collections.emptyList(); + + // list containing two filters + List> filters = + new ArrayList>(); + filters.add(newMinimumSizeFilter(BIG_FILE_THRESHOLD)); + filters.add(newGlobFilter("*.html")); + + int accepted; + DirectoryStream stream; + + System.out.println("Test: newContentTypeFilter"); + accepted = 0; + stream = dir.newDirectoryStream(newContentTypeFilter("text/html")); + try { + for (Path entry: stream) { + if (!isHtml(entry)) + throw new RuntimeException("html file expected"); + accepted++; + } + } finally { + stream.close(); + } + checkCount(htmlCount, accepted); + + System.out.println("Test: allOf with list of filters"); + accepted = 0; + stream = dir.newDirectoryStream(allOf(filters)); + try { + for (Path entry: stream) { + if (!isHtml(entry)) + throw new RuntimeException("html file expected"); + if (!isBig(entry)) + throw new RuntimeException("big file expected"); + accepted++; + } + } finally { + stream.close(); + } + checkCount(bigAndHtmlCount, accepted); + + System.out.println("Test: allOf with empty list"); + accepted = 0; + stream = dir.newDirectoryStream(allOf(emptyList)); + try { + for (Path entry: stream) { + accepted++; + } + } finally { + stream.close(); + } + checkCount(totalCount, accepted); + + System.out.println("Test: anyOf with list of filters"); + accepted = 0; + stream = dir.newDirectoryStream(anyOf(filters)); + try { + for (Path entry: stream) { + if (!isHtml(entry) && !isBig(entry)) + throw new RuntimeException("html or big file expected"); + accepted++; + } + } finally { + stream.close(); + } + checkCount(bigOrHtmlCount, accepted); + + System.out.println("Test: anyOf with empty list"); + accepted = 0; + stream = dir.newDirectoryStream(anyOf(emptyList)); + try { + for (Path entry: stream) { + accepted++; + } + } finally { + stream.close(); + } + checkCount(0, accepted); + + System.out.println("Test: complementOf"); + accepted = 0; + stream = dir.newDirectoryStream(complementOf(newGlobFilter("*.html"))); + try { + for (Path entry: stream) { + accepted++; + } + } finally { + stream.close(); + } + checkCount(totalCount-htmlCount, accepted); + + System.out.println("Test: nulls"); + try { + newContentTypeFilter(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + try { + allOf(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + try { + anyOf(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + try { + complementOf(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException npe) { } + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + setup(dir); + doTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java new file mode 100644 index 00000000000..98367d8958c --- /dev/null +++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java @@ -0,0 +1,370 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.SecureDirectoryStream + * @library .. + */ + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.nio.channels.*; +import java.io.IOException; +import java.util.*; + +public class SecureDS { + static boolean supportsLinks; + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + DirectoryStream stream = dir.newDirectoryStream(); + stream.close(); + if (!(stream instanceof SecureDirectoryStream)) { + System.out.println("SecureDirectoryStream not supported."); + return; + } + + supportsLinks = TestUtil.supportsLinks(dir); + + // run tests + doBasicTests(dir); + doMoveTests(dir); + miscTests(dir); + + } finally { + TestUtil.removeAll(dir); + } + } + + // Exercise each of SecureDirectoryStream's method (except move) + static void doBasicTests(Path dir) throws IOException { + Path dir1 = dir.resolve("dir1").createDirectory(); + Path dir2 = dir.resolve("dir2"); + + // create a file, directory, and two sym links in the directory + Path fileEntry = Paths.get("myfile"); + dir1.resolve(fileEntry).createFile(); + Path dirEntry = Paths.get("mydir"); + dir1.resolve(dirEntry).createDirectory(); + // myfilelink -> myfile + Path link1Entry = Paths.get("myfilelink"); + if (supportsLinks) + dir1.resolve(link1Entry).createSymbolicLink(fileEntry); + // mydirlink -> mydir + Path link2Entry = Paths.get("mydirlink"); + if (supportsLinks) + dir1.resolve(link2Entry).createSymbolicLink(dirEntry); + + // open directory and then move it so that it is no longer accessible + // via its original path. + SecureDirectoryStream stream = + (SecureDirectoryStream)dir1.newDirectoryStream(); + dir1.moveTo(dir2); + + // Test: iterate over all entries + int count = 0; + for (Path entry: stream) { count++; } + assertTrue(count == (supportsLinks ? 4 : 2)); + + // Test: getFileAttributeView to access directory's attributes + assertTrue(stream + .getFileAttributeView(BasicFileAttributeView.class) + .readAttributes() + .isDirectory()); + + // Test: dynamic access to directory's attributes + BasicFileAttributeView view = stream. + getFileAttributeView(BasicFileAttributeView.class); + Map attrs = view.readAttributes("*"); + assertTrue((Boolean)attrs.get("isDirectory")); + attrs = view.readAttributes("isRegularFile", "size"); + assertTrue(!(Boolean)attrs.get("isRegularFile")); + assertTrue((Long)attrs.get("size") >= 0); + int linkCount = (Integer)view.getAttribute("linkCount"); + assertTrue(linkCount > 0); + view.setAttribute("lastModifiedTime", 0L); + + // Test: getFileAttributeView to access attributes of entries + assertTrue(stream + .getFileAttributeView(fileEntry, BasicFileAttributeView.class) + .readAttributes() + .isRegularFile()); + assertTrue(stream + .getFileAttributeView(fileEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes() + .isRegularFile()); + assertTrue(stream + .getFileAttributeView(dirEntry, BasicFileAttributeView.class) + .readAttributes() + .isDirectory()); + assertTrue(stream + .getFileAttributeView(dirEntry, BasicFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes() + .isDirectory()); + if (supportsLinks) { + assertTrue(stream + .getFileAttributeView(link1Entry, BasicFileAttributeView.class) + .readAttributes() + .isRegularFile()); + assertTrue(stream + .getFileAttributeView(link1Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes() + .isSymbolicLink()); + assertTrue(stream + .getFileAttributeView(link2Entry, BasicFileAttributeView.class) + .readAttributes() + .isDirectory()); + assertTrue(stream + .getFileAttributeView(link2Entry, BasicFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes() + .isSymbolicLink()); + } + + // Test: dynamic access to entry attributes + view = stream + .getFileAttributeView(fileEntry, PosixFileAttributeView.class, NOFOLLOW_LINKS); + if (view != null) { + attrs = view.readAttributes("owner", "size"); + UserPrincipal owner = (UserPrincipal)attrs.get("owner"); + assertTrue(owner != null); + assertTrue((Long)attrs.get("size") >= 0L); + view.setAttribute("lastAccessTime", 0L); + } + + // Test: newByteChannel + Set opts = Collections.emptySet(); + stream.newByteChannel(fileEntry, opts).close(); + if (supportsLinks) { + stream.newByteChannel(link1Entry, opts).close(); + try { + Set mixed = new HashSet(); + mixed.add(READ); + mixed.add(NOFOLLOW_LINKS); + stream.newByteChannel(link1Entry, mixed).close(); + shouldNotGetHere(); + } catch (IOException x) { } + } + + // Test: newDirectoryStream + stream.newDirectoryStream(dirEntry, true, null).close(); + stream.newDirectoryStream(dirEntry, false, null).close(); + if (supportsLinks) { + stream.newDirectoryStream(link2Entry, true, null).close(); + try { + stream.newDirectoryStream(link2Entry, false, null).close(); + shouldNotGetHere(); + } catch (IOException x) { } + } + + // Test: delete + if (supportsLinks) { + stream.deleteFile(link1Entry); + stream.deleteFile(link2Entry); + } + stream.deleteDirectory(dirEntry); + stream.deleteFile(fileEntry); + + // Test: remove + // (requires resetting environment to get new iterator) + stream.close(); + dir2.moveTo(dir1); + dir1.resolve(fileEntry).createFile(); + stream = (SecureDirectoryStream)dir1.newDirectoryStream(); + dir1.moveTo(dir2); + Iterator iter = stream.iterator(); + int removed = 0; + while (iter.hasNext()) { + iter.next(); + iter.remove(); + removed++; + } + assertTrue(removed == 1); + + // clean-up + stream.close(); + dir2.delete(); + } + + // Exercise SecureDirectoryStream's move method + static void doMoveTests(Path dir) throws IOException { + Path dir1 = dir.resolve("dir1").createDirectory(); + Path dir2 = dir.resolve("dir2").createDirectory(); + + // create dir1/myfile, dir1/mydir, dir1/mylink + Path fileEntry = Paths.get("myfile"); + dir1.resolve(fileEntry).createFile(); + Path dirEntry = Paths.get("mydir"); + dir1.resolve(dirEntry).createDirectory(); + Path linkEntry = Paths.get("mylink"); + if (supportsLinks) + dir1.resolve(linkEntry).createSymbolicLink(Paths.get("missing")); + + // target name + Path target = Paths.get("newfile"); + + // open stream to both directories + SecureDirectoryStream stream1 = + (SecureDirectoryStream)dir1.newDirectoryStream(); + SecureDirectoryStream stream2 = + (SecureDirectoryStream)dir2.newDirectoryStream(); + + // Test: move dir1/myfile -> dir2/newfile + stream1.move(fileEntry, stream2, target); + assertTrue(dir1.resolve(fileEntry).notExists()); + assertTrue(dir2.resolve(target).exists()); + stream2.deleteFile(target); + + // Test: move dir1/mydir -> dir2/newfile + stream1.move(dirEntry, stream2, target); + assertTrue(dir1.resolve(dirEntry).notExists()); + assertTrue(dir2.resolve(target).exists()); + stream2.deleteDirectory(target); + + // Test: move dir1/mylink -> dir2/newfile + if (supportsLinks) { + stream1.move(linkEntry, stream2, target); + assertTrue(dir2.resolve(target) + .getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes() + .isSymbolicLink()); + stream2.deleteFile(target); + } + + // Test: move between devices + String testDirAsString = System.getProperty("test.dir"); + if (testDirAsString != null) { + Path testDir = Paths.get(testDirAsString); + if (!dir1.getFileStore().equals(testDir.getFileStore())) { + SecureDirectoryStream ts = + (SecureDirectoryStream)testDir.newDirectoryStream(); + dir1.resolve(fileEntry).createFile(); + try { + stream1.move(fileEntry, ts, target); + shouldNotGetHere(); + } catch (AtomicMoveNotSupportedException x) { } + ts.close(); + stream1.deleteFile(fileEntry); + } + } + + // clean-up + dir1.delete(); + dir2.delete(); + } + + // null and ClosedDirectoryStreamException + static void miscTests(Path dir) throws IOException { + Path file = Paths.get("file"); + dir.resolve(file).createFile(); + + SecureDirectoryStream stream = + (SecureDirectoryStream)dir.newDirectoryStream(); + + // NullPointerException + try { + stream.getFileAttributeView(null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.getFileAttributeView(null, BasicFileAttributeView.class); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.getFileAttributeView(file, null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.newByteChannel(null, EnumSet.of(CREATE,WRITE)); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.newByteChannel(null, EnumSet.of(CREATE,WRITE,null)); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.newByteChannel(file, null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.move(null, stream, file); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.move(file, null, file); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.move(file, stream, null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.newDirectoryStream(null, true, null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.deleteFile(null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + try { + stream.deleteDirectory(null); + shouldNotGetHere(); + } catch (NullPointerException x) { } + + // close stream + stream.close(); + stream.close(); // should be no-op + + // ClosedDirectoryStreamException + try { + stream.newDirectoryStream(file, true, null); + shouldNotGetHere(); + } catch (ClosedDirectoryStreamException x) { } + try { + stream.newByteChannel(file, EnumSet.of(READ)); + shouldNotGetHere(); + } catch (ClosedDirectoryStreamException x) { } + try { + stream.move(file, stream, file); + shouldNotGetHere(); + } catch (ClosedDirectoryStreamException x) { } + try { + stream.deleteFile(file); + shouldNotGetHere(); + } catch (ClosedDirectoryStreamException x) { } + + // clean-up + dir.resolve(file).delete(); + } + + static void assertTrue(boolean b) { + if (!b) throw new RuntimeException("Assertion failed"); + } + + static void shouldNotGetHere() { + assertTrue(false); + } +} diff --git a/jdk/test/java/nio/file/FileStore/Basic.java b/jdk/test/java/nio/file/FileStore/Basic.java new file mode 100644 index 00000000000..604795db435 --- /dev/null +++ b/jdk/test/java/nio/file/FileStore/Basic.java @@ -0,0 +1,87 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.FileStore + * @library .. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +public class Basic { + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion failed"); + } + + static void doTests(Path dir) throws IOException { + /** + * Test: Directory should be on FileStore that is writable + */ + assertTrue(!dir.getFileStore().isReadOnly()); + + /** + * Test: Two files should have the same FileStore + */ + FileStore store1 = dir.resolve("foo").createFile().getFileStore(); + FileStore store2 = dir.resolve("bar").createFile().getFileStore(); + assertTrue(store1.equals(store2)); + assertTrue(store2.equals(store1)); + assertTrue(store1.hashCode() == store2.hashCode()); + + /** + * Test: File and FileStore attributes + */ + assertTrue(store1.supportsFileAttributeView("basic")); + + /** + * Test: Enumerate all FileStores + */ + FileStore prev = null; + for (FileStore store: FileSystems.getDefault().getFileStores()) { + System.out.format("%s (name=%s type=%s)\n", store, store.name(), + store.type()); + + // check space attributes + Attributes.readFileStoreSpaceAttributes(store); + + // two distinct FileStores should not be equal + assertTrue(!store.equals(prev)); + prev = store; + } + } +} diff --git a/jdk/test/java/nio/file/FileSystem/Basic.java b/jdk/test/java/nio/file/FileSystem/Basic.java new file mode 100644 index 00000000000..8df7c1e8de6 --- /dev/null +++ b/jdk/test/java/nio/file/FileSystem/Basic.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.FileSystem + * @library .. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + +/** + * Simple santity checks for java.nio.file.FileSystem + */ +public class Basic { + + static void check(boolean okay, String msg) { + if (!okay) + throw new RuntimeException(msg); + } + + static void checkSupported(FileSystem fs, String... views) { + for (String view: views) { + check(fs.supportedFileAttributeViews().contains(view), + "support for '" + view + "' expected"); + } + } + + public static void main(String[] args) throws IOException { + FileSystem fs = FileSystems.getDefault(); + + // close should throw UOE + try { + fs.close(); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException e) { } + check(fs.isOpen(), "should be open"); + + check(!fs.isReadOnly(), "should provide read-write access"); + + check(fs.provider().getScheme().equals("file"), + "should use 'file' scheme"); + + // santity check method - need to re-visit this in future as I/O errors + // are possible + for (FileStore store: fs.getFileStores()) { + System.out.println(store); + } + + // sanity check supportedFileAttributeViews + checkSupported(fs, "basic"); + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) + checkSupported(fs, "posix", "unix", "owner", "acl", "xattr"); + if (os.equals("Linux")) + checkSupported(fs, "posix", "unix", "owner", "dos", "xattr"); + if (os.equals("Windows")) + checkSupported(fs, "owner", "dos", "acl", "xattr"); + } +} diff --git a/jdk/test/java/nio/file/Files/ContentType.java b/jdk/test/java/nio/file/Files/ContentType.java new file mode 100644 index 00000000000..a0a5afc22b7 --- /dev/null +++ b/jdk/test/java/nio/file/Files/ContentType.java @@ -0,0 +1,91 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.io.*; + +/** + * Uses Files.probeContentType to probe html file and custom file type. + */ + +public class ContentType { + + static FileRef createHtmlFile() throws IOException { + Path file = File.createTempFile("foo", ".html").toPath(); + OutputStream out = file.newOutputStream(); + try { + out.write("foo".getBytes()); + } finally { + out.close(); + } + + return file; + } + + static FileRef createUnknownFile() throws IOException { + return File.createTempFile("unknown", "unknown-file-type-789").toPath(); + } + + static FileRef createGrapeFile() throws IOException { + return File.createTempFile("red", ".grape").toPath(); + } + + public static void main(String[] args) throws IOException { + + // exercise default file type detector + FileRef file = createHtmlFile(); + try { + String type = Files.probeContentType(file); + if (type == null) { + System.err.println("Content type cannot be determined - test skipped"); + } else { + if (!type.equals("text/html")) + throw new RuntimeException("Unexpected type: " + type); + } + } finally { + TestUtil.deleteUnchecked(file); + } + file = createUnknownFile(); + try { + String type = Files.probeContentType(file); + if (type != null) + throw new RuntimeException(file + " should not be recognized as:" + + type); + } finally { + TestUtil.deleteUnchecked(file); + } + + // exercise custom file type detector + file = createGrapeFile(); + try { + String type = Files.probeContentType(file); + if (type == null) + throw new RuntimeException("Custom file type detector not installed?"); + if (!type.equals("grape/unknown")) + throw new RuntimeException("Unexpected type: " + type); + } finally { + TestUtil.deleteUnchecked(file); + } + + } +} diff --git a/jdk/test/java/nio/file/Files/CreateFileTree.java b/jdk/test/java/nio/file/Files/CreateFileTree.java new file mode 100644 index 00000000000..17549a7e350 --- /dev/null +++ b/jdk/test/java/nio/file/Files/CreateFileTree.java @@ -0,0 +1,96 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.io.IOException; +import java.util.*; + +/** + * Creates a file tree with possible cycles caused by symbolic links + * to ancestor directories. + */ + +public class CreateFileTree { + + static final Random rand = new Random(); + + public static Path createTemporaryDirectory() throws IOException { + Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); + Path dir; + do { + dir = tmpdir.resolve("name" + rand.nextInt()); + } while (dir.exists()); + dir.createDirectory(); + return dir; + } + + public static void main(String[] args) throws IOException { + Path top = createTemporaryDirectory(); + if (!top.isAbsolute()) + top = top.toAbsolutePath(); + + List dirs = new ArrayList(); + + // create tree + Queue queue = new ArrayDeque(); + queue.add(top); + int total = 1 + rand.nextInt(20); + int n = 0; + Path dir; + while (((dir = queue.poll()) != null) && (n < total)) { + int r = Math.min((total-n), (1+rand.nextInt(3))); + for (int i=0; i= 2; + + // create a few regular files in the file tree + int files = dirs.size() * 3; + for (int i=0; i() { + public void invoke(Path entry) { + } + }); + npeExpected(); + } catch (NullPointerException e) { + } + + try { + Files.withDirectory(Paths.get("."), (String)null, new FileAction() { + public void invoke(Path entry) { + } + }); + npeExpected(); + } catch (NullPointerException e) { + } + + try { + Files.withDirectory(Paths.get("."), "*", null); + npeExpected(); + } catch (NullPointerException e) { + } + + // test propogation of IOException + Path tmpdir = TestUtil.createTemporaryDirectory(); + try { + tmpdir.resolve("foo").createFile(); + try { + Files.withDirectory(tmpdir, new FileAction() { + public void invoke(Path entry) throws IOException { + throw new IOException(); + } + }); + throw new RuntimeException("IOException expected"); + } catch (IOException e) { + } + } finally { + TestUtil.removeAll(tmpdir); + } + + try { + Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class), + Integer.MAX_VALUE, new SimpleFileVisitor(){}); + npeExpected(); + } catch (NullPointerException e) { + } + + try { + Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE, + new SimpleFileVisitor(){}); + npeExpected(); + } catch (NullPointerException e) { + } + + try { + Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), + -1, new SimpleFileVisitor(){}); + throw new RuntimeException("IllegalArgumentExpected expected"); + } catch (IllegalArgumentException e) { + } + + try { + Set opts = new HashSet(1); + opts.add(null); + Files.walkFileTree(Paths.get("."), opts, Integer.MAX_VALUE, + new SimpleFileVisitor(){}); + npeExpected(); + } catch (NullPointerException e) { + } + + try { + Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), + Integer.MAX_VALUE, null); + npeExpected(); + } catch (NullPointerException e) { + } + } +} diff --git a/jdk/test/java/nio/file/Files/PrintFileTree.java b/jdk/test/java/nio/file/Files/PrintFileTree.java new file mode 100644 index 00000000000..dc2c49f8db1 --- /dev/null +++ b/jdk/test/java/nio/file/Files/PrintFileTree.java @@ -0,0 +1,78 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Invokes Files.walkFileTree to traverse a file tree and prints + * each of the directories and files. The -L option causes symbolic + * links to be followed. + */ + +public class PrintFileTree { + + public static void main(String[] args) throws Exception { + boolean followLinks = false; + Path dir; + + if (args[0].equals("-L")) { + followLinks = true; + dir = Paths.get(args[1]); + } else { + dir = Paths.get(args[0]); + } + + Set options = new HashSet(); + if (followLinks) + options.add(FileVisitOption.FOLLOW_LINKS); + + Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor() { + public FileVisitResult preVisitDirectory(FileRef dir) { + System.out.println(dir); + return FileVisitResult.CONTINUE; + } + public FileVisitResult preVisitDirectoryFailed(FileRef dir, IOException exc) { + exc.printStackTrace(); + return FileVisitResult.CONTINUE; + } + public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) { + System.out.println(file); + return FileVisitResult.CONTINUE; + } + public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) { + if (exc != null) { + exc.printStackTrace(); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + public FileVisitResult visitFileFailed(FileRef file, IOException exc) { + exc.printStackTrace(); + return FileVisitResult.TERMINATE; + } + }); + } +} diff --git a/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java b/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java new file mode 100644 index 00000000000..0b66706d636 --- /dev/null +++ b/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.nio.file.spi.FileTypeDetector; +import java.io.*; + + +public class SimpleFileTypeDetector extends FileTypeDetector { + public SimpleFileTypeDetector() { + } + + public String probeContentType(FileRef file) throws IOException { + + System.out.println("probe " + file + "..."); + + if (file instanceof Path) { + String name = ((Path)file).toString(); + if (name.endsWith(".grape")) { + return "grape/unknown"; + } + } + + // unknown + return null; + } +} diff --git a/jdk/test/java/nio/file/Files/SkipSiblings.java b/jdk/test/java/nio/file/Files/SkipSiblings.java new file mode 100644 index 00000000000..e8524552012 --- /dev/null +++ b/jdk/test/java/nio/file/Files/SkipSiblings.java @@ -0,0 +1,85 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Unit test for Files.walkFileTree to test SKIP_SIBLINGS return value. + */ + +public class SkipSiblings { + + static final Random rand = new Random(); + static final Set skipped = new HashSet(); + + // check if this path's directory has been skipped + static void check(Path path) { + if (skipped.contains(path.getParent())) + throw new RuntimeException(path + " should not have been visited"); + } + + // indicates if the siblings of this path should be skipped + static boolean skip(Path path) { + Path parent = path.getParent(); + if (parent != null && rand.nextBoolean()) { + skipped.add(parent); + return true; + } + return false; + } + + public static void main(String[] args) throws Exception { + Path dir = Paths.get(args[0]); + + Files.walkFileTree(dir, new FileVisitor() { + public FileVisitResult preVisitDirectory(Path dir) { + check(dir); + if (skip(dir)) + return FileVisitResult.SKIP_SIBLINGS; + return FileVisitResult.CONTINUE; + } + public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) { + throw new RuntimeException(exc); + } + + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + check(file); + if (skip(file)) + return FileVisitResult.SKIP_SIBLINGS; + return FileVisitResult.CONTINUE; + } + public FileVisitResult postVisitDirectory(Path dir, IOException x) { + if (x != null) + throw new RuntimeException(x); + check(dir); + return FileVisitResult.CONTINUE; + } + public FileVisitResult visitFileFailed(Path file, IOException x) { + throw new RuntimeException(x); + } + }); + } +} diff --git a/jdk/test/java/nio/file/Files/TerminateWalk.java b/jdk/test/java/nio/file/Files/TerminateWalk.java new file mode 100644 index 00000000000..82fc8ed579f --- /dev/null +++ b/jdk/test/java/nio/file/Files/TerminateWalk.java @@ -0,0 +1,70 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Unit test for Files.walkFileTree to test TERMINATE return value + */ + +public class TerminateWalk { + + static final Random rand = new Random(); + static boolean terminated; + + static FileVisitResult maybeTerminate() { + if (terminated) + throw new RuntimeException("FileVisitor invoked after termination"); + if (rand.nextInt(10) == 0) { + terminated = true; + return FileVisitResult.TERMINATE; + } else { + return FileVisitResult.CONTINUE; + } + } + + public static void main(String[] args) throws Exception { + Path dir = Paths.get(args[0]); + + Files.walkFileTree(dir, new FileVisitor() { + public FileVisitResult preVisitDirectory(Path dir) { + return maybeTerminate(); + } + public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) { + return maybeTerminate(); + } + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + return maybeTerminate(); + } + public FileVisitResult postVisitDirectory(Path dir, IOException x) { + return maybeTerminate(); + } + public FileVisitResult visitFileFailed(Path file, IOException x) { + return maybeTerminate(); + } + }); + } +} diff --git a/jdk/test/java/nio/file/Files/content_type.sh b/jdk/test/java/nio/file/Files/content_type.sh new file mode 100644 index 00000000000..46f4626c72a --- /dev/null +++ b/jdk/test/java/nio/file/Files/content_type.sh @@ -0,0 +1,71 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4313887 +# @summary Unit test for probeContentType method +# @library .. +# @build ContentType SimpleFileTypeDetector +# @run shell content_type.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java +else + JAVA="${TESTJAVA}/bin/java" +fi + +OS=`uname -s` +case "$OS" in + Windows_* ) + CLASSPATH="${TESTCLASSES};${TESTSRC}" + ;; + * ) + CLASSPATH=${TESTCLASSES}:${TESTSRC} + ;; +esac +export CLASSPATH + +failures=0 + +go() { + echo '' + $JAVA $1 $2 $3 2>&1 + if [ $? != 0 ]; then failures=`expr $failures + 1`; fi +} + +# Run the test + +go ContentType + +# +# Results +# +echo '' +if [ $failures -gt 0 ]; + then echo "$failures test(s) failed"; + else echo "All test(s) passed"; fi +exit $failures diff --git a/jdk/test/java/nio/file/Files/walk_file_tree.sh b/jdk/test/java/nio/file/Files/walk_file_tree.sh new file mode 100644 index 00000000000..73022d31d58 --- /dev/null +++ b/jdk/test/java/nio/file/Files/walk_file_tree.sh @@ -0,0 +1,86 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4313887 +# @summary Unit test for walkFileTree method +# @build CreateFileTree PrintFileTree SkipSiblings TerminateWalk +# @run shell walk_file_tree.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java +else + JAVA="${TESTJAVA}/bin/java" +fi + +OS=`uname -s` +case "$OS" in + Windows_* ) + echo "This test does not run on Windows" + exit 0 + ;; + * ) + CLASSPATH=${TESTCLASSES}:${TESTSRC} + ;; +esac +export CLASSPATH + +# create the file tree +ROOT=`$JAVA CreateFileTree` +if [ $? != 0 ]; then exit 1; fi + +failures=0 + +# print the file tree and compare output with find(1) +$JAVA PrintFileTree "$ROOT" > out1 +find "$ROOT" > out2 +diff out1 out2 +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + +# repeat test following links (use -follow instead of -L +# to allow running on older systems) +$JAVA PrintFileTree -L "$ROOT" > out1 +find "$ROOT" -follow > out2 +diff out1 out2 +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + +# test SKIP_SIBLINGS +$JAVA SkipSiblings "$ROOT" +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + +# test TERMINATE +$JAVA TerminateWalk "$ROOT" +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi + +# clean-up +rm -r "$ROOT" + +echo '' +if [ $failures -gt 0 ]; + then echo "$failures test(s) failed"; + else echo "Test passed"; fi +exit $failures diff --git a/jdk/test/java/nio/file/Path/CopyAndMove.java b/jdk/test/java/nio/file/Path/CopyAndMove.java new file mode 100644 index 00000000000..4e4c75fd2aa --- /dev/null +++ b/jdk/test/java/nio/file/Path/CopyAndMove.java @@ -0,0 +1,983 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path copyTo/moveTo methods + * @library .. + */ + +import java.nio.ByteBuffer; +import java.nio.file.*; +import static java.nio.file.StandardCopyOption.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.io.*; +import java.util.*; + +public class CopyAndMove { + static final Random rand = new Random(); + static boolean heads() { return rand.nextBoolean(); } + static boolean supportsLinks; + + public static void main(String[] args) throws Exception { + Path dir1 = TestUtil.createTemporaryDirectory(); + try { + supportsLinks = TestUtil.supportsLinks(dir1); + + // Exercise copyTo + doCopyTests(dir1); + + // Exercise moveTo + // if test.dir differs to temporary file system then can test + // moving between devices + String testDir = System.getProperty("test.dir"); + Path dir2 = (testDir != null) ? Paths.get(testDir) : dir1; + doMoveTests(dir1, dir2); + + } finally { + TestUtil.removeAll(dir1); + } + } + + static void checkBasicAttributes(BasicFileAttributes attrs1, + BasicFileAttributes attrs2) + { + // check file type + assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile()); + assertTrue(attrs1.isDirectory() == attrs2.isDirectory()); + assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink()); + assertTrue(attrs1.isOther() == attrs2.isOther()); + + // check last modified time (assume millisecond precision) + long time1 = attrs1.resolution().toMillis(attrs1.lastModifiedTime()); + long time2 = attrs1.resolution().toMillis(attrs2.lastModifiedTime()); + assertTrue(time1 == time2); + + // check size + if (attrs1.isRegularFile()) + assertTrue(attrs1.size() == attrs2.size()); + } + + static void checkPosixAttributes(PosixFileAttributes attrs1, + PosixFileAttributes attrs2) + { + assertTrue(attrs1.permissions().equals(attrs2.permissions())); + assertTrue(attrs1.owner().equals(attrs2.owner())); + assertTrue(attrs1.group().equals(attrs2.group())); + } + + static void checkDosAttributes(DosFileAttributes attrs1, + DosFileAttributes attrs2) + { + assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly()); + assertTrue(attrs1.isHidden() == attrs2.isHidden()); + assertTrue(attrs1.isArchive() == attrs2.isArchive()); + assertTrue(attrs1.isSystem() == attrs2.isSystem()); + } + + static void checkUserDefinedFileAttributes(Map attrs1, + Map attrs2) + { + assert attrs1.size() == attrs2.size(); + for (String name: attrs1.keySet()) { + ByteBuffer bb1 = attrs1.get(name); + ByteBuffer bb2 = attrs2.get(name); + assertTrue(bb2 != null); + assertTrue(bb1.equals(bb2)); + } + } + + static Map readUserDefinedFileAttributes(Path file) + throws IOException + { + UserDefinedFileAttributeView view = file + .getFileAttributeView(UserDefinedFileAttributeView.class); + Map result = new HashMap(); + for (String name: view.list()) { + int size = view.size(name); + ByteBuffer bb = ByteBuffer.allocate(size); + int n = view.read(name, bb); + assertTrue(n == size); + bb.flip(); + result.put(name, bb); + } + return result; + } + + // move source to target with verification + static void moveAndVerify(Path source, Path target, CopyOption... options) + throws IOException + { + // read attributes before file is moved + BasicFileAttributes basicAttributes = null; + PosixFileAttributes posixAttributes = null; + DosFileAttributes dosAttributes = null; + Map namedAttributes = null; + + // get file attributes of source file + String os = System.getProperty("os.name"); + if (os.equals("SunOS") || os.equals("Linux")) { + posixAttributes = Attributes.readPosixFileAttributes(source, NOFOLLOW_LINKS); + basicAttributes = posixAttributes; + } + if (os.startsWith("Windows")) { + dosAttributes = Attributes.readDosFileAttributes(source, NOFOLLOW_LINKS); + basicAttributes = dosAttributes; + } + if (basicAttributes == null) + basicAttributes = Attributes.readBasicFileAttributes(source, NOFOLLOW_LINKS); + + // hash file contents if regular file + int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0; + + // record link target if symbolic link + Path linkTarget = null; + if (basicAttributes.isSymbolicLink()) + linkTarget = source.readSymbolicLink(); + + // read named attributes if available (and file is not a sym link) + if (!basicAttributes.isSymbolicLink() && + source.getFileStore().supportsFileAttributeView("xattr")) + { + namedAttributes = readUserDefinedFileAttributes(source); + } + + // move file + source.moveTo(target, options); + + // verify source does not exist + assertTrue(source.notExists()); + + // verify file contents + if (basicAttributes.isRegularFile()) { + if (computeHash(target) != hash) + throw new RuntimeException("Failed to verify move of regular file"); + } + + // verify link target + if (basicAttributes.isSymbolicLink()) { + if (!target.readSymbolicLink().equals(linkTarget)) + throw new RuntimeException("Failed to verify move of symbolic link"); + } + + // verify basic attributes + checkBasicAttributes(basicAttributes, + Attributes.readBasicFileAttributes(target, NOFOLLOW_LINKS)); + + // verify POSIX attributes + if (posixAttributes != null && !basicAttributes.isSymbolicLink()) { + checkPosixAttributes(posixAttributes, + Attributes.readPosixFileAttributes(target, NOFOLLOW_LINKS)); + } + + // verify DOS attributes + if (dosAttributes != null && !basicAttributes.isSymbolicLink()) { + checkDosAttributes(dosAttributes, + Attributes.readDosFileAttributes(target, NOFOLLOW_LINKS)); + } + + // verify named attributes + if (namedAttributes != null && + target.getFileStore().supportsFileAttributeView("xattr")) + { + checkUserDefinedFileAttributes(namedAttributes, readUserDefinedFileAttributes(target)); + } + } + + /** + * Tests all possible ways to invoke moveTo + */ + static void doMoveTests(Path dir1, Path dir2) throws IOException { + Path source, target, entry; + + boolean sameDevice = dir1.getFileStore().equals(dir2.getFileStore()); + + // -- regular file -- + + /** + * Test: move regular file, target does not exist + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.delete(); + + /** + * Test: move regular file, target exists + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1).createFile(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + target.delete(); + target.createDirectory(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + source.delete(); + target.delete(); + + /** + * Test: move regular file, target does not exist + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move regular file, target exists + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1).createFile(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move regular file, target exists and is empty directory + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1).createDirectory(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move regular file, target exists and is non-empty directory + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1).createDirectory(); + entry = target.resolve("foo").createFile(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + entry.delete(); + source.delete(); + target.delete(); + + /** + * Test atomic move of regular file (same file store) + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1); + moveAndVerify(source, target, ATOMIC_MOVE); + target.delete(); + + /** + * Test atomic move of regular file (different file store) + */ + if (!sameDevice) { + source = createSourceFile(dir1); + target = getTargetFile(dir2); + try { + moveAndVerify(source, target, ATOMIC_MOVE); + throw new RuntimeException("AtomicMoveNotSupportedException expected"); + } catch (AtomicMoveNotSupportedException x) { + } + source.delete(); + } + + // -- directories -- + + /* + * Test: move empty directory, target does not exist + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.delete(); + + /** + * Test: move empty directory, target exists + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1).createFile(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + target.delete(); + target.createDirectory(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + source.delete(); + target.delete(); + + /** + * Test: move empty directory, target does not exist + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move empty directory, target exists + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1).createFile(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move empty, target exists and is empty directory + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1).createDirectory(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + + /** + * Test: move empty directory, target exists and is non-empty directory + */ + source = createSourceDirectory(dir1); + target = getTargetFile(dir1).createDirectory(); + entry = target.resolve("foo").createFile(); + try { + moveAndVerify(source, target, REPLACE_EXISTING); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + entry.delete(); + source.delete(); + target.delete(); + + /** + * Test: move non-empty directory (same file system) + */ + source = createSourceDirectory(dir1); + source.resolve("foo").createFile(); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.resolve("foo").delete(); + target.delete(); + + /** + * Test: move non-empty directory (different file store) + */ + if (!sameDevice) { + source = createSourceDirectory(dir1); + source.resolve("foo").createFile(); + target = getTargetFile(dir2); + try { + moveAndVerify(source, target); + throw new RuntimeException("IOException expected"); + } catch (IOException x) { + } + source.resolve("foo").delete(); + source.delete(); + } + + /** + * Test atomic move of directory (same file store) + */ + source = createSourceDirectory(dir1); + source.resolve("foo").createFile(); + target = getTargetFile(dir1); + moveAndVerify(source, target, ATOMIC_MOVE); + target.resolve("foo").delete(); + target.delete(); + + // -- symbolic links -- + + /** + * Test: Move symbolic link to file, target does not exist + */ + if (supportsLinks) { + Path tmp = createSourceFile(dir1); + source = dir1.resolve("link").createSymbolicLink(tmp); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.delete(); + tmp.delete(); + } + + /** + * Test: Move symbolic link to directory, target does not exist + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir2); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.delete(); + } + + /** + * Test: Move broken symbolic link, target does not exists + */ + if (supportsLinks) { + Path tmp = Paths.get("doesnotexist"); + source = dir1.resolve("link").createSymbolicLink(tmp); + target = getTargetFile(dir1); + moveAndVerify(source, target); + target.delete(); + } + + /** + * Test: Move symbolic link, target exists + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir2); + target = getTargetFile(dir1).createFile(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + source.delete(); + target.delete(); + } + + /** + * Test: Move regular file, target exists + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir2); + target = getTargetFile(dir1).createFile(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + } + + /** + * Test: move symbolic link, target exists and is empty directory + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir2); + target = getTargetFile(dir1).createDirectory(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + } + + /** + * Test: symbolic link, target exists and is non-empty directory + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir2); + target = getTargetFile(dir1).createDirectory(); + entry = target.resolve("foo").createFile(); + try { + moveAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + entry.delete(); + source.delete(); + target.delete(); + } + + /** + * Test atomic move of symbolic link (same file store) + */ + if (supportsLinks) { + source = dir1.resolve("link").createSymbolicLink(dir1); + target = getTargetFile(dir1).createFile(); + moveAndVerify(source, target, REPLACE_EXISTING); + target.delete(); + } + + // -- misc. tests -- + + /** + * Test nulls + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1); + try { + source.moveTo(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + try { + source.moveTo(target, (CopyOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + try { + CopyOption[] opts = { REPLACE_EXISTING, null }; + source.moveTo(target, opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + source.delete(); + + /** + * Test UOE + */ + source = createSourceFile(dir1); + target = getTargetFile(dir1); + try { + source.moveTo(target, new CopyOption() { }); + } catch (UnsupportedOperationException x) { } + try { + source.moveTo(target, REPLACE_EXISTING, new CopyOption() { }); + } catch (UnsupportedOperationException x) { } + source.delete(); + } + + // copy source to target with verification + static void copyAndVerify(Path source, Path target, CopyOption... options) + throws IOException + { + source.copyTo(target, options); + + // get attributes of source and target file to verify copy + boolean followLinks = true; + LinkOption[] linkOptions = new LinkOption[0]; + boolean copyAttributes = false; + for (CopyOption opt : options) { + if (opt == NOFOLLOW_LINKS) { + followLinks = false; + linkOptions = new LinkOption[] { NOFOLLOW_LINKS }; + } + if (opt == COPY_ATTRIBUTES) + copyAttributes = true; + } + BasicFileAttributes basicAttributes = Attributes + .readBasicFileAttributes(source, linkOptions); + + // check hash if regular file + if (basicAttributes.isRegularFile()) + assertTrue(computeHash(source) == computeHash(target)); + + // check link target if symbolic link + if (basicAttributes.isSymbolicLink()) + assert( source.readSymbolicLink().equals(target.readSymbolicLink())); + + // check that attributes are copied + if (copyAttributes && followLinks) { + checkBasicAttributes(basicAttributes, + Attributes.readBasicFileAttributes(source, linkOptions)); + + // check POSIX attributes are copied + String os = System.getProperty("os.name"); + if (os.equals("SunOS") || os.equals("Linux")) { + checkPosixAttributes( + Attributes.readPosixFileAttributes(source, linkOptions), + Attributes.readPosixFileAttributes(target, linkOptions)); + } + + // check DOS attributes are copied + if (os.startsWith("Windows")) { + checkDosAttributes( + Attributes.readDosFileAttributes(source, linkOptions), + Attributes.readDosFileAttributes(target, linkOptions)); + } + + // check named attributes are copied + if (followLinks && + source.getFileStore().supportsFileAttributeView("xattr") && + target.getFileStore().supportsFileAttributeView("xattr")) + { + checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source), + readUserDefinedFileAttributes(target)); + } + } + } + + /** + * Tests all possible ways to invoke copyTo + */ + static void doCopyTests(Path dir) throws IOException { + Path source, target, link, entry; + + // -- regular file -- + + /** + * Test: move regular file, target does not exist + */ + source = createSourceFile(dir); + target = getTargetFile(dir); + copyAndVerify(source, target); + source.delete(); + target.delete(); + + /** + * Test: copy regular file, target exists + */ + source = createSourceFile(dir); + target = getTargetFile(dir).createFile(); + try { + copyAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + target.delete(); + target.createDirectory(); + try { + copyAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + source.delete(); + target.delete(); + + /** + * Test: copy regular file, target does not exist + */ + source = createSourceFile(dir); + target = getTargetFile(dir); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy regular file, target exists + */ + source = createSourceFile(dir); + target = getTargetFile(dir).createFile(); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy regular file, target exists and is empty directory + */ + source = createSourceFile(dir); + target = getTargetFile(dir).createDirectory(); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy regular file, target exists and is non-empty directory + */ + source = createSourceFile(dir); + target = getTargetFile(dir).createDirectory(); + entry = target.resolve("foo").createFile(); + try { + copyAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + entry.delete(); + source.delete(); + target.delete(); + + /** + * Test: copy regular file + attributes + */ + source = createSourceFile(dir); + target = getTargetFile(dir); + copyAndVerify(source, target, COPY_ATTRIBUTES); + source.delete(); + target.delete(); + + + // -- directory -- + + /* + * Test: copy directory, target does not exist + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir); + copyAndVerify(source, target); + source.delete(); + target.delete(); + + /** + * Test: copy directory, target exists + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir).createFile(); + try { + copyAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + target.delete(); + target.createDirectory(); + try { + copyAndVerify(source, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + source.delete(); + target.delete(); + + /** + * Test: copy directory, target does not exist + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy directory, target exists + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir).createFile(); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy directory, target exists and is empty directory + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir).createDirectory(); + copyAndVerify(source, target, REPLACE_EXISTING); + source.delete(); + target.delete(); + + /** + * Test: copy directory, target exists and is non-empty directory + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir).createDirectory(); + entry = target.resolve("foo").createFile(); + try { + copyAndVerify(source, target, REPLACE_EXISTING); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException x) { + } + entry.delete(); + source.delete(); + target.delete(); + + /* + * Test: copy directory + attributes + */ + source = createSourceDirectory(dir); + target = getTargetFile(dir); + copyAndVerify(source, target, COPY_ATTRIBUTES); + source.delete(); + target.delete(); + + // -- symbolic links -- + + /** + * Test: Follow link + */ + if (supportsLinks) { + source = createSourceFile(dir); + link = dir.resolve("link").createSymbolicLink(source); + target = getTargetFile(dir); + copyAndVerify(link, target); + link.delete(); + source.delete(); + } + + /** + * Test: Copy link (to file) + */ + if (supportsLinks) { + source = createSourceFile(dir); + link = dir.resolve("link").createSymbolicLink(source); + target = getTargetFile(dir); + copyAndVerify(link, target, NOFOLLOW_LINKS); + link.delete(); + source.delete(); + } + + /** + * Test: Copy link (to directory) + */ + if (supportsLinks) { + source = dir.resolve("mydir").createDirectory(); + link = dir.resolve("link").createSymbolicLink(source); + target = getTargetFile(dir); + copyAndVerify(link, target, NOFOLLOW_LINKS); + link.delete(); + source.delete(); + } + + /** + * Test: Copy broken link + */ + if (supportsLinks) { + assertTrue(source.notExists()); + link = dir.resolve("link").createSymbolicLink(source); + target = getTargetFile(dir); + copyAndVerify(link, target, NOFOLLOW_LINKS); + link.delete(); + } + + /** + * Test: Copy link to UNC (Windows only) + */ + if (supportsLinks && + System.getProperty("os.name").startsWith("Windows")) + { + Path unc = Paths.get("\\\\rialto\\share\\file"); + link = dir.resolve("link").createSymbolicLink(unc); + target = getTargetFile(dir); + copyAndVerify(link, target, NOFOLLOW_LINKS); + link.delete(); + } + + // -- misc. tests -- + + /** + * Test nulls + */ + source = createSourceFile(dir); + target = getTargetFile(dir); + try { + source.copyTo(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + try { + source.copyTo(target, (CopyOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + try { + CopyOption[] opts = { REPLACE_EXISTING, null }; + source.copyTo(target, opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + source.delete(); + + /** + * Test UOE + */ + source = createSourceFile(dir); + target = getTargetFile(dir); + try { + source.copyTo(target, new CopyOption() { }); + } catch (UnsupportedOperationException x) { } + try { + source.copyTo(target, REPLACE_EXISTING, new CopyOption() { }); + } catch (UnsupportedOperationException x) { } + source.delete(); + } + + + static void assertTrue(boolean value) { + if (!value) + throw new RuntimeException("Assertion failed"); + } + + // computes simple hash of the given file + static int computeHash(Path file) throws IOException { + int h = 0; + + InputStream in = file.newInputStream(); + try { + byte[] buf = new byte[1024]; + int n; + do { + n = in.read(buf); + for (int i=0; i 0); + } finally { + in.close(); + } + return h; + } + + // create file of random size in given directory + static Path createSourceFile(Path dir) throws IOException { + String name = "source" + Integer.toString(rand.nextInt()); + Path file = dir.resolve(name).createFile(); + byte[] bytes = new byte[rand.nextInt(128*1024)]; + rand.nextBytes(bytes); + OutputStream out = file.newOutputStream(); + try { + out.write(bytes); + } finally { + out.close(); + } + randomizeAttributes(file); + return file; + } + + // create directory in the given directory + static Path createSourceDirectory(Path dir) throws IOException { + String name = "sourcedir" + Integer.toString(rand.nextInt()); + Path subdir = dir.resolve(name).createDirectory(); + randomizeAttributes(subdir); + return subdir; + } + + // "randomize" the file attributes of the given file. + static void randomizeAttributes(Path file) throws IOException { + String os = System.getProperty("os.name"); + boolean isWindows = os.startsWith("Windows"); + boolean isUnix = os.equals("SunOS") || os.equals("Linux"); + boolean isDirectory = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS) + .isDirectory(); + + if (isUnix) { + Set perms = Attributes + .readPosixFileAttributes(file, NOFOLLOW_LINKS).permissions(); + PosixFilePermission[] toChange = { + PosixFilePermission.GROUP_READ, + PosixFilePermission.GROUP_WRITE, + PosixFilePermission.GROUP_EXECUTE, + PosixFilePermission.OTHERS_READ, + PosixFilePermission.OTHERS_WRITE, + PosixFilePermission.OTHERS_EXECUTE + }; + for (PosixFilePermission perm: toChange) { + if (heads()) { + perms.add(perm); + } else { + perms.remove(perm); + } + } + Attributes.setPosixFilePermissions(file, perms); + } + + if (isWindows) { + DosFileAttributeView view = file + .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS); + // only set or unset the hidden attribute + view.setHidden(heads()); + } + + boolean addUserDefinedFileAttributes = heads() && + file.getFileStore().supportsFileAttributeView("xattr"); + + // remove this when copying a direcory copies its named streams + if (isWindows && isDirectory) addUserDefinedFileAttributes = false; + + if (addUserDefinedFileAttributes) { + UserDefinedFileAttributeView view = file + .getFileAttributeView(UserDefinedFileAttributeView.class); + int n = rand.nextInt(16); + while (n > 0) { + byte[] value = new byte[1 + rand.nextInt(100)]; + view.write("user." + Integer.toString(n), ByteBuffer.wrap(value)); + n--; + } + } + } + + // create name for file in given directory + static Path getTargetFile(Path dir) throws IOException { + String name = "target" + Integer.toString(rand.nextInt()); + return dir.resolve(name); + } + } diff --git a/jdk/test/java/nio/file/Path/DeleteOnClose.java b/jdk/test/java/nio/file/Path/DeleteOnClose.java new file mode 100644 index 00000000000..8bc0e852c3e --- /dev/null +++ b/jdk/test/java/nio/file/Path/DeleteOnClose.java @@ -0,0 +1,77 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.io.*; +import java.util.*; + +public class DeleteOnClose { + + public static void main(String[] args) throws IOException { + // open file but do not close it. Its existance will be checked by + // the calling script. + Paths.get(args[0]).newByteChannel(READ, WRITE, DELETE_ON_CLOSE); + + // check temporary file has been deleted after closing it + Path file = File.createTempFile("blah", "tmp").toPath(); + file.newByteChannel(READ, WRITE, DELETE_ON_CLOSE).close(); + if (file.exists()) + throw new RuntimeException("Temporary file was not deleted"); + + Path dir = TestUtil.createTemporaryDirectory(); + try { + // check that DELETE_ON_CLOSE fails when file is a sym link + if (TestUtil.supportsLinks(dir)) { + file = dir.resolve("foo").createFile(); + Path link = dir.resolve("link").createSymbolicLink(file); + try { + link.newByteChannel(READ, WRITE, DELETE_ON_CLOSE); + throw new RuntimeException("IOException expected"); + } catch (IOException ignore) { } + } + + // check that DELETE_ON_CLOSE works with files created via open + // directories + DirectoryStream stream = dir.newDirectoryStream(); + try { + if (stream instanceof SecureDirectoryStream) { + SecureDirectoryStream secure = (SecureDirectoryStream)stream; + file = Paths.get("foo"); + + Set opts = new HashSet(); + opts.add(WRITE); + opts.add(DELETE_ON_CLOSE); + secure.newByteChannel(file, opts).close(); + + if (dir.resolve(file).exists()) + throw new RuntimeException("File not deleted"); + } + } finally { + stream.close(); + } + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/Path/InterruptCopy.java b/jdk/test/java/nio/file/Path/InterruptCopy.java new file mode 100644 index 00000000000..d7962224eb1 --- /dev/null +++ b/jdk/test/java/nio/file/Path/InterruptCopy.java @@ -0,0 +1,119 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for Sun-specific ExtendedCopyOption.INTERRUPTIBLE option + * @library .. + * @run main/othervm -XX:-UseVMInterruptibleIO InterruptCopy + */ + +import java.nio.file.*; +import java.nio.file.attribute.Attributes; +import java.io.*; +import java.util.concurrent.*; +import com.sun.nio.file.ExtendedCopyOption; + +public class InterruptCopy { + + private static final long FILE_SIZE_TO_COPY = 512 * 1024 * 1024; + private static final int DELAY_IN_MS = 500; + + public static void main(String[] args) throws Exception { + Path dir = TestUtil.createTemporaryDirectory(); + try { + FileStore store = dir.getFileStore(); + System.out.format("Checking space (%s)\n", store); + long usableSpace = Attributes + .readFileStoreSpaceAttributes(store).usableSpace(); + if (usableSpace < 2*FILE_SIZE_TO_COPY) { + System.out.println("Insufficient disk space to run test."); + return; + } + doTest(dir); + } finally { + TestUtil.removeAll(dir); + } + } + + static void doTest(Path dir) throws Exception { + final Path source = dir.resolve("foo"); + final Path target = dir.resolve("bar"); + + // create source file (don't create it as sparse file because we + // require the copy to take a long time) + System.out.println("Creating source file..."); + byte[] buf = new byte[32*1024]; + long total = 0; + OutputStream out = source.newOutputStream(); + try { + do { + out.write(buf); + total += buf.length; + } while (total < FILE_SIZE_TO_COPY); + } finally { + out.close(); + } + System.out.println("Source file created."); + + ScheduledExecutorService pool = + Executors.newSingleThreadScheduledExecutor(); + try { + // copy source to target in main thread, interrupting it after a delay + final Thread me = Thread.currentThread(); + pool.schedule(new Runnable() { + public void run() { + me.interrupt(); + }}, DELAY_IN_MS, TimeUnit.MILLISECONDS); + System.out.println("Copying file..."); + try { + source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE); + throw new RuntimeException("Copy completed (this is not expected)"); + } catch (IOException e) { + boolean interrupted = Thread.interrupted(); + if (!interrupted) + throw new RuntimeException("Interrupt status was not set"); + System.out.println("Copy failed (this is expected)"); + } + + // copy source to target via task in thread pool, interrupting it after + // a delay using cancel(true) + Future result = pool.submit(new Callable() { + public Void call() throws IOException { + System.out.println("Copying file..."); + source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE, + StandardCopyOption.REPLACE_EXISTING); + return null; + } + }); + Thread.sleep(DELAY_IN_MS); + boolean cancelled = result.cancel(true); + if (!cancelled) + result.get(); + System.out.println("Copy cancelled."); + } finally { + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + } + } +} diff --git a/jdk/test/java/nio/file/Path/Links.java b/jdk/test/java/nio/file/Path/Links.java new file mode 100644 index 00000000000..3b0d6daeaa8 --- /dev/null +++ b/jdk/test/java/nio/file/Path/Links.java @@ -0,0 +1,147 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path createSymbolicLink, + * readSymbolicLink, and createLink methods + * @library .. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.*; +import java.util.*; + +public class Links { + + static final boolean isWindows = + System.getProperty("os.name").startsWith("Windows"); + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion failed"); + } + + /** + * Exercise createSymbolicLink and readLink methods + */ + static void testSymLinks(Path dir) throws IOException { + Path link = dir.resolve("link"); + + // Check if sym links are supported + try { + link.createSymbolicLink(Paths.get("foo")); + link.delete(); + } catch (UnsupportedOperationException x) { + // sym links not supported + return; + } catch (IOException x) { + // probably insufficient privileges to create sym links (Windows) + return; + } + + // Test links to various targets + String[] windowsTargets = + { "foo", "C:\\foo", "\\foo", "\\\\server\\share\\foo" }; + String[] otherTargets = { "relative", "/absolute" }; + + String[] targets = (isWindows) ? windowsTargets : otherTargets; + for (String s: targets) { + Path target = Paths.get(s); + link.createSymbolicLink(target); + try { + assertTrue(link.readSymbolicLink().equals(target)); + } finally { + link.delete(); + } + } + } + + /** + * Exercise createLink method + */ + static void testHardLinks(Path dir) throws IOException { + Path foo = dir.resolve("foo").createFile(); + try { + Path bar; + try { + bar = dir.resolve("bar").createLink(foo); + } catch (UnsupportedOperationException x) { + return; + } catch (IOException x) { + // probably insufficient privileges (Windows) + return; + } + try { + Object key1 = Attributes + .readBasicFileAttributes(foo).fileKey(); + Object key2 = Attributes + .readBasicFileAttributes(bar).fileKey(); + assertTrue((key1 == null) || (key1.equals(key2))); + +// Testing of linkCount disabled until linkCount method removed frmo +// BasicFileAttributes +/* + assertTrue(Attributes + .readBasicFileAttributes(foo).linkCount() >= 2); + assertTrue(Attributes + .readBasicFileAttributes(bar).linkCount() >= 2); +*/ + + } finally { + bar.delete(); + } + + + } finally { + foo.delete(); + } + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + testSymLinks(dir); + testHardLinks(dir); + + // repeat tests on Windows with long path + if (isWindows) { + Path dirWithLongPath = null; + try { + dirWithLongPath = TestUtil.createDirectoryWithLongPath(dir); + } catch (IOException x) { + System.out.println("Unable to create long path: " + x); + } + if (dirWithLongPath != null) { + System.out.println(""); + System.out.println("** REPEAT TESTS WITH LONG PATH **"); + testSymLinks(dirWithLongPath); + testHardLinks(dirWithLongPath); + } + } + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/Path/Misc.java b/jdk/test/java/nio/file/Path/Misc.java new file mode 100644 index 00000000000..ba6640f7f34 --- /dev/null +++ b/jdk/test/java/nio/file/Path/Misc.java @@ -0,0 +1,389 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path for miscellenous methods not + * covered by other tests + * @library .. + */ + +import java.nio.file.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.io.*; +import java.util.*; + +public class Misc { + static final boolean isWindows = + System.getProperty("os.name").startsWith("Windows"); + static boolean supportsLinks; + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + supportsLinks = TestUtil.supportsLinks(dir); + + // equals and hashCode methods + equalsAndHashCode(); + + // checkAccess method + checkAccessTests(dir); + + // getFileAttributeView methods + getFileAttributeViewTests(dir); + + // toRealPath method + toRealPathTests(dir); + + // isSameFile method + isSameFileTests(dir); + + // isHidden method + isHiddenTests(dir); + + } finally { + TestUtil.removeAll(dir); + } + } + + /** + * Exercise equals and hashCode methods + */ + static void equalsAndHashCode() { + + Path thisFile = Paths.get("this"); + Path thatFile = Paths.get("that"); + + assertTrue(thisFile.equals(thisFile)); + assertTrue(!thisFile.equals(thatFile)); + + assertTrue(!thisFile.equals(null)); + assertTrue(!thisFile.equals(new Object())); + + Path likeThis = Paths.get("This"); + if (isWindows) { + // case insensitive + assertTrue(thisFile.equals(likeThis)); + assertTrue(thisFile.hashCode() == likeThis.hashCode()); + } else { + // case senstive + assertTrue(!thisFile.equals(likeThis)); + } + } + + /** + * Exercise checkAccess method + */ + static void checkAccessTests(Path dir) throws IOException { + final Path file = dir.resolve("foo").createFile(); + + /** + * Test: This directory should readable and writable + */ + dir.checkAccess(); + dir.checkAccess(AccessMode.READ); + dir.checkAccess(AccessMode.WRITE); + dir.checkAccess(AccessMode.READ, AccessMode.WRITE); + + /** + * Test: File does not exist + */ + Path doesNotExist = dir.resolve("thisDoesNotExists"); + try { + doesNotExist.checkAccess(); + throw new RuntimeException("NoSuchFileException expected"); + } catch (NoSuchFileException x) { + } + try { + doesNotExist.checkAccess(AccessMode.READ); + throw new RuntimeException("NoSuchFileException expected"); + } catch (NoSuchFileException x) { + } + try { + doesNotExist.checkAccess(AccessMode.WRITE); + throw new RuntimeException("NoSuchFileException expected"); + } catch (NoSuchFileException x) { + } + try { + doesNotExist.checkAccess(AccessMode.EXECUTE); + throw new RuntimeException("NoSuchFileException expected"); + } catch (NoSuchFileException x) { + } + + /** + * Test: Edit ACL to deny WRITE and EXECUTE + */ + AclFileAttributeView view = file + .getFileAttributeView(AclFileAttributeView.class); + if (view != null && + file.getFileStore().supportsFileAttributeView("acl")) + { + UserPrincipal owner = view.getOwner(); + List acl = view.getAcl(); + + // Insert entry to deny WRITE and EXECUTE + AclEntry entry = AclEntry.newBuilder() + .setType(AclEntryType.DENY) + .setPrincipal(owner) + .setPermissions(AclEntryPermission.WRITE_DATA, + AclEntryPermission.EXECUTE) + .build(); + acl.add(0, entry); + view.setAcl(acl); + + try { + file.checkAccess(AccessMode.WRITE); + throw new RuntimeException("AccessDeniedException expected"); + } catch (AccessDeniedException x) { + } + + try { + file.checkAccess(AccessMode.EXECUTE); + throw new RuntimeException("AccessDeniedException expected"); + } catch (AccessDeniedException x) { + } + + + // Restore ACL + acl.remove(0); + view.setAcl(acl); + } + + /** + * Test: Windows DOS read-only attribute + */ + if (isWindows) { + DosFileAttributeView dview = + file.getFileAttributeView(DosFileAttributeView.class); + dview.setReadOnly(true); + try { + file.checkAccess(AccessMode.WRITE); + throw new RuntimeException("AccessDeniedException expected"); + } catch (AccessDeniedException x) { + } + dview.setReadOnly(false); + + // Read-only attribute does not make direcory read-only + dview = dir.getFileAttributeView(DosFileAttributeView.class); + boolean save = dview.readAttributes().isReadOnly(); + dview.setReadOnly(true); + dir.checkAccess(AccessMode.WRITE); + dview.setReadOnly(save); + } + + /** + * Test: null + */ + try { + file.checkAccess((AccessMode)null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + + // clean-up + file.delete(); + } + + /** + * Exercise getFileAttributeFile methods + */ + static void getFileAttributeViewTests(Path dir) { + assertTrue(dir.getFileAttributeView(BasicFileAttributeView.class) + instanceof BasicFileAttributeView); + assertTrue(dir.getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) + instanceof BasicFileAttributeView); + assertTrue(dir.getFileAttributeView("basic") + instanceof BasicFileAttributeView); + assertTrue(dir.getFileAttributeView("basic", NOFOLLOW_LINKS) + instanceof BasicFileAttributeView); + assertTrue(dir.getFileAttributeView(BogusFileAttributeView.class) == null); + assertTrue(dir.getFileAttributeView("bogus") == null); + try { + dir.getFileAttributeView((Class)null); + } catch (NullPointerException ignore) { } + try { + dir.getFileAttributeView(BasicFileAttributeView.class, (LinkOption[])null); + } catch (NullPointerException ignore) { } + try { + dir.getFileAttributeView(BasicFileAttributeView.class, (LinkOption)null); + } catch (NullPointerException ignore) { } + try { + dir.getFileAttributeView((String)null); + } catch (NullPointerException ignore) { } + try { + dir.getFileAttributeView("basic", (LinkOption[])null); + } catch (NullPointerException ignore) { } + try { + dir.getFileAttributeView("basic", (LinkOption)null); + } catch (NullPointerException ignore) { } + + } + interface BogusFileAttributeView extends FileAttributeView { } + + /** + * Exercise toRealPath method + */ + static void toRealPathTests(Path dir) throws IOException { + final Path file = dir.resolve("foo").createFile(); + final Path link = dir.resolve("link"); + + /** + * Test: toRealPath(true) will access same file as toRealPath(false) + */ + assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false))); + + /** + * Test: toRealPath(true) should resolve links + */ + if (supportsLinks) { + link.createSymbolicLink(file.toAbsolutePath()); + assertTrue(link.toRealPath(true).equals(file.toRealPath(true))); + link.delete(); + } + + + /** + * Test: toRealPath(false) should not resolve links + */ + if (supportsLinks) { + link.createSymbolicLink(file.toAbsolutePath()); + assertTrue(link.toRealPath(false).getName().equals(link.getName())); + link.delete(); + } + + /** + * Test: toRealPath should eliminate "." + */ + assertTrue(dir.resolve(".").toRealPath(true).equals(dir.toRealPath(true))); + assertTrue(dir.resolve(".").toRealPath(false).equals(dir.toRealPath(false))); + + /** + * Test: toRealPath should eliminate ".." when it doesn't follow a + * symbolic link + */ + Path subdir = dir.resolve("subdir").createDirectory(); + assertTrue(subdir.resolve("..").toRealPath(true).equals(dir.toRealPath(true))); + assertTrue(subdir.resolve("..").toRealPath(false).equals(dir.toRealPath(false))); + subdir.delete(); + + // clean-up + file.delete(); + } + + /** + * Exercise isSameFile method + */ + static void isSameFileTests(Path dir) throws IOException { + Path thisFile = dir.resolve("thisFile"); + Path thatFile = dir.resolve("thatFile"); + + /** + * Test: isSameFile for self and null + */ + assertTrue(thisFile.isSameFile(thisFile)); + assertTrue(!thisFile.isSameFile(null)); + + /** + * Test: Neither files exist + */ + try { + thisFile.isSameFile(thatFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + try { + thatFile.isSameFile(thisFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + + thisFile.createFile(); + try { + /** + * Test: One file exists + */ + try { + thisFile.isSameFile(thatFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + try { + thatFile.isSameFile(thisFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + + thatFile.createFile(); + + /** + * Test: Both file exists + */ + try { + assertTrue(!thisFile.isSameFile(thatFile)); + assertTrue(!thatFile.isSameFile(thisFile)); + } finally { + TestUtil.deleteUnchecked(thatFile); + } + + /** + * Test: Symbolic links + */ + if (supportsLinks) { + thatFile.createSymbolicLink(thisFile); + try { + assertTrue(thisFile.isSameFile(thatFile)); + assertTrue(thatFile.isSameFile(thisFile)); + } finally { + TestUtil.deleteUnchecked(thatFile); + } + } + } finally { + thisFile.delete(false); + } + } + + /** + * Exercise isHidden method + */ + static void isHiddenTests(Path dir) throws IOException { + assertTrue(!dir.isHidden()); + + Path file = dir.resolve(".foo"); + if (isWindows) { + file.createFile(); + try { + Attributes.setAttribute(file, "dos:hidden", true); + assertTrue(file.isHidden()); + } finally { + file.delete(); + } + } else { + assertTrue(file.isHidden()); + } + } + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion Failed"); + } +} diff --git a/jdk/test/java/nio/file/Path/PathOps.java b/jdk/test/java/nio/file/Path/PathOps.java new file mode 100644 index 00000000000..231123c7d9a --- /dev/null +++ b/jdk/test/java/nio/file/Path/PathOps.java @@ -0,0 +1,752 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path path operations + */ + +import java.nio.file.*; + +public class PathOps { + + static final java.io.PrintStream out = System.out; + + private String input; + private Path path; + private Exception exc; + + private PathOps(String s) { + out.println(); + input = s; + try { + path = FileSystems.getDefault().getPath(s); + out.format("%s -> %s", s, path); + } catch (Exception x) { + exc = x; + out.format("%s -> %s", s, x); + } + out.println(); + } + + Path path() { + return path; + } + + void fail() { + throw new RuntimeException("PathOps failed"); + } + + void checkPath() { + if (path == null) { + throw new InternalError("path is null"); + } + } + + void check(Object result, String expected) { + out.format("\tExpected: %s\n", expected); + out.format("\tActual: %s\n", result); + if (result == null) { + if (expected == null) return; + } else { + // compare string representations + if (expected != null && result.toString().equals(expected.toString())) + return; + } + fail(); + } + + void check(Object result, boolean expected) { + check(result, Boolean.toString(expected)); + } + + PathOps root(String expected) { + out.println("check root"); + checkPath(); + check(path.getRoot(), expected); + return this; + } + + PathOps parent(String expected) { + out.println("check parent"); + checkPath(); + check(path.getParent(), expected); + return this; + } + + PathOps name(String expected) { + out.println("check name"); + checkPath(); + check(path.getName(), expected); + return this; + } + + PathOps element(int index, String expected) { + out.format("check element %d\n", index); + checkPath(); + check(path.getName(index), expected); + return this; + } + + PathOps subpath(int startIndex, int endIndex, String expected) { + out.format("test subpath(%d,%d)\n", startIndex, endIndex); + checkPath(); + check(path.subpath(startIndex, endIndex), expected); + return this; + } + + PathOps starts(String prefix) { + out.format("test startsWith with %s\n", prefix); + checkPath(); + Path s = FileSystems.getDefault().getPath(prefix); + check(path.startsWith(s), true); + return this; + } + + PathOps notStarts(String prefix) { + out.format("test not startsWith with %s\n", prefix); + checkPath(); + Path s = FileSystems.getDefault().getPath(prefix); + check(path.startsWith(s), false); + return this; + } + + PathOps ends(String suffix) { + out.format("test endsWith %s\n", suffix); + checkPath(); + Path s = FileSystems.getDefault().getPath(suffix); + check(path.endsWith(s), true); + return this; + } + + PathOps notEnds(String suffix) { + out.format("test not endsWith %s\n", suffix); + checkPath(); + Path s = FileSystems.getDefault().getPath(suffix); + check(path.endsWith(s), false); + return this; + } + + PathOps absolute() { + out.println("check path is absolute"); + checkPath(); + check(path.isAbsolute(), true); + return this; + } + + PathOps notAbsolute() { + out.println("check path is not absolute"); + checkPath(); + check(path.isAbsolute(), false); + return this; + } + + PathOps resolve(String other, String expected) { + out.format("test resolve %s\n", other); + checkPath(); + check(path.resolve(other), expected); + return this; + } + + PathOps relativize(String other, String expected) { + out.format("test relativize %s\n", other); + checkPath(); + Path that = FileSystems.getDefault().getPath(other); + check(path.relativize(that), expected); + return this; + } + + PathOps normalize(String expected) { + out.println("check normalized path"); + checkPath(); + check(path.normalize(), expected); + return this; + } + + PathOps string(String expected) { + out.println("check string representation"); + checkPath(); + check(path, expected); + return this; + } + + PathOps invalid() { + if (!(exc instanceof InvalidPathException)) { + out.println("InvalidPathException not thrown as expected"); + fail(); + } + return this; + } + + static PathOps test(String s) { + return new PathOps(s); + } + + // -- PathOpss -- + + static void header(String s) { + out.println(); + out.println(); + out.println("-- " + s + " --"); + } + + static void doWindowsTests() { + header("Windows specific tests"); + + // all components present + test("C:\\a\\b\\c") + .root("C:\\") + .parent("C:\\a\\b") + .name("c"); + test("C:a\\b\\c") + .root("C:") + .parent("C:a\\b") + .name("c"); + test("\\\\server\\share\\a") + .root("\\\\server\\share\\") + .parent("\\\\server\\share\\") + .name("a"); + + // root component only + test("C:\\") + .root("C:\\") + .parent(null) + .name(null); + test("C:") + .root("C:") + .parent(null) + .name(null); + test("\\\\server\\share\\") + .root("\\\\server\\share\\") + .parent(null) + .name(null); + + // no root component + test("a\\b") + .root(null) + .parent("a") + .name("b"); + + // name component only + test("foo") + .root(null) + .parent(null) + .name("foo"); + + // startsWith + test("C:\\") + .starts("C:\\") + .starts("c:\\") + .notStarts("C") + .notStarts("C:"); + test("C:") + .starts("C:") + .starts("c:") + .notStarts("C"); + test("\\") + .starts("\\"); + test("C:\\foo\\bar") + .starts("C:\\") + .starts("C:\\foo") + .starts("C:\\FOO") + .starts("C:\\foo\\bar") + .starts("C:\\Foo\\Bar") + .notStarts("C:") + .notStarts("C") + .notStarts("C:foo"); + test("\\foo\\bar") + .starts("\\") + .starts("\\foo") + .starts("\\foO") + .starts("\\foo\\bar") + .starts("\\fOo\\BaR") + .notStarts("foo") + .notStarts("foo\\bar"); + test("foo\\bar") + .starts("foo") + .starts("foo\\bar") + .notStarts("\\"); + test("\\\\server\\share") + .starts("\\\\server\\share") + .starts("\\\\server\\share\\") + .notStarts("\\"); + + // endsWith + test("C:\\") + .ends("C:\\") + .ends("c:\\") + .notEnds("\\"); + test("C:") + .ends("C:") + .ends("c:"); + test("\\") + .ends("\\"); + test("C:\\foo\\bar") + .ends("bar") + .ends("BAR") + .ends("foo\\bar") + .ends("Foo\\Bar") + .ends("C:\\foo\\bar") + .ends("c:\\foO\\baR") + .notEnds("r") + .notEnds("\\foo\\bar"); + test("\\foo\\bar") + .ends("bar") + .ends("BaR") + .ends("foo\\bar") + .ends("foO\\baR") + .ends("\\foo\\bar") + .ends("\\Foo\\Bar") + .notEnds("oo\\bar"); + test("foo\\bar") + .ends("bar") + .ends("BAR") + .ends("foo\\bar") + .ends("Foo\\Bar") + .notEnds("ar"); + test("\\\\server\\share") + .ends("\\\\server\\share") + .ends("\\\\server\\share\\") + .notEnds("shared") + .notEnds("\\"); + + // elements + test("C:\\a\\b\\c") + .element(0, "a") + .element(1, "b") + .element(2, "c"); + test("foo.bar\\gus.alice") + .element(0, "foo.bar") + .element(1, "gus.alice"); + + // subpath + test("C:\\foo") + .subpath(0, 1, "foo"); + test("C:foo") + .subpath(0, 1, "foo"); + test("foo") + .subpath(0, 1, "foo"); + test("C:\\foo\\bar\\gus") + .subpath(0, 1, "foo") + .subpath(0, 2, "foo\\bar") + .subpath(0, 3, "foo\\bar\\gus") + .subpath(1, 2, "bar") + .subpath(1, 3, "bar\\gus") + .subpath(2, 3, "gus"); + test("\\\\server\\share\\foo") + .subpath(0, 1, "foo"); + + // isAbsolute + test("foo").notAbsolute(); + test("C:").notAbsolute(); + test("C:\\").absolute(); + test("C:\\abc").absolute(); + test("\\\\server\\share\\").absolute(); + + // resolve + test("C:\\") + .resolve("foo", "C:\\foo") + .resolve("D:\\bar", "D:\\bar") + .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolve("C:foo", "C:\\foo") + .resolve("D:foo", "D:foo"); + test("\\") + .resolve("foo", "\\foo") + .resolve("D:bar", "D:bar") + .resolve("C:\\bar", "C:\\bar") + .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolve("\\foo", "\\foo"); + test("\\foo") + .resolve("bar", "\\foo\\bar") + .resolve("D:bar", "D:bar") + .resolve("C:\\bar", "C:\\bar") + .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolve("\\bar", "\\bar"); + test("foo") + .resolve("bar", "foo\\bar") + .resolve("D:\\bar", "D:\\bar") + .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolve("C:bar", "C:bar") + .resolve("D:foo", "D:foo"); + test("C:") + .resolve("foo", "C:foo"); + test("\\\\server\\share\\foo") + .resolve("bar", "\\\\server\\share\\foo\\bar") + .resolve("\\bar", "\\\\server\\share\\bar") + .resolve("D:\\bar", "D:\\bar") + .resolve("\\\\other\\share\\bar", "\\\\other\\share\\bar") + .resolve("D:bar", "D:bar"); + + // relativize + test("foo\\bar") + .relativize("foo\\bar", null) + .relativize("foo", ".."); + test("C:\\a\\b\\c") + .relativize("C:\\a", "..\\.."); + test("\\\\server\\share\\foo") + .relativize("\\\\server\\share\\bar", "..\\bar"); + + // normalize + test("C:\\") + .normalize("C:\\"); + test("C:\\.") + .normalize("C:\\"); + test("C:\\..") + .normalize("C:\\"); + test("\\\\server\\share") + .normalize("\\\\server\\share\\"); + test("\\\\server\\share\\.") + .normalize("\\\\server\\share\\"); + test("\\\\server\\share\\..") + .normalize("\\\\server\\share\\"); + test("C:") + .normalize("C:"); + test("C:.") + .normalize("C:"); + test("C:..") + .normalize("C:.."); + test("\\") + .normalize("\\"); + test("\\.") + .normalize("\\"); + test("\\..") + .normalize("\\"); + test("foo") + .normalize("foo"); + test("foo\\.") + .normalize("foo"); + test("foo\\..") + .normalize(null); + test("C:\\foo") + .normalize("C:\\foo"); + test("C:\\foo\\.") + .normalize("C:\\foo"); + test("C:\\.\\foo") + .normalize("C:\\foo"); + test("C:\\foo\\..") + .normalize("C:\\"); + test("C:\\..\\foo") + .normalize("C:\\foo"); + test("\\\\server\\share\\foo") + .normalize("\\\\server\\share\\foo"); + test("\\\\server\\share\\foo\\.") + .normalize("\\\\server\\share\\foo"); + test("\\\\server\\share\\.\\foo") + .normalize("\\\\server\\share\\foo"); + test("\\\\server\\share\\foo\\..") + .normalize("\\\\server\\share\\"); + test("\\\\server\\share\\..\\foo") + .normalize("\\\\server\\share\\foo"); + test("C:foo") + .normalize("C:foo"); + test("C:foo\\.") + .normalize("C:foo"); + test("C:.\\foo") + .normalize("C:foo"); + test("C:foo\\..") + .normalize("C:"); + test("C:..\\foo") + .normalize("C:..\\foo"); + test("\\foo") + .normalize("\\foo"); + test("\\foo\\.") + .normalize("\\foo"); + test("\\.\\foo") + .normalize("\\foo"); + test("\\foo\\..") + .normalize("\\"); + test("\\..\\foo") + .normalize("\\foo"); + test(".") + .normalize(null); + test("..") + .normalize(".."); + test("\\..\\..") + .normalize("\\"); + test("..\\..\\foo") + .normalize("..\\..\\foo"); + test("foo\\bar\\..") + .normalize("foo"); + test("foo\\bar\\.\\..") + .normalize("foo"); + test("foo\\bar\\gus\\..\\..") + .normalize("foo"); + test(".\\foo\\.\\bar\\.\\gus\\..\\.\\..") + .normalize("foo"); + + // UNC corner cases + test("\\\\server\\share\\") + .root("\\\\server\\share\\") + .parent(null) + .name(null); + test("\\\\server") + .invalid(); + test("\\\\server\\") + .invalid(); + test("\\\\server\\share") + .root("\\\\server\\share\\") + .parent(null) + .name(null); + + // invalid + test(":\\foo") + .invalid(); + test("C::") + .invalid(); + test("C:\\?") // invalid character + .invalid(); + test("C:\\*") // invalid character + .invalid(); + test("C:\\abc\u0001\\foo") + .invalid(); + test("C:\\\u0019\\foo") + .invalid(); + test("\\\\server\u0019\\share") + .invalid(); + test("\\\\server\\share\u0019") + .invalid(); + test("foo\u0000\bar") + .invalid(); + test("C:\\foo ") // trailing space + .invalid(); + test("C:\\foo \\bar") + .invalid(); + //test("C:\\foo.") // trailing dot + //.invalid(); + //test("C:\\foo...\\bar") + //.invalid(); + + // normalization at construction time (remove redundant and replace slashes) + test("C:/a/b/c") + .string("C:\\a\\b\\c") + .root("C:\\") + .parent("C:\\a\\b"); + test("C://a//b//c") + .string("C:\\a\\b\\c") + .root("C:\\") + .parent("C:\\a\\b"); + + // hashCode + header("hashCode"); + int h1 = test("C:\\foo").path().hashCode(); + int h2 = test("c:\\FOO").path().hashCode(); + if (h1 != h2) + throw new RuntimeException("PathOps failed"); + } + + static void doUnixTests() { + header("Unix specific tests"); + + // all components + test("/a/b/c") + .root("/") + .parent("/a/b") + .name("c"); + + // root component only + test("/") + .root("/") + .parent(null) + .name(null); + + // no root component + test("a/b") + .root(null) + .parent("a") + .name("b"); + + // name component only + test("foo") + .root(null) + .parent(null) + .name("foo"); + + // startsWith + test("/") + .starts("/") + .notStarts("/foo"); + test("/foo") + .starts("/") + .starts("/foo") + .notStarts("/f"); + test("/foo/bar") + .starts("/") + .starts("/foo") + .starts("/foo/bar") + .notStarts("/f") + .notStarts("foo") + .notStarts("foo/bar"); + test("foo") + .starts("foo") + .notStarts("f"); + test("foo/bar") + .starts("foo") + .starts("foo/bar") + .notStarts("f") + .notStarts("/foo") + .notStarts("/foo/bar"); + + // endsWith + test("/") + .ends("/") + .notEnds("foo") + .notEnds("/foo"); + test("/foo") + .ends("foo") + .ends("/foo") + .notEnds("/"); + test("/foo/bar") + .ends("bar") + .ends("foo/bar") + .ends("/foo/bar") + .notEnds("/bar"); + test("foo") + .ends("foo"); + test("foo/bar") + .ends("bar") + .ends("foo/bar"); + + // elements + test("a/b/c") + .element(0,"a") + .element(1,"b") + .element(2,"c"); + + // isAbsolute + test("/") + .absolute(); + test("/tmp") + .absolute(); + test("tmp") + .notAbsolute(); + + // resolve + test("/tmp") + .resolve("foo", "/tmp/foo") + .resolve("/foo", "/foo"); + test("tmp") + .resolve("foo", "tmp/foo") + .resolve("/foo", "/foo"); + + // relativize + test("/a/b/c") + .relativize("/a/b/c", null) + .relativize("/a/b/c/d/e", "d/e") + .relativize("/a/x", "../../x"); + + // normalize + test("/") + .normalize("/"); + test("foo") + .normalize("foo"); + test("/foo") + .normalize("/foo"); + test(".") + .normalize(null); + test("..") + .normalize(".."); + test("/..") + .normalize("/"); + test("/../..") + .normalize("/"); + test("foo/.") + .normalize("foo"); + test("./foo") + .normalize("foo"); + test("foo/..") + .normalize(null); + test("../foo") + .normalize("../foo"); + test("../../foo") + .normalize("../../foo"); + test("foo/bar/..") + .normalize("foo"); + test("foo/bar/gus/../..") + .normalize("foo"); + test("/foo/bar/gus/../..") + .normalize("/foo"); + + // invalid + test("foo\u0000\bar") + .invalid(); + + // normalization + test("//foo//bar") + .string("/foo/bar") + .root("/") + .parent("/foo") + .name("bar"); + } + + static void npes() { + header("NullPointerException"); + + Path path = FileSystems.getDefault().getPath("foo"); + + try { + path.resolve((String)null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException npe) { + } + + try { + path.relativize(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException npe) { + } + + try { + path.compareTo(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException npe) { + } + + try { + path.startsWith(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException npe) { + } + + try { + path.endsWith(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException npe) { + } + + } + + public static void main(String[] args) { + // all platforms + npes(); + + // operating system specific + String osname = System.getProperty("os.name"); + if (osname.startsWith("Windows")) { + doWindowsTests(); + } + if (osname.equals("SunOS") || osname.equals("Linux")) { + doUnixTests(); + } + + } +} diff --git a/jdk/test/java/nio/file/Path/SBC.java b/jdk/test/java/nio/file/Path/SBC.java new file mode 100644 index 00000000000..724c8706a26 --- /dev/null +++ b/jdk/test/java/nio/file/Path/SBC.java @@ -0,0 +1,468 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path.newByteChannel + * @library .. + */ + +import java.nio.ByteBuffer; +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import static com.sun.nio.file.ExtendedOpenOption.*; +import java.nio.file.attribute.FileAttribute; +import java.nio.channels.*; +import java.io.IOException; +import java.util.*; + +public class SBC { + + static boolean supportsLinks; + + public static void main(String[] args) throws Exception { + Path dir = TestUtil.createTemporaryDirectory(); + try { + supportsLinks = TestUtil.supportsLinks(dir); + + // open options + createTests(dir); + appendTests(dir); + truncateExistingTests(dir); + noFollowLinksTests(dir); + + // SeekableByteChannel methods + sizeTruncatePositionTests(dir); + + // platform specific + if (System.getProperty("os.name").startsWith("Windows")) + dosSharingOptionTests(dir); + + // misc. tests + badCombinations(dir); + unsupportedOptions(dir); + nullTests(dir); + + } finally { + TestUtil.removeAll(dir); + } + } + + // test CREATE and CREATE_NEW options + static void createTests(Path dir) throws Exception { + Path file = dir.resolve("foo"); + + // CREATE + try { + // create file (no existing file) + file.newByteChannel(CREATE, WRITE).close(); + if (file.notExists()) + throw new RuntimeException("File not created"); + + // create file (existing file) + file.newByteChannel(CREATE, WRITE).close(); + + // create file where existing file is a sym link + if (supportsLinks) { + Path link = dir.resolve("link").createSymbolicLink(file); + try { + // file already exists + link.newByteChannel(CREATE, WRITE).close(); + + // file does not exist + file.delete(); + link.newByteChannel(CREATE, WRITE).close(); + if (file.notExists()) + throw new RuntimeException("File not created"); + + } finally { + TestUtil.deleteUnchecked(link); + } + } + + } finally { + TestUtil.deleteUnchecked(file); + } + + // CREATE_NEW + try { + // create file + file.newByteChannel(CREATE_NEW, WRITE).close(); + if (file.notExists()) + throw new RuntimeException("File not created"); + + // create should fail + try { + SeekableByteChannel sbc = + file.newByteChannel(CREATE_NEW, WRITE); + sbc.close(); + throw new RuntimeException("FileAlreadyExistsException not thrown"); + } catch (FileAlreadyExistsException x) { } + + // create should fail + if (supportsLinks) { + Path link = dir.resolve("link"); + Path target = dir.resolve("thisDoesNotExist"); + link.createSymbolicLink(target); + try { + + try { + SeekableByteChannel sbc = + file.newByteChannel(CREATE_NEW, WRITE); + sbc.close(); + throw new RuntimeException("FileAlreadyExistsException not thrown"); + } catch (FileAlreadyExistsException x) { } + + } finally { + TestUtil.deleteUnchecked(link); + } + } + + + } finally { + TestUtil.deleteUnchecked(file); + } + + // CREATE_NEW + SPARSE + try { + SeekableByteChannel sbc = file + .newByteChannel(CREATE_NEW, WRITE, SPARSE); + try { + final long hole = 2L * 1024L * 1024L * 1024L; + sbc.position(hole); + write(sbc, "hello"); + long size = sbc.size(); + if (size != (hole + 5)) + throw new RuntimeException("Unexpected size"); + } finally { + sbc.close(); + } + } finally { + TestUtil.deleteUnchecked(file); + } + } + + // test APPEND option + static void appendTests(Path dir) throws Exception { + Path file = dir.resolve("foo"); + try { + // "hello there" should be written to file + SeekableByteChannel sbc = file + .newByteChannel(CREATE_NEW, WRITE, APPEND); + try { + write(sbc, "hello "); + sbc.position(0L); + write(sbc, "there"); + } finally { + sbc.close(); + } + + // check file + Scanner s = new Scanner(file); + try { + String line = s.nextLine(); + if (!line.equals("hello there")) + throw new RuntimeException("Unexpected file contents"); + } finally { + s.close(); + } + + // check that read is not allowed + sbc = file.newByteChannel(APPEND); + try { + sbc.read(ByteBuffer.allocate(100)); + } catch (NonReadableChannelException x) { + } finally { + sbc.close(); + } + } finally { + // clean-up + TestUtil.deleteUnchecked(file); + } + } + + // test TRUNCATE_EXISTING option + static void truncateExistingTests(Path dir) throws Exception { + Path file = dir.resolve("foo"); + try { + SeekableByteChannel sbc = + file.newByteChannel(CREATE_NEW, WRITE); + try { + write(sbc, "Have a nice day!"); + } finally { + sbc.close(); + } + + // re-open with truncate option + // write short message and check + sbc = file.newByteChannel(WRITE, TRUNCATE_EXISTING); + try { + write(sbc, "Hello there!"); + } finally { + sbc.close(); + } + Scanner s = new Scanner(file); + try { + String line = s.nextLine(); + if (!line.equals("Hello there!")) + throw new RuntimeException("Unexpected file contents"); + } finally { + s.close(); + } + + // re-open with create + truncate option + // check file is of size 0L + sbc = file.newByteChannel(WRITE, CREATE, TRUNCATE_EXISTING); + try { + long size = ((FileChannel)sbc).size(); + if (size != 0L) + throw new RuntimeException("File not truncated"); + } finally { + sbc.close(); + } + + } finally { + // clean-up + TestUtil.deleteUnchecked(file); + } + + } + + // test NOFOLLOW_LINKS option + static void noFollowLinksTests(Path dir) throws Exception { + if (!supportsLinks) + return; + Path file = dir.resolve("foo").createFile(); + try { + // ln -s foo link + Path link = dir.resolve("link").createSymbolicLink(file); + + // open with NOFOLLOW_LINKS option + try { + link.newByteChannel(READ, LinkOption.NOFOLLOW_LINKS); + throw new RuntimeException(); + } catch (IOException x) { + } finally { + TestUtil.deleteUnchecked(link); + } + + } finally { + // clean-up + TestUtil.deleteUnchecked(file); + } + } + + // test size/truncate/position methods + static void sizeTruncatePositionTests(Path dir) throws Exception { + Path file = dir.resolve("foo"); + try { + SeekableByteChannel sbc = file + .newByteChannel(CREATE_NEW, READ, WRITE); + try { + if (sbc.size() != 0L) + throw new RuntimeException("Unexpected size"); + + // check size + write(sbc, "hello"); + if (sbc.size() != 5L) + throw new RuntimeException("Unexpected size"); + + // truncate (size and position should change) + sbc.truncate(4L); + if (sbc.size() != 4L) + throw new RuntimeException("Unexpected size"); + if (sbc.position() != 4L) + throw new RuntimeException("Unexpected position"); + + // truncate (position should not change) + sbc.position(2L).truncate(3L); + if (sbc.size() != 3L) + throw new RuntimeException("Unexpected size"); + if (sbc.position() != 2L) + throw new RuntimeException("Unexpected position"); + } finally { + sbc.close(); + } + } finally { + TestUtil.deleteUnchecked(file); + } + } + + // Windows specific options for the use by applications that really want + // to use legacy DOS sharing options + static void dosSharingOptionTests(Path dir) throws Exception { + Path file = dir.resolve("foo").createFile(); + try { + SeekableByteChannel ch; + + // no sharing + ch = file.newByteChannel(READ, + NOSHARE_READ, NOSHARE_WRITE, NOSHARE_DELETE); + try { + try { + file.newByteChannel(READ); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + try { + file.newByteChannel(WRITE); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + try { + file.delete(); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + } finally { + ch.close(); + } + + // read allowed + ch = file.newByteChannel(READ, NOSHARE_WRITE, NOSHARE_DELETE); + try { + file.newByteChannel(READ).close(); + try { + file.newByteChannel(WRITE); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + try { + file.delete(); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + } finally { + ch.close(); + } + + // write allowed + ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_DELETE); + try { + try { + file.newByteChannel(READ); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + file.newByteChannel(WRITE).close(); + try { + file.delete(); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + } finally { + ch.close(); + } + + // delete allowed + ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_WRITE); + try { + try { + file.newByteChannel(READ); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + try { + file.newByteChannel(WRITE); + throw new RuntimeException("Sharing violation expected"); + } catch (IOException ignore) { } + file.delete(); + } finally { + ch.close(); + } + + } finally { + TestUtil.deleteUnchecked(file); + } + } + + // invalid combinations of options + static void badCombinations(Path dir) throws Exception { + Path file = dir.resolve("bad"); + + try { + file.newByteChannel(READ, APPEND); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException x) { } + + try { + file.newByteChannel(WRITE, APPEND, TRUNCATE_EXISTING); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException x) { } + } + + // unsupported operations + static void unsupportedOptions(Path dir) throws Exception { + Path file = dir.resolve("bad"); + + OpenOption badOption = new OpenOption() { }; + try { + file.newByteChannel(badOption); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException e) { } + try { + file.newByteChannel(READ, WRITE, badOption); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException e) { } + } + + // null handling + static void nullTests(Path dir) throws Exception { + Path file = dir.resolve("foo"); + + try { + file.newByteChannel((OpenOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + OpenOption[] opts = { READ, null }; + file.newByteChannel(opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + file.newByteChannel((Set)null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + Set opts = new HashSet(); + opts.add(READ); + opts.add(null); + file.newByteChannel(opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + EnumSet opts = EnumSet.of(READ); + file.newByteChannel(opts, (FileAttribute[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + EnumSet opts = EnumSet.of(READ); + FileAttribute[] attrs = { null }; + file.newByteChannel(opts, attrs); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + } + + static void write(WritableByteChannel wbc, String msg) throws IOException { + ByteBuffer buf = ByteBuffer.wrap(msg.getBytes()); + while (buf.hasRemaining()) + wbc.write(buf); + } +} diff --git a/jdk/test/java/nio/file/Path/TemporaryFiles.java b/jdk/test/java/nio/file/Path/TemporaryFiles.java new file mode 100644 index 00000000000..6a9d28d9782 --- /dev/null +++ b/jdk/test/java/nio/file/Path/TemporaryFiles.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.file.attribute.*; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Set; + +public class TemporaryFiles { + + static void checkFile(Path file) throws IOException { + // check file is in temporary directory + Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); + if (!file.getParent().equals(tmpdir)) + throw new RuntimeException("Not in temporary directory"); + + // check that file can be opened for reading and writing + file.newByteChannel(READ).close(); + file.newByteChannel(WRITE).close(); + file.newByteChannel(READ,WRITE).close(); + + // check file permissions are 0600 or more secure + if (file.getFileStore().supportsFileAttributeView("posix")) { + Set perms = Attributes + .readPosixFileAttributes(file).permissions(); + perms.remove(PosixFilePermission.OWNER_READ); + perms.remove(PosixFilePermission.OWNER_WRITE); + if (!perms.isEmpty()) + throw new RuntimeException("Temporary file is not secure"); + } + } + + public static void main(String[] args) throws IOException { + Path file = File.createTempFile("blah", null, false).toPath(); + try { + checkFile(file); + } finally { + TestUtil.deleteUnchecked(file); + } + + // temporary file with deleteOnExit + file = File.createTempFile("blah", "tmp", true).toPath(); + checkFile(file); + // write path to temporary file to file so that calling script can + // check that it is deleted + OutputStream out = Paths.get(args[0]).newOutputStream(); + try { + out.write(file.toString().getBytes()); + } finally { + out.close(); + } + } +} diff --git a/jdk/test/java/nio/file/Path/UriImportExport.java b/jdk/test/java/nio/file/Path/UriImportExport.java new file mode 100644 index 00000000000..560423195ed --- /dev/null +++ b/jdk/test/java/nio/file/Path/UriImportExport.java @@ -0,0 +1,80 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.Path + */ + +import java.nio.file.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.io.PrintStream; + +public class UriImportExport { + + static final PrintStream log = System.out; + static int failures = 0; + + static void test(String fn, String expected) { + log.println(); + Path p = Paths.get(fn); + log.println(p); + URI u = p.toUri(); + log.println(" --> " + u); + if (expected != null && !(u.toString().equals(expected))) { + log.println("FAIL: Expected " + expected); + failures++; + return; + } + Path q = Paths.get(u); + log.println(" --> " + q); + if (!p.toAbsolutePath().equals(q)) { + log.println("FAIL: Expected " + p + ", got " + q); + failures++; + return; + } + } + + static void test(String fn) { + test(fn, null); + } + + public static void main(String[] args) throws Exception { + test("foo"); + test("/foo"); + test("/foo bar"); + + String osname = System.getProperty("os.name"); + if (osname.startsWith("Windows")) { + test("C:\\foo"); + test("C:foo"); + test("\\\\rialto.dublin.com\\share\\"); + test("\\\\fe80--203-baff-fe5a-749ds1.ipv6-literal.net\\share\\missing", + "file://[fe80::203:baff:fe5a:749d%1]/share/missing"); + } + + if (failures > 0) + throw new RuntimeException(failures + " test(s) failed"); + } +} diff --git a/jdk/test/java/nio/file/Path/delete_on_close.sh b/jdk/test/java/nio/file/Path/delete_on_close.sh new file mode 100644 index 00000000000..198e99d7201 --- /dev/null +++ b/jdk/test/java/nio/file/Path/delete_on_close.sh @@ -0,0 +1,61 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4313887 +# @summary Unit test for DELETE_ON_CLOSE open option +# @library .. +# @build DeleteOnClose +# @run shell delete_on_close.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java +else + JAVA="${TESTJAVA}/bin/java" +fi + +OS=`uname -s` +case "$OS" in + Windows_* ) + CLASSPATH="${TESTCLASSES};${TESTSRC}" + ;; + * ) + CLASSPATH=${TESTCLASSES}:${TESTSRC} + ;; +esac +export CLASSPATH + +TMPFILE="$$.tmp" +touch $TMPFILE +$JAVA DeleteOnClose $TMPFILE 2>&1 +if [ $? != 0 ]; then exit 1; fi +if [ -f $TMPFILE ]; then + echo "$TMPFILE was not deleted" + exit 1 +fi + +exit 0 diff --git a/jdk/test/java/nio/file/Path/temporary_files.sh b/jdk/test/java/nio/file/Path/temporary_files.sh new file mode 100644 index 00000000000..552dcfdab46 --- /dev/null +++ b/jdk/test/java/nio/file/Path/temporary_files.sh @@ -0,0 +1,65 @@ +# +# Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4313887 +# @summary Unit test for File.createTempFile (to be be moved to test/java/io/File) +# @library .. +# @build TemporaryFiles +# @run shell temporary_files.sh + +# if TESTJAVA isn't set then we assume an interactive run. + +if [ -z "$TESTJAVA" ]; then + TESTSRC=. + TESTCLASSES=. + JAVA=java +else + JAVA="${TESTJAVA}/bin/java" +fi + +OS=`uname -s` +case "$OS" in + Windows_* ) + CLASSPATH="${TESTCLASSES};${TESTSRC}" + ;; + * ) + CLASSPATH=${TESTCLASSES}:${TESTSRC} + ;; +esac +export CLASSPATH + +TMPFILENAME="$$.tmp" +$JAVA TemporaryFiles $TMPFILENAME 2>&1 +if [ $? != 0 ]; then exit 1; fi +if [ ! -f $TMPFILENAME ]; then + echo "$TMPFILENAME not found" + exit 1 +fi +TMPFILE=`cat $TMPFILENAME` +if [ -f $TMPFILE ]; then + echo "$TMPFILE not deleted" + exit 1 +fi + +exit 0 diff --git a/jdk/test/java/nio/file/PathMatcher/Basic.java b/jdk/test/java/nio/file/PathMatcher/Basic.java new file mode 100644 index 00000000000..16efcf099d0 --- /dev/null +++ b/jdk/test/java/nio/file/PathMatcher/Basic.java @@ -0,0 +1,174 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.PathMatcher + */ + +import java.nio.file.*; +import java.util.regex.PatternSyntaxException; + +public class Basic { + static int failures; + + static void match(String name, String pattern, boolean expectedToMatch) { + System.out.format("%s -> %s", name, pattern); + Path file = Paths.get(name); + boolean matched = file.getFileSystem() + .getPathMatcher("glob:" + pattern).matches(file); + if (matched) + System.out.print(" (matched)"); + else + System.out.print(" (no match)"); + if (matched != expectedToMatch) { + System.out.println(" ==> UNEXPECTED RESULT!"); + failures++; + } else { + System.out.println(" OKAY"); + } + } + + static void assertMatch(String path, String pattern) { + match(path, pattern, true); + } + + static void assertNotMatch(String path, String pattern) { + match(path, pattern, false); + } + + static void assertBadPattern(String path, String pattern) { + System.out.format("Compile bad pattern %s\t", pattern); + try { + FileSystems.getDefault().getPathMatcher("glob:" + pattern); + System.out.println("Compiled ==> UNEXPECTED RESULT!"); + failures++; + } catch (PatternSyntaxException e) { + System.out.println("Failed to compile ==> OKAY"); + } + } + + public static void main(String[] args) { + // basic + assertMatch("foo.html", "foo.html"); + assertNotMatch("foo.html", "foo.htm"); + assertNotMatch("foo.html", "bar.html"); + + // match zero or more characters + assertMatch("foo.html", "f*"); + assertMatch("foo.html", "*.html"); + assertMatch("foo.html", "foo.html*"); + assertMatch("foo.html", "*foo.html"); + assertMatch("foo.html", "*foo.html*"); + assertNotMatch("foo.html", "*.htm"); + assertNotMatch("foo.html", "f.*"); + + // match one character + assertMatch("foo.html", "?oo.html"); + assertMatch("foo.html", "??o.html"); + assertMatch("foo.html", "???.html"); + assertMatch("foo.html", "???.htm?"); + assertNotMatch("foo.html", "foo.???"); + + // group of subpatterns + assertMatch("foo.html", "foo{.html,.class}"); + assertMatch("foo.html", "foo.{class,html}"); + assertNotMatch("foo.html", "foo{.htm,.class}"); + + // bracket expressions + assertMatch("foo.html", "[f]oo.html"); + assertMatch("foo.html", "[e-g]oo.html"); + assertMatch("foo.html", "[abcde-g]oo.html"); + assertMatch("foo.html", "[abcdefx-z]oo.html"); + assertMatch("foo.html", "[!a]oo.html"); + assertMatch("foo.html", "[!a-e]oo.html"); + assertMatch("foo-bar", "foo[-a-z]bar"); // match dash + assertMatch("foo.html", "foo[!-]html"); // match !dash + + // groups of subpattern with bracket expressions + assertMatch("foo.html", "[f]oo.{[h]tml,class}"); + assertMatch("foo.html", "foo.{[a-z]tml,class}"); + assertMatch("foo.html", "foo.{[!a-e]tml,.class}"); + + // assume special characters are allowed in file names + assertMatch("{foo}.html", "\\{foo*"); + assertMatch("{foo}.html", "*\\}.html"); + assertMatch("[foo].html", "\\[foo*"); + assertMatch("[foo].html", "*\\].html"); + + // errors + assertBadPattern("foo.html", "*[a--z]"); // bad range + assertBadPattern("foo.html", "*[a--]"); // bad range + assertBadPattern("foo.html", "*[a-z"); // missing ] + assertBadPattern("foo.html", "*{class,java"); // missing } + assertBadPattern("foo.html", "*.{class,{.java}}"); // nested group + assertBadPattern("foo.html", "*.html\\"); // nothing to escape + + // platform specific + if (System.getProperty("os.name").startsWith("Windows")) { + assertMatch("C:\\foo", "C:\\\\f*"); + assertMatch("C:\\FOO", "c:\\\\f*"); + assertMatch("C:\\foo\\bar\\gus", "C:\\\\**\\\\gus"); + assertMatch("C:\\foo\\bar\\gus", "C:\\\\**"); + } else { + assertMatch("/tmp/foo", "/tmp/*"); + assertMatch("/tmp/foo/bar", "/tmp/**"); + + // some special characters not allowed on Windows + assertMatch("myfile?", "myfile\\?"); + assertMatch("one\\two", "one\\\\two"); + assertMatch("one*two", "one\\*two"); + } + + + + // regex syntax + { + String pattern = ".*\\.html"; + System.out.format("Test regex pattern: %s", pattern); + Path file = Paths.get("foo.html"); + boolean matched = file.getFileSystem() + .getPathMatcher("regex:" + pattern).matches(file); + if (matched) { + System.out.println(" OKAY"); + } else { + System.out.println(" ==> UNEXPECTED RESULT!"); + failures++; + } + } + + // unknown syntax + try { + System.out.format("Test unknown syntax"); + FileSystems.getDefault().getPathMatcher("grep:foo"); + System.out.println(" ==> NOT EXPECTED TO COMPILE"); + failures++; + } catch (UnsupportedOperationException e) { + System.out.println(" OKAY"); + } + + if (failures > 0) + throw new RuntimeException(failures + + " sub-test(s) failed - see log for details"); + } +} diff --git a/jdk/test/java/nio/file/TestUtil.java b/jdk/test/java/nio/file/TestUtil.java new file mode 100644 index 00000000000..c19e28fbdc4 --- /dev/null +++ b/jdk/test/java/nio/file/TestUtil.java @@ -0,0 +1,125 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Random; +import java.io.IOException; + +public class TestUtil { + private TestUtil() { + } + + public static Path createTemporaryDirectory() throws IOException { + Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); + Random r = new Random(); + + Path dir; + do { + dir = tmpdir.resolve("name" + r.nextInt()); + } while (dir.exists()); + return dir.createDirectory(); + } + + static void removeAll(Path dir) { + Files.walkFileTree(dir, new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir) { + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) { + System.err.format("Error occured accessing directory %s\n", dir, exc); + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + file.delete(false); + } catch (IOException x) { + System.err.format("Unable to delete %s: %s\n", file, x); + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + try { + dir.delete(false); + } catch (IOException x) { + System.err.format("Unable to delete %s: %s\n", dir, x); + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + System.err.format("Unable to visit %s: %s\n", file, exc); + return FileVisitResult.CONTINUE; + } + }); + } + + static void deleteUnchecked(FileRef file) { + try { + file.delete(); + } catch (IOException exc) { + System.err.format("Unable to delete %s: %s\n", file, exc); + } + } + + /** + * Creates a directory tree in the given directory so that the total + * size of the path is more than 2k in size. This is used for long + * path tests on Windows. + */ + static Path createDirectoryWithLongPath(Path dir) + throws IOException + { + StringBuilder sb = new StringBuilder(); + for (int i=0; i<240; i++) { + sb.append('A'); + } + String name = sb.toString(); + do { + dir = dir.resolve(name).resolve("."); + dir.createDirectory(); + } while (dir.toString().length() < 2048); + return dir; + } + + /** + * Returns true if symbolic links are supported + */ + static boolean supportsLinks(Path dir) { + Path link = dir.resolve("testlink"); + Path target = dir.resolve("testtarget"); + try { + link.createSymbolicLink(target); + target.delete(false); + return true; + } catch (UnsupportedOperationException x) { + return false; + } catch (IOException x) { + return false; + } + } +} diff --git a/jdk/test/java/nio/file/WatchService/Basic.java b/jdk/test/java/nio/file/WatchService/Basic.java new file mode 100644 index 00000000000..60c18d74b9b --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/Basic.java @@ -0,0 +1,493 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.WatchService + * @library .. + * @run main/timeout=120 Basic + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKind.*; +import java.nio.file.attribute.*; +import java.io.*; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Unit test for WatchService that exercises all methods in various scenarios. + */ + +public class Basic { + + static void createFile(Path file) throws IOException { + file.newOutputStream().close(); + } + + static void takeExpectedKey(WatchService watcher, WatchKey expected) { + System.out.println("take events..."); + WatchKey key; + try { + key = watcher.take(); + } catch (InterruptedException x) { + // not expected + throw new RuntimeException(x); + } + if (key != expected) + throw new RuntimeException("removed unexpected key"); + } + + static void checkExpectedEvent(Iterable> events, + WatchEvent.Kind expectedKind, + Object expectedContext) + { + WatchEvent event = events.iterator().next(); + System.out.format("got event: type=%s, count=%d, context=%s\n", + event.kind(), event.count(), event.context()); + if (event.kind() != expectedKind) + throw new RuntimeException("unexpected event"); + if (!expectedContext.equals(event.context())) + throw new RuntimeException("unexpected context"); + } + + /** + * Simple test of each of the standard events + */ + static void testEvents(Path dir) throws IOException { + System.out.println("-- Standard Events --"); + + FileSystem fs = FileSystems.getDefault(); + Path name = fs.getPath("foo"); + + WatchService watcher = fs.newWatchService(); + try { + // --- ENTRY_CREATE --- + + // register for event + System.out.format("register %s for ENTRY_CREATE\n", dir); + WatchKey myKey = dir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE }); + + // create file + Path file = dir.resolve("foo"); + System.out.format("create %s\n", file); + createFile(file); + + // remove key and check that we got the ENTRY_CREATE event + takeExpectedKey(watcher, myKey); + checkExpectedEvent(myKey.pollEvents(), + StandardWatchEventKind.ENTRY_CREATE, name); + + System.out.println("reset key"); + if (!myKey.reset()) + throw new RuntimeException("key has been cancalled"); + + System.out.println("OKAY"); + + // --- ENTRY_DELETE --- + + System.out.format("register %s for ENTRY_DELETE\n", dir); + WatchKey deleteKey = dir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_DELETE }); + if (deleteKey != myKey) + throw new RuntimeException("register did not return existing key"); + + System.out.format("delete %s\n", file); + file.delete(false); + takeExpectedKey(watcher, myKey); + checkExpectedEvent(myKey.pollEvents(), + StandardWatchEventKind.ENTRY_DELETE, name); + + System.out.println("reset key"); + if (!myKey.reset()) + throw new RuntimeException("key has been cancalled"); + + System.out.println("OKAY"); + + // create the file for the next test + createFile(file); + + // --- ENTRY_MODIFY --- + + System.out.format("register %s for ENTRY_MODIFY\n", dir); + WatchKey newKey = dir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_MODIFY }); + if (newKey != myKey) + throw new RuntimeException("register did not return existing key"); + + System.out.format("update: %s\n", file); + OutputStream out = file.newOutputStream(EnumSet.of(StandardOpenOption.APPEND)); + try { + out.write("I am a small file".getBytes("UTF-8")); + } finally { + out.close(); + } + + // remove key and check that we got the ENTRY_MODIFY event + takeExpectedKey(watcher, myKey); + checkExpectedEvent(myKey.pollEvents(), + StandardWatchEventKind.ENTRY_MODIFY, name); + System.out.println("OKAY"); + + // done + file.delete(false); + + } finally { + watcher.close(); + } + } + + /** + * Check that a cancelled key will never be queued + */ + static void testCancel(Path dir) throws IOException { + System.out.println("-- Cancel --"); + + WatchService watcher = FileSystems.getDefault().newWatchService(); + try { + + System.out.format("register %s for events\n", dir); + WatchKey myKey = dir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE }); + + System.out.println("cancel key"); + myKey.cancel(); + + // create a file in the directory + Path file = dir.resolve("mars"); + System.out.format("create: %s\n", file); + createFile(file); + + // poll for keys - there will be none + System.out.println("poll..."); + try { + WatchKey key = watcher.poll(3000, TimeUnit.MILLISECONDS); + if (key != null) + throw new RuntimeException("key should not be queued"); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + + // done + file.delete(false); + + System.out.println("OKAY"); + + } finally { + watcher.close(); + } + } + + /** + * Check that deleting a registered directory causes the key to be + * cancelled and queued. + */ + static void testAutomaticCancel(Path dir) throws IOException { + System.out.println("-- Automatic Cancel --"); + + Path subdir = dir.resolve("bar").createDirectory(); + + WatchService watcher = FileSystems.getDefault().newWatchService(); + try { + + System.out.format("register %s for events\n", subdir); + WatchKey myKey = subdir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }); + + System.out.format("delete: %s\n", subdir); + subdir.delete(false); + takeExpectedKey(watcher, myKey); + + System.out.println("reset key"); + if (myKey.reset()) + throw new RuntimeException("Key was not cancelled"); + if (myKey.isValid()) + throw new RuntimeException("Key is still valid"); + + System.out.println("OKAY"); + + } finally { + watcher.close(); + } + } + + /** + * Asynchronous close of watcher causes blocked threads to wakeup + */ + static void testWakeup(Path dir) throws IOException { + System.out.println("-- Wakeup Tests --"); + final WatchService watcher = FileSystems.getDefault().newWatchService(); + Runnable r = new Runnable() { + public void run() { + try { + Thread.sleep(5000); + System.out.println("close WatchService..."); + watcher.close(); + } catch (InterruptedException x) { + x.printStackTrace(); + } catch (IOException x) { + x.printStackTrace(); + } + } + }; + + // start thread to close watch service after delay + new Thread(r).start(); + + try { + System.out.println("take..."); + watcher.take(); + throw new RuntimeException("ClosedWatchServiceException not thrown"); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } catch (ClosedWatchServiceException x) { + System.out.println("ClosedWatchServiceException thrown"); + } + + System.out.println("OKAY"); + } + + /** + * Simple test to check exceptions and other cases + */ + @SuppressWarnings("unchecked") + static void testExceptions(Path dir) throws IOException { + System.out.println("-- Exceptions and other simple tests --"); + + WatchService watcher = FileSystems.getDefault().newWatchService(); + try { + + // Poll tests + + WatchKey key; + System.out.println("poll..."); + key = watcher.poll(); + if (key != null) + throw new RuntimeException("no keys registered"); + + System.out.println("poll with timeout..."); + try { + long start = System.currentTimeMillis(); + key = watcher.poll(3000, TimeUnit.MILLISECONDS); + if (key != null) + throw new RuntimeException("no keys registered"); + long waited = System.currentTimeMillis() - start; + if (waited < 2900) + throw new RuntimeException("poll was too short"); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } + + // IllegalArgumentException + System.out.println("IllegalArgumentException tests..."); + try { + dir.register(watcher, new WatchEvent.Kind[]{ } ); + throw new RuntimeException("IllegalArgumentException not thrown"); + } catch (IllegalArgumentException x) { + } + try { + // OVERFLOW is ignored so this is equivalent to the empty set + dir.register(watcher, new WatchEvent.Kind[]{ OVERFLOW }); + throw new RuntimeException("IllegalArgumentException not thrown"); + } catch (IllegalArgumentException x) { + } + + // UnsupportedOperationException + try { + dir.register(watcher, new WatchEvent.Kind[]{ + new WatchEvent.Kind() { + @Override public String name() { return "custom"; } + @Override public Class type() { return Object.class; } + }}); + } catch (UnsupportedOperationException x) { + } + try { + dir.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE }, + new WatchEvent.Modifier() { + @Override public String name() { return "custom"; } + }); + throw new RuntimeException("UnsupportedOperationException not thrown"); + } catch (UnsupportedOperationException x) { + } + + // NullPointerException + System.out.println("NullPointerException tests..."); + try { + dir.register(null, new WatchEvent.Kind[]{ ENTRY_CREATE }); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + dir.register(watcher, new WatchEvent.Kind[]{ null }); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + dir.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE }, + (WatchEvent.Modifier)null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + } finally { + watcher.close(); + } + + // -- ClosedWatchServiceException -- + + System.out.println("ClosedWatchServiceException tests..."); + + try { + watcher.poll(); + throw new RuntimeException("ClosedWatchServiceException not thrown"); + } catch (ClosedWatchServiceException x) { + } + + // assume that poll throws exception immediately + long start = System.currentTimeMillis(); + try { + watcher.poll(10000, TimeUnit.MILLISECONDS); + throw new RuntimeException("ClosedWatchServiceException not thrown"); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } catch (ClosedWatchServiceException x) { + long waited = System.currentTimeMillis() - start; + if (waited > 5000) + throw new RuntimeException("poll was too long"); + } + + try { + watcher.take(); + throw new RuntimeException("ClosedWatchServiceException not thrown"); + } catch (InterruptedException x) { + throw new RuntimeException(x); + } catch (ClosedWatchServiceException x) { + } + + try { + dir.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE }); + throw new RuntimeException("ClosedWatchServiceException not thrown"); + } catch (ClosedWatchServiceException x) { + } + + System.out.println("OKAY"); + } + + /** + * Test that directory can be registered with more than one watch service + * and that events don't interfere with each other + */ + static void testTwoWatchers(Path dir) throws IOException { + System.out.println("-- Two watchers test --"); + + FileSystem fs = FileSystems.getDefault(); + WatchService watcher1 = fs.newWatchService(); + WatchService watcher2 = fs.newWatchService(); + try { + Path name1 = fs.getPath("gus1"); + Path name2 = fs.getPath("gus2"); + + // create gus1 + Path file1 = dir.resolve(name1); + System.out.format("create %s\n", file1); + createFile(file1); + + // register with both watch services (different events) + System.out.println("register for different events"); + WatchKey key1 = dir.register(watcher1, + new WatchEvent.Kind[]{ ENTRY_CREATE }); + WatchKey key2 = dir.register(watcher2, + new WatchEvent.Kind[]{ ENTRY_DELETE }); + + if (key1 == key2) + throw new RuntimeException("keys should be different"); + + // create gus2 + Path file2 = dir.resolve(name2); + System.out.format("create %s\n", file2); + createFile(file2); + + // check that key1 got ENTRY_CREATE + takeExpectedKey(watcher1, key1); + checkExpectedEvent(key1.pollEvents(), + StandardWatchEventKind.ENTRY_CREATE, name2); + + // check that key2 got zero events + WatchKey key = watcher2.poll(); + if (key != null) + throw new RuntimeException("key not expected"); + + // delete gus1 + file1.delete(false); + + // check that key2 got ENTRY_DELETE + takeExpectedKey(watcher2, key2); + checkExpectedEvent(key2.pollEvents(), + StandardWatchEventKind.ENTRY_DELETE, name1); + + // check that key1 got zero events + key = watcher1.poll(); + if (key != null) + throw new RuntimeException("key not expected"); + + // reset for next test + key1.reset(); + key2.reset(); + + // change registration with watcher2 so that they are both + // registered for the same event + System.out.println("register for same event"); + key2 = dir.register(watcher2, new WatchEvent.Kind[]{ ENTRY_CREATE }); + + // create file and key2 should be queued + System.out.format("create %s\n", file1); + createFile(file1); + takeExpectedKey(watcher2, key2); + checkExpectedEvent(key2.pollEvents(), + StandardWatchEventKind.ENTRY_CREATE, name1); + + System.out.println("OKAY"); + + } finally { + watcher2.close(); + watcher1.close(); + } + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + + testEvents(dir); + testCancel(dir); + testAutomaticCancel(dir); + testWakeup(dir); + testExceptions(dir); + testTwoWatchers(dir); + + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/WatchService/FileTreeModifier.java b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java new file mode 100644 index 00000000000..741c86df094 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java @@ -0,0 +1,148 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Sanity test for Sun-specific FILE_TREE watch event modifier + * @library .. + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKind.*; +import java.io.IOException; +import java.io.OutputStream; +import java.util.*; +import java.util.concurrent.*; +import static com.sun.nio.file.ExtendedWatchEventModifier.*; + +public class FileTreeModifier { + + static void checkExpectedEvent(WatchService watcher, + WatchEvent.Kind expectedType, + Object expectedContext) + { + WatchKey key; + try { + key = watcher.take(); + } catch (InterruptedException x) { + // should not happen + throw new RuntimeException(x); + } + WatchEvent event = key.pollEvents().iterator().next(); + System.out.format("Event: type=%s, count=%d, context=%s\n", + event.kind(), event.count(), event.context()); + if (event.kind() != expectedType) + throw new RuntimeException("unexpected event"); + if (!expectedContext.equals(event.context())) + throw new RuntimeException("unexpected context"); + } + + static void doTest(Path top) throws IOException { + FileSystem fs = top.getFileSystem(); + WatchService watcher = fs.newWatchService(); + + // create directories + Path subdir = top + .resolve("a").createDirectory() + .resolve("b").createDirectory() + .resolve("c").createDirectory(); + + // Test ENTRY_CREATE with FILE_TREE modifier. + + WatchKey key = top.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE }, FILE_TREE); + + // create file in a/b/c and check we get create event + Path file = subdir.resolve("foo").createFile(); + checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file)); + key.reset(); + + // Test ENTRY_DELETE with FILE_TREE modifier. + + WatchKey k = top.register(watcher, + new WatchEvent.Kind[]{ ENTRY_DELETE }, FILE_TREE); + if (k != key) + throw new RuntimeException("Existing key not returned"); + + // delete a/b/c/foo and check we get delete event + file.delete(false); + checkExpectedEvent(watcher, ENTRY_DELETE, top.relativize(file)); + key.reset(); + + // Test changing registration to ENTRY_CREATE without modifier + + k = top.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE }); + if (k != key) + throw new RuntimeException("Existing key not returned"); + + // create a/b/c/foo + file.createFile(); + + // check that key is not queued + try { + k = watcher.poll(3, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(); + } + if (k != null) + throw new RuntimeException("WatchKey not expected to be polled"); + + // create bar and check we get create event + file = top.resolve("bar").createFile(); + checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file)); + key.reset(); + + // Test changing registration to with FILE_TREE modifier + + k = top.register(watcher, + new WatchEvent.Kind[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }, + FILE_TREE); + if (k != key) + throw new RuntimeException("Existing key not returned"); + + // modify bar and check we get modify event + OutputStream out = file.newOutputStream(); + try { + out.write("Double shot expresso please".getBytes("UTF-8")); + } finally { + out.close(); + } + checkExpectedEvent(watcher, ENTRY_MODIFY, top.relativize(file)); + key.reset(); + } + + + public static void main(String[] args) throws IOException { + if (!System.getProperty("os.name").startsWith("Windows")) { + System.out.println("This is Windows-only test at this time!"); + return; + } + + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTest(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java new file mode 100644 index 00000000000..62aedeeac0a --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java @@ -0,0 +1,122 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Sanity test for Sun-specific sensitivyt level watch event modifier + * @library .. + * @run main/timeout=330 Basic + */ + +import java.nio.file.*; +import static java.nio.file.StandardWatchEventKind.*; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import com.sun.nio.file.SensitivityWatchEventModifier; + +public class SensitivityModifier { + + static final Random rand = new Random(); + + static void register(Path[] dirs, WatchService watcher) throws IOException { + SensitivityWatchEventModifier[] sensitivtives = + SensitivityWatchEventModifier.values(); + for (int i=0; i[]{ ENTRY_MODIFY }, sensivity); + } + } + + static void doTest(Path top) throws Exception { + FileSystem fs = top.getFileSystem(); + WatchService watcher = fs.newWatchService(); + + // create directories and files + int nDirs = 5 + rand.nextInt(20); + int nFiles = 50 + rand.nextInt(50); + Path[] dirs = new Path[nDirs]; + Path[] files = new Path[nFiles]; + for (int i=0; i event = key.pollEvents().iterator().next(); + if (event.kind() != ENTRY_MODIFY) + throw new RuntimeException("Unexpected event: " + event); + Path name = ((WatchEvent)event).context(); + if (!name.equals(file.getName())) + throw new RuntimeException("Unexpected context: " + name); + System.out.println("Event OK"); + + // drain events (to avoid interference) + do { + key.reset(); + key = watcher.poll(1, TimeUnit.SECONDS); + } while (key != null); + + // re-register the directories to force changing their sensitivity + // level + register(dirs, watcher); + } + + // done + watcher.close(); + } + + public static void main(String[] args) throws Exception { + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTest(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/WatchService/WithSecurityManager.java b/jdk/test/java/nio/file/WatchService/WithSecurityManager.java new file mode 100644 index 00000000000..c227585eef7 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/WithSecurityManager.java @@ -0,0 +1,83 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for Watchable#register's permission checks + * @build WithSecurityManager + * @run main/othervm WithSecurityManager denyAll.policy - fail + * @run main/othervm WithSecurityManager denyAll.policy tree fail + * @run main/othervm WithSecurityManager grantDirOnly.policy - pass + * @run main/othervm WithSecurityManager grantDirOnly.policy tree fail + * @run main/othervm WithSecurityManager grantDirAndOneLevel.policy - pass + * @run main/othervm WithSecurityManager grantDirAndOneLevel.policy tree fail + * @run main/othervm WithSecurityManager grantDirAndTree.policy - pass + * @run main/othervm WithSecurityManager grantDirAndTree.policy tree pass + */ + +import java.nio.file.*; +import java.io.IOException; +import com.sun.nio.file.ExtendedWatchEventModifier; + +public class WithSecurityManager { + + public static void main(String[] args) throws IOException { + String policyFile = args[0]; + boolean recursive = args[1].equals("tree"); + boolean expectedToFail = args[2].equals("fail"); + + // install security manager with the given policy file + String testSrc = System.getProperty("test.src"); + if (testSrc == null) + throw new RuntimeException("This test must be run by jtreg"); + Path dir = Paths.get(testSrc); + System.setProperty("java.security.policy", dir.resolve(policyFile).toString()); + System.setSecurityManager(new SecurityManager()); + + // initialize optional modifier + WatchEvent.Modifier[] modifiers; + if (recursive) { + modifiers = new WatchEvent.Modifier[1]; + modifiers[0] = ExtendedWatchEventModifier.FILE_TREE; + } else { + modifiers = new WatchEvent.Modifier[0]; + } + + // attempt to register directory + try { + dir.register(dir.getFileSystem().newWatchService(), + new WatchEvent.Kind[]{ StandardWatchEventKind.ENTRY_CREATE }, + modifiers); + if (expectedToFail) + throw new RuntimeException("SecurityException not thrown"); + } catch (SecurityException e) { + if (!expectedToFail) + throw e; + } catch (UnsupportedOperationException e) { + // FILE_TREE modifier only supported on some platforms + if (!recursive) + throw new RuntimeException(e); + System.out.println("FILE_TREE option not supported"); + } + } +} diff --git a/jdk/test/java/nio/file/WatchService/denyAll.policy b/jdk/test/java/nio/file/WatchService/denyAll.policy new file mode 100644 index 00000000000..32500947791 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/denyAll.policy @@ -0,0 +1,3 @@ +// policy file that does not grant any permissions +grant { +}; diff --git a/jdk/test/java/nio/file/WatchService/grantDirAndOneLevel.policy b/jdk/test/java/nio/file/WatchService/grantDirAndOneLevel.policy new file mode 100644 index 00000000000..1a34646464a --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/grantDirAndOneLevel.policy @@ -0,0 +1,5 @@ +// policy file that grants read access to source directory and its entries +grant { + permission java.io.FilePermission "${test.src}", "read"; + permission java.io.FilePermission "${test.src}${file.separator}*", "read"; +}; diff --git a/jdk/test/java/nio/file/WatchService/grantDirAndTree.policy b/jdk/test/java/nio/file/WatchService/grantDirAndTree.policy new file mode 100644 index 00000000000..85bc0d0fb51 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/grantDirAndTree.policy @@ -0,0 +1,5 @@ +// policy file that grants read access to source directory and all descendants +grant { + permission java.io.FilePermission "${test.src}", "read"; + permission java.io.FilePermission "${test.src}${file.separator}-", "read"; +}; diff --git a/jdk/test/java/nio/file/WatchService/grantDirOnly.policy b/jdk/test/java/nio/file/WatchService/grantDirOnly.policy new file mode 100644 index 00000000000..fca1539416f --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/grantDirOnly.policy @@ -0,0 +1,4 @@ +// policy file that grants read access to source directory +grant { + permission java.io.FilePermission "${test.src}", "read"; +}; diff --git a/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java new file mode 100644 index 00000000000..3a9960702f9 --- /dev/null +++ b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java @@ -0,0 +1,166 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.AclFileAttribueView + * @library ../.. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +import static java.nio.file.attribute.AclEntryType.*; +import static java.nio.file.attribute.AclEntryPermission.*; +import static java.nio.file.attribute.AclEntryFlag.*; + +public class Basic { + + static void printAcl(List acl) { + for (AclEntry entry: acl) { + System.out.format(" %s%n", entry); + } + } + + // sanity check read and writing ACL + static void testReadWrite(Path dir) throws IOException { + Path file = dir.resolve("foo"); + if (file.notExists()) + file.createFile(); + + AclFileAttributeView view = file + .getFileAttributeView(AclFileAttributeView.class); + + // print existing ACL + List acl = view.getAcl(); + System.out.println(" -- current ACL --"); + printAcl(acl); + + // insert entry to grant owner read access + UserPrincipal owner = view.getOwner(); + AclEntry entry = AclEntry.newBuilder() + .setType(ALLOW) + .setPrincipal(owner) + .setPermissions(READ_DATA, READ_ATTRIBUTES) + .build(); + System.out.println(" -- insert (entry 0) --"); + System.out.format(" %s%n", entry); + acl.add(0, entry); + view.setAcl(acl); + + // re-ACL and check entry + List newacl = view.getAcl(); + System.out.println(" -- current ACL --"); + printAcl(acl); + if (!newacl.get(0).equals(entry)) { + throw new RuntimeException("Entry 0 is not expected"); + } + + // if PosixFileAttributeView then repeat test with OWNER@ + if (file.getFileStore().supportsFileAttributeView("posix")) { + owner = file.getFileSystem().getUserPrincipalLookupService() + .lookupPrincipalByName("OWNER@"); + entry = AclEntry.newBuilder(entry).setPrincipal(owner).build(); + + System.out.println(" -- replace (entry 0) --"); + System.out.format(" %s%n", entry); + + acl.set(0, entry); + view.setAcl(acl); + newacl = view.getAcl(); + System.out.println(" -- current ACL --"); + printAcl(acl); + if (!newacl.get(0).equals(entry)) { + throw new RuntimeException("Entry 0 is not expected"); + } + } + } + + static FileAttribute> asAclAttribute(final List acl) { + return new FileAttribute>() { + public String name() { return "acl:acl"; } + public List value() { return acl; } + }; + } + + static void assertEquals(List actual, List expected) { + if (!actual.equals(expected)) { + System.err.format("Actual: %s\n", actual); + System.err.format("Expected: %s\n", expected); + throw new RuntimeException("ACL not expected"); + } + } + + // sanity check create a file or directory with initial ACL + static void testCreateFile(Path dir) throws IOException { + UserPrincipal user = Attributes.getOwner(dir); + + // create file with initial ACL + System.out.println("-- create file with initial ACL --"); + Path file = dir.resolve("gus"); + List fileAcl = Arrays.asList( + AclEntry.newBuilder() + .setType(AclEntryType.ALLOW) + .setPrincipal(user) + .setPermissions(SYNCHRONIZE, READ_DATA, WRITE_DATA, + READ_ATTRIBUTES, READ_ACL, WRITE_ATTRIBUTES, DELETE) + .build()); + file.createFile(asAclAttribute(fileAcl)); + assertEquals(Attributes.getAcl(file), fileAcl); + + // create directory with initial ACL + System.out.println("-- create directory with initial ACL --"); + Path subdir = dir.resolve("stuff"); + List dirAcl = Arrays.asList( + AclEntry.newBuilder() + .setType(AclEntryType.ALLOW) + .setPrincipal(user) + .setPermissions(SYNCHRONIZE, ADD_FILE, DELETE) + .build(), + AclEntry.newBuilder(fileAcl.get(0)) + .setFlags(FILE_INHERIT) + .build()); + subdir.createDirectory(asAclAttribute(dirAcl)); + assertEquals(Attributes.getAcl(subdir), dirAcl); + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + if (!dir.getFileStore().supportsFileAttributeView("acl")) { + System.out.println("ACLs not supported - test skipped!"); + return; + } + testReadWrite(dir); + + // only currently feasible on Windows + if (System.getProperty("os.name").startsWith("Windows")) + testCreateFile(dir); + + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/Attributes/Basic.java b/jdk/test/java/nio/file/attribute/Attributes/Basic.java new file mode 100644 index 00000000000..8dfde80d9a5 --- /dev/null +++ b/jdk/test/java/nio/file/attribute/Attributes/Basic.java @@ -0,0 +1,254 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.Attributes + * @library ../.. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Exercises getAttribute/setAttribute/readAttributes methods. + */ + +public class Basic { + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion Failed"); + } + + static void checkEqual(Object o1, Object o2) { + if (o1 == null) { + assertTrue(o2 == null); + } else { + assertTrue (o1.equals(o2)); + } + } + + // Exercise getAttribute/setAttribute/readAttributes on basic attributes + static void checkBasicAttributes(FileRef file, BasicFileAttributes attrs) + throws IOException + { + // getAttribute + checkEqual(attrs.size(), Attributes.getAttribute(file, "size")); + checkEqual(attrs.lastModifiedTime(), + Attributes.getAttribute(file, "basic:lastModifiedTime")); + checkEqual(attrs.lastAccessTime(), + Attributes.getAttribute(file, "lastAccessTime")); + checkEqual(attrs.creationTime(), + Attributes.getAttribute(file, "basic:creationTime")); + assertTrue((Boolean)Attributes.getAttribute(file, "isRegularFile")); + assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isDirectory")); + assertTrue(!(Boolean)Attributes.getAttribute(file, "isSymbolicLink")); + assertTrue(!(Boolean)Attributes.getAttribute(file, "basic:isOther")); + checkEqual(attrs.linkCount(), + (Integer)Attributes.getAttribute(file, "linkCount")); + checkEqual(attrs.fileKey(), Attributes.getAttribute(file, "basic:fileKey")); + + // setAttribute + if (attrs.resolution() == TimeUnit.MILLISECONDS) { + long modTime = attrs.lastModifiedTime(); + Attributes.setAttribute(file, "basic:lastModifiedTime", 0L); + assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == 0L); + Attributes.setAttribute(file, "lastModifiedTime", modTime); + assertTrue(Attributes.readBasicFileAttributes(file).lastModifiedTime() == modTime); + } + + // readAttributes + Map map; + map = Attributes.readAttributes(file, "*"); + assertTrue(map.size() >= 11); + checkEqual(attrs.isRegularFile(), map.get("isRegularFile")); // check one + + map = Attributes.readAttributes(file, "basic:*"); + assertTrue(map.size() >= 11); + checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); // check one + + map = Attributes.readAttributes(file, "size,lastModifiedTime"); + assertTrue(map.size() == 2); + checkEqual(attrs.size(), map.get("size")); + checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); + + map = Attributes.readAttributes(file, + "basic:lastModifiedTime,lastAccessTime,linkCount,ShouldNotExist"); + assertTrue(map.size() == 3); + checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); + checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); + checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); + } + + // Exercise getAttribute/setAttribute/readAttributes on posix attributes + static void checkPosixAttributes(FileRef file, PosixFileAttributes attrs) + throws IOException + { + checkBasicAttributes(file, attrs); + + // getAttribute + checkEqual(attrs.permissions(), + Attributes.getAttribute(file, "posix:permissions")); + checkEqual(attrs.owner(), + Attributes.getAttribute(file, "posix:owner")); + checkEqual(attrs.group(), + Attributes.getAttribute(file, "posix:group")); + + // setAttribute + Set orig = attrs.permissions(); + Set newPerms = new HashSet(orig); + newPerms.remove(PosixFilePermission.OTHERS_READ); + newPerms.remove(PosixFilePermission.OTHERS_WRITE); + newPerms.remove(PosixFilePermission.OTHERS_EXECUTE); + Attributes.setAttribute(file, "posix:permissions", newPerms); + checkEqual(Attributes.readPosixFileAttributes(file).permissions(), newPerms); + Attributes.setAttribute(file, "posix:permissions", orig); + checkEqual(Attributes.readPosixFileAttributes(file).permissions(), orig); + Attributes.setAttribute(file, "posix:owner", attrs.owner()); + Attributes.setAttribute(file, "posix:group", attrs.group()); + + // readAttributes + Map map; + map = Attributes.readAttributes(file, "posix:*"); + assertTrue(map.size() >= 14); + checkEqual(attrs.permissions(), map.get("permissions")); // check one + + map = Attributes.readAttributes(file, "posix:size,owner,ShouldNotExist"); + assertTrue(map.size() == 2); + checkEqual(attrs.size(), map.get("size")); + checkEqual(attrs.owner(), map.get("owner")); + } + + // Exercise getAttribute/setAttribute/readAttributes on unix attributes + static void checkUnixAttributes(FileRef file) throws IOException { + // getAttribute + int mode = (Integer)Attributes.getAttribute(file, "unix:mode"); + long ino = (Long)Attributes.getAttribute(file, "unix:ino"); + long dev = (Long)Attributes.getAttribute(file, "unix:dev"); + long rdev = (Long)Attributes.getAttribute(file, "unix:rdev"); + int uid = (Integer)Attributes.getAttribute(file, "unix:uid"); + int gid = (Integer)Attributes.getAttribute(file, "unix:gid"); + long ctime = (Long)Attributes.getAttribute(file, "unix:ctime"); + + // readAttributes + Map map; + map = Attributes.readAttributes(file, "unix:*"); + assertTrue(map.size() >= 21); + + map = Attributes.readAttributes(file, "unix:size,uid,gid,ShouldNotExist"); + assertTrue(map.size() == 3); + checkEqual(map.get("size"), + Attributes.readBasicFileAttributes(file).size()); + } + + // Exercise getAttribute/setAttribute/readAttributes on dos attributes + static void checkDosAttributes(FileRef file, DosFileAttributes attrs) + throws IOException + { + checkBasicAttributes(file, attrs); + + // getAttribute + checkEqual(attrs.isReadOnly(), + Attributes.getAttribute(file, "dos:readonly")); + checkEqual(attrs.isHidden(), + Attributes.getAttribute(file, "dos:hidden")); + checkEqual(attrs.isSystem(), + Attributes.getAttribute(file, "dos:system")); + checkEqual(attrs.isArchive(), + Attributes.getAttribute(file, "dos:archive")); + + // setAttribute + boolean value; + + value = attrs.isReadOnly(); + Attributes.setAttribute(file, "dos:readonly", !value); + checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), !value); + Attributes.setAttribute(file, "dos:readonly", value); + checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), value); + + value = attrs.isHidden(); + Attributes.setAttribute(file, "dos:hidden", !value); + checkEqual(Attributes.readDosFileAttributes(file).isHidden(), !value); + Attributes.setAttribute(file, "dos:hidden", value); + checkEqual(Attributes.readDosFileAttributes(file).isHidden(), value); + + value = attrs.isSystem(); + Attributes.setAttribute(file, "dos:system", !value); + checkEqual(Attributes.readDosFileAttributes(file).isSystem(), !value); + Attributes.setAttribute(file, "dos:system", value); + checkEqual(Attributes.readDosFileAttributes(file).isSystem(), value); + + value = attrs.isArchive(); + Attributes.setAttribute(file, "dos:archive", !value); + checkEqual(Attributes.readDosFileAttributes(file).isArchive(), !value); + Attributes.setAttribute(file, "dos:archive", value); + checkEqual(Attributes.readDosFileAttributes(file).isArchive(), value); + + // readAttributes + Map map; + map = Attributes.readAttributes(file, "dos:*"); + assertTrue(map.size() >= 15); + checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one + + map = Attributes.readAttributes(file, "dos:size,hidden,ShouldNotExist"); + assertTrue(map.size() == 2); + checkEqual(attrs.size(), map.get("size")); + checkEqual(attrs.isHidden(), map.get("hidden")); + } + + static void doTests(Path dir) throws IOException { + Path file = dir.resolve("foo").createFile(); + FileStore store = file.getFileStore(); + try { + checkBasicAttributes(file, + Attributes.readBasicFileAttributes(file)); + + if (store.supportsFileAttributeView("posix")) + checkPosixAttributes(file, + Attributes.readPosixFileAttributes(file)); + + if (store.supportsFileAttributeView("unix")) + checkUnixAttributes(file); + + if (store.supportsFileAttributeView("dos")) + checkDosAttributes(file, + Attributes.readDosFileAttributes(file)); + } finally { + file.delete(); + } + } + + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + doTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java new file mode 100644 index 00000000000..1cc192f2a45 --- /dev/null +++ b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java @@ -0,0 +1,150 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.BasicFileAttributeView + * @library ../.. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.io.*; + +public class Basic { + + static void check(boolean okay, String msg) { + if (!okay) + throw new RuntimeException(msg); + } + + static void checkAttributesOfDirectory(Path dir) + throws IOException + { + BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir); + check(attrs.isDirectory(), "is a directory"); + check(!attrs.isRegularFile(), "is not a regular file"); + check(!attrs.isSymbolicLink(), "is not a link"); + check(!attrs.isOther(), "is not other"); + check(attrs.linkCount() >= 1, "should be at least 1"); + + // last-modified-time should match java.io.File + if (attrs.resolution() == TimeUnit.MILLISECONDS) { + File f = new File(dir.toString()); + check(f.lastModified() == attrs.lastModifiedTime(), + "last-modified time should be the same"); + } + } + + static void checkAttributesOfFile(Path dir, Path file) + throws IOException + { + BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file); + check(attrs.isRegularFile(), "is a regular file"); + check(!attrs.isDirectory(), "is not a directory"); + check(!attrs.isSymbolicLink(), "is not a link"); + check(!attrs.isOther(), "is not other"); + check(attrs.linkCount() >= 1, "should be at least 1"); + + // size and last-modified-time should match java.io.File + File f = new File(file.toString()); + check(f.length() == attrs.size(), "size should be the same"); + if (attrs.resolution() == TimeUnit.MILLISECONDS) { + check(f.lastModified() == attrs.lastModifiedTime(), + "last-modified time should be the same"); + } + + // copy last-modified time and file create time from directory to file, + // re-read attribtues, and check they match + BasicFileAttributeView view = + file.getFileAttributeView(BasicFileAttributeView.class); + BasicFileAttributes dirAttrs = Attributes.readBasicFileAttributes(dir); + view.setTimes(dirAttrs.lastModifiedTime(), null, null, dirAttrs.resolution()); + if (dirAttrs.creationTime() != -1L) { + view.setTimes(null, null, dirAttrs.creationTime(), dirAttrs.resolution()); + } + attrs = view.readAttributes(); + check(attrs.lastModifiedTime() == dirAttrs.lastModifiedTime(), + "last-modified time should be equal"); + if (dirAttrs.creationTime() != -1L) { + check(attrs.creationTime() == dirAttrs.creationTime(), + "create time should be the same"); + } + + // security tests + check (!(attrs instanceof PosixFileAttributes), + "should not be able to cast to PosixFileAttributes"); + } + + static void checkAttributesOfLink(Path link) + throws IOException + { + BasicFileAttributes attrs = Attributes + .readBasicFileAttributes(link, LinkOption.NOFOLLOW_LINKS); + check(attrs.isSymbolicLink(), "is a link"); + check(!attrs.isDirectory(), "is a directory"); + check(!attrs.isRegularFile(), "is not a regular file"); + check(!attrs.isOther(), "is not other"); + check(attrs.linkCount() >= 1, "should be at least 1"); + } + + static void attributeReadWriteTests(Path dir) + throws IOException + { + // create file + Path file = dir.resolve("foo"); + OutputStream out = file.newOutputStream(); + try { + out.write("this is not an empty file".getBytes("UTF-8")); + } finally { + out.close(); + } + + // check attributes of directory and file + checkAttributesOfDirectory(dir); + checkAttributesOfFile(dir, file); + + // symbolic links may be supported + Path link = dir.resolve("link"); + try { + link.createSymbolicLink( file ); + } catch (UnsupportedOperationException x) { + return; + } catch (IOException x) { + return; + } + checkAttributesOfLink(link); + } + + public static void main(String[] args) throws IOException { + // create temporary directory to run tests + Path dir = TestUtil.createTemporaryDirectory(); + try { + attributeReadWriteTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java new file mode 100644 index 00000000000..3c8a296188b --- /dev/null +++ b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java @@ -0,0 +1,155 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.DosFileAttributeView + * @library ../.. + */ + +import java.nio.file.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.io.IOException; + +public class Basic { + + static void check(boolean okay) { + if (!okay) + throw new RuntimeException("Test failed"); + } + + // exercise each setter/getter method, leaving all attributes unset + static void testAttributes(DosFileAttributeView view) throws IOException { + view.setReadOnly(true); + check(view.readAttributes().isReadOnly()); + view.setReadOnly(false); + check(!view.readAttributes().isReadOnly()); + view.setHidden(true); + check(view.readAttributes().isHidden()); + view.setHidden(false); + check(!view.readAttributes().isHidden()); + view.setArchive(true); + check(view.readAttributes().isArchive()); + view.setArchive(false); + check(!view.readAttributes().isArchive()); + view.setSystem(true); + check(view.readAttributes().isSystem()); + view.setSystem(false); + check(!view.readAttributes().isSystem()); + } + + // set the value of all attributes + static void setAll(DosFileAttributeView view, boolean value) + throws IOException + { + view.setReadOnly(value); + view.setHidden(value); + view.setArchive(value); + view.setSystem(value); + } + + // read and write FAT attributes + static void readWriteTests(Path dir) throws IOException { + + // create "foo" and test that we can read/write each FAT attribute + Path file = dir.resolve("foo"); + file.newOutputStream().close(); + try { + testAttributes(file + .getFileAttributeView(DosFileAttributeView.class)); + + // Following tests use a symbolic link so skip if not supported + if (!TestUtil.supportsLinks(dir)) + return; + + Path link = dir.resolve("link").createSymbolicLink(file); + + // test following links + testAttributes(link + .getFileAttributeView(DosFileAttributeView.class)); + + // test not following links + try { + try { + testAttributes(link + .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS)); + } catch (IOException x) { + // access to link attributes not supported + return; + } + + // set all attributes on link + // run test on target of link (which leaves them all un-set) + // check that attributes of link remain all set + setAll(link + .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), true); + testAttributes(link + .getFileAttributeView(DosFileAttributeView.class)); + DosFileAttributes attrs = Attributes.readDosFileAttributes(link, NOFOLLOW_LINKS); + check(attrs.isReadOnly()); + check(attrs.isHidden()); + check(attrs.isArchive()); + check(attrs.isSystem()); + setAll(link + .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), false); + + // set all attributes on target + // run test on link (which leaves them all un-set) + // check that attributes of target remain all set + setAll(link + .getFileAttributeView(DosFileAttributeView.class), true); + testAttributes(link + .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS)); + attrs = Attributes.readDosFileAttributes(link); + check(attrs.isReadOnly()); + check(attrs.isHidden()); + check(attrs.isArchive()); + check(attrs.isSystem()); + setAll(link + .getFileAttributeView(DosFileAttributeView.class), false); + } finally { + TestUtil.deleteUnchecked(link); + } + } finally { + TestUtil.deleteUnchecked(file); + } + } + + public static void main(String[] args) throws IOException { + // create temporary directory to run tests + Path dir = TestUtil.createTemporaryDirectory(); + + try { + // skip test if DOS file attributes not supported + if (!dir.getFileStore().supportsFileAttributeView("dos")) { + System.out.println("DOS file attribute not supported."); + return; + } + readWriteTests(dir); + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java new file mode 100644 index 00000000000..993e8c1ddec --- /dev/null +++ b/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java @@ -0,0 +1,171 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.FileStoreAttributeView + * @library ../.. + */ + +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.File; +import java.io.IOException; +import java.util.*; + +/** + * Simple unit test for FileStoreAttributeView that checks that the disk space + * attribtues are "close" to the equivalent values reported by java.io.File. + */ + +public class Basic { + + static final long K = 1024L; + static final long G = 1024L * 1024L * 1024L; + + /** + * Print out the disk space information for the given file system + */ + static void printFileStore(FileStore fs) throws IOException { + FileStoreSpaceAttributeView view = + fs.getFileStoreAttributeView(FileStoreSpaceAttributeView.class); + FileStoreSpaceAttributes attrs = view.readAttributes(); + + long total = attrs.totalSpace() / K; + long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K; + long avail = attrs.usableSpace() / K; + + String s = fs.toString(); + if (s.length() > 20) { + System.out.println(s); + s = ""; + } + System.out.format("%-20s %12d %12d %12d\n", s, total, used, avail); + } + + /** + * Check that two values are within 1GB of each other + */ + static void checkWithin1GB(long value1, long value2) { + long diff = Math.abs(value1 - value2); + if (diff > G) + throw new RuntimeException("values differ by more than 1GB"); + } + + /** + * Check disk space on the file system of the given file + */ + static void checkSpace(Path file) throws IOException { + System.out.println(" -- check space -- "); + System.out.println(file); + + FileStore fs = file.getFileStore(); + System.out.format("Filesystem: %s\n", fs); + + // get values reported by java.io.File + File f = new File(file.toString()); + long total = f.getTotalSpace(); + long free = f.getFreeSpace(); + long usable = f.getUsableSpace(); + System.out.println("java.io.File"); + System.out.format(" Total: %d\n", total); + System.out.format(" Free: %d\n", free); + System.out.format(" Usable: %d\n", usable); + + // get values reported by the FileStoreSpaceAttributeView + FileStoreSpaceAttributes attrs = fs + .getFileStoreAttributeView(FileStoreSpaceAttributeView.class) + .readAttributes(); + System.out.println("java.nio.file.FileStoreSpaceAttributeView:"); + System.out.format(" Total: %d\n", attrs.totalSpace()); + System.out.format(" Free: %d\n", attrs.unallocatedSpace()); + System.out.format(" Usable: %d\n", attrs.usableSpace()); + + // check values are "close" + checkWithin1GB(total, attrs.totalSpace()); + checkWithin1GB(free, attrs.unallocatedSpace()); + checkWithin1GB(usable, attrs.usableSpace()); + + // get values by name (and in bulk) + FileStoreAttributeView view = fs.getFileStoreAttributeView("space"); + checkWithin1GB(total, (Long)view.getAttribute("totalSpace")); + checkWithin1GB(free, (Long)view.getAttribute("unallocatedSpace")); + checkWithin1GB(usable, (Long)view.getAttribute("usableSpace")); + Map map = view.readAttributes("*"); + checkWithin1GB(total, (Long)map.get("totalSpace")); + checkWithin1GB(free, (Long)map.get("unallocatedSpace")); + checkWithin1GB(usable, (Long)map.get("usableSpace")); + map = view.readAttributes("totalSpace", "unallocatedSpace", "usableSpace"); + checkWithin1GB(total, (Long)map.get("totalSpace")); + checkWithin1GB(free, (Long)map.get("unallocatedSpace")); + checkWithin1GB(usable, (Long)map.get("usableSpace")); + } + + /** + * Check (Windows-specific) volume attributes + */ + static void checkVolumeAttributes() throws IOException { + System.out.println(" -- volumes -- "); + for (FileStore store: FileSystems.getDefault().getFileStores()) { + FileStoreAttributeView view = store.getFileStoreAttributeView("volume"); + if (view == null) + continue; + Map attrs = view.readAttributes("*"); + int vsn = (Integer)attrs.get("vsn"); + boolean compressed = (Boolean)attrs.get("compressed"); + boolean removable = (Boolean)attrs.get("removable"); + boolean cdrom = (Boolean)attrs.get("cdrom"); + String type; + if (removable) type = "removable"; + else if (cdrom) type = "cdrom"; + else type = "unknown"; + System.out.format("%s (%s) vsn:%x compressed:%b%n", store.name(), + type, vsn, compressed); + } + + } + + public static void main(String[] args) throws IOException { + // print out the disk space information for all file systems + FileSystem fs = FileSystems.getDefault(); + for (FileStore store: fs.getFileStores()) { + printFileStore(store); + } + + Path dir = TestUtil.createTemporaryDirectory(); + try { + // check space using directory + checkSpace(dir); + + // check space using file + Path file = dir.resolve("foo").createFile(); + checkSpace(file); + + // volume attributes (Windows specific) + checkVolumeAttributes(); + + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java new file mode 100644 index 00000000000..2ee059bb95d --- /dev/null +++ b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java @@ -0,0 +1,398 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.PosixFileAttributeView + * @library ../.. + */ + +import java.nio.file.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.*; + +/** + * Unit test for PosixFileAttributeView, passing silently if this attribute + * view is not available. + */ + +public class Basic { + + /** + * Use view to update permission to the given mode and check that the + * permissions have been updated. + */ + static void testPermissions(PosixFileAttributeView view, String mode) + throws IOException + { + System.out.format("change mode: %s\n", mode); + Set perms = PosixFilePermissions.fromString(mode); + + // change permissions and re-read them. + view.setPermissions(perms); + Set current = view.readAttributes().permissions(); + if (!current.equals(perms)) { + throw new RuntimeException("Actual permissions: " + + PosixFilePermissions.toString(current) + ", expected: " + + PosixFilePermissions.toString(perms)); + } + + // repeat test using setAttribute/getAttribute + view.setAttribute("permissions", perms); + current = (Set)view.getAttribute("permissions"); + if (!current.equals(perms)) { + throw new RuntimeException("Actual permissions: " + + PosixFilePermissions.toString(current) + ", expected: " + + PosixFilePermissions.toString(perms)); + } + } + + /** + * Check that the actual permissions of a file match or make it more + * secure than requested + */ + static void checkSecure(Set requested, + Set actual) + { + for (PosixFilePermission perm: actual) { + if (!requested.contains(perm)) { + throw new RuntimeException("Actual permissions: " + + PosixFilePermissions.toString(actual) + ", requested: " + + PosixFilePermissions.toString(requested) + + " - file is less secure than requested"); + } + } + } + + /** + * Create file with given mode and check that the file is created with a + * mode that is not less secure + */ + static void createWithPermissions(Path file, + String mode) + throws IOException + { + Set requested = PosixFilePermissions.fromString(mode); + FileAttribute> attr = + PosixFilePermissions.asFileAttribute(requested); + System.out.format("create file with mode: %s\n", mode); + + EnumSet options = EnumSet.of(StandardOpenOption.CREATE_NEW, + StandardOpenOption.WRITE); + file.newOutputStream(options, attr).close(); + try { + checkSecure(requested, file + .getFileAttributeView(PosixFileAttributeView.class) + .readAttributes() + .permissions()); + } finally { + file.delete(false); + } + + System.out.format("create directory with mode: %s\n", mode); + file.createDirectory(attr); + try { + checkSecure(requested, file + .getFileAttributeView(PosixFileAttributeView.class) + .readAttributes() + .permissions()); + } finally { + file.delete(false); + } + } + + /** + * Test the setPermissions/permissions methods. + */ + static void permissionTests(Path dir) + throws IOException + { + System.out.println("-- Permission Tests --"); + + // create file and test updating and reading its permissions + Path file = dir.resolve("foo"); + System.out.format("create %s\n", file); + file.newOutputStream().close(); + try { + // get initial permissions so that we can restore them later + PosixFileAttributeView view = file + .getFileAttributeView(PosixFileAttributeView.class); + Set save = view.readAttributes() + .permissions(); + + // test various modes + try { + testPermissions(view, "---------"); + testPermissions(view, "r--------"); + testPermissions(view, "-w-------"); + testPermissions(view, "--x------"); + testPermissions(view, "rwx------"); + testPermissions(view, "---r-----"); + testPermissions(view, "----w----"); + testPermissions(view, "-----x---"); + testPermissions(view, "---rwx---"); + testPermissions(view, "------r--"); + testPermissions(view, "-------w-"); + testPermissions(view, "--------x"); + testPermissions(view, "------rwx"); + testPermissions(view, "r--r-----"); + testPermissions(view, "r--r--r--"); + testPermissions(view, "rw-rw----"); + testPermissions(view, "rwxrwx---"); + testPermissions(view, "rw-rw-r--"); + testPermissions(view, "r-xr-x---"); + testPermissions(view, "r-xr-xr-x"); + testPermissions(view, "rwxrwxrwx"); + } finally { + view.setPermissions(save); + } + } finally { + file.delete(false); + } + + // create link (to file that doesn't exist) and test reading of + // permissions + if (TestUtil.supportsLinks(dir)) { + Path link = dir.resolve("link"); + System.out.format("create link %s\n", link); + link.createSymbolicLink(file); + try { + PosixFileAttributes attrs = Attributes + .readPosixFileAttributes(link, NOFOLLOW_LINKS); + if (!attrs.isSymbolicLink()) { + throw new RuntimeException("not a link"); + } + } finally { + link.delete(false); + } + } + + System.out.println("OKAY"); + } + + /** + * Test creating a file and directory with initial permissios + */ + static void createTests(Path dir) + throws IOException + { + System.out.println("-- Create Tests --"); + + Path file = dir.resolve("foo"); + + createWithPermissions(file, "---------"); + createWithPermissions(file, "r--------"); + createWithPermissions(file, "-w-------"); + createWithPermissions(file, "--x------"); + createWithPermissions(file, "rwx------"); + createWithPermissions(file, "---r-----"); + createWithPermissions(file, "----w----"); + createWithPermissions(file, "-----x---"); + createWithPermissions(file, "---rwx---"); + createWithPermissions(file, "------r--"); + createWithPermissions(file, "-------w-"); + createWithPermissions(file, "--------x"); + createWithPermissions(file, "------rwx"); + createWithPermissions(file, "r--r-----"); + createWithPermissions(file, "r--r--r--"); + createWithPermissions(file, "rw-rw----"); + createWithPermissions(file, "rwxrwx---"); + createWithPermissions(file, "rw-rw-r--"); + createWithPermissions(file, "r-xr-x---"); + createWithPermissions(file, "r-xr-xr-x"); + createWithPermissions(file, "rwxrwxrwx"); + + System.out.println("OKAY"); + } + + /** + * Test setOwner/setGroup methods - this test simply exercises the + * methods to avoid configuration. + */ + static void ownerTests(Path dir) + throws IOException + { + System.out.println("-- Owner Tests --"); + + Path file = dir.resolve("gus"); + System.out.format("create %s\n", file); + + file.newOutputStream().close(); + try { + + // read attributes of directory to get owner/group + PosixFileAttributeView view = file + .getFileAttributeView(PosixFileAttributeView.class); + PosixFileAttributes attrs = view.readAttributes(); + + // set to existing owner/group + view.setOwner(attrs.owner()); + view.setGroup(attrs.group()); + + // repeat test using setAttribute + Map map = view.readAttributes("owner","group"); + view.setAttribute("owner", map.get("owner")); + view.setAttribute("group", map.get("group")); + + } finally { + file.delete(false); + } + + System.out.println("OKAY"); + } + + /** + * Test the lookupPrincipalByName/lookupPrincipalByGroupName methods + */ + static void lookupPrincipalTests(Path dir) + throws IOException + { + System.out.println("-- Lookup UserPrincipal Tests --"); + + UserPrincipalLookupService lookupService = dir.getFileSystem() + .getUserPrincipalLookupService(); + + // read attributes of directory to get owner/group + PosixFileAttributes attrs = Attributes.readPosixFileAttributes(dir); + + // lookup owner and check it matches file's owner + System.out.format("lookup: %s\n", attrs.owner().getName()); + try { + UserPrincipal owner = lookupService.lookupPrincipalByName(attrs.owner().getName()); + if (owner instanceof GroupPrincipal) + throw new RuntimeException("owner is a group?"); + if (!owner.equals(attrs.owner())) + throw new RuntimeException("owner different from file owner"); + } catch (UserPrincipalNotFoundException x) { + System.out.println("user not found - test skipped"); + } + + // lookup group and check it matches file's group-owner + System.out.format("lookup group: %s\n", attrs.group().getName()); + try { + GroupPrincipal group = lookupService.lookupPrincipalByGroupName(attrs.group().getName()); + if (!group.equals(attrs.group())) + throw new RuntimeException("group different from file group-owner"); + } catch (UserPrincipalNotFoundException x) { + System.out.println("group not found - test skipped"); + } + + // test that UserPrincipalNotFoundException is thrown + String invalidPrincipal = "scumbag99"; + try { + System.out.format("lookup: %s\n", invalidPrincipal); + lookupService.lookupPrincipalByName(invalidPrincipal); + throw new RuntimeException("'" + invalidPrincipal + "' is a valid user?"); + } catch (UserPrincipalNotFoundException x) { + } + try { + System.out.format("lookup group: %s\n", invalidPrincipal); + lookupService.lookupPrincipalByGroupName("idonotexist"); + throw new RuntimeException("'" + invalidPrincipal + "' is a valid group?"); + } catch (UserPrincipalNotFoundException x) { + } + System.out.println("OKAY"); + } + + /** + * Test various exceptions are thrown as expected + */ + @SuppressWarnings("unchecked") + static void exceptionsTests(Path dir) + throws IOException + { + System.out.println("-- Exceptions --"); + + PosixFileAttributeView view = dir + .getFileAttributeView(PosixFileAttributeView.class); + + // NullPointerException + try { + view.setOwner(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + view.setGroup(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + + UserPrincipalLookupService lookupService = dir.getFileSystem() + .getUserPrincipalLookupService(); + try { + lookupService.lookupPrincipalByName(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + lookupService.lookupPrincipalByGroupName(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + view.setPermissions(null); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + try { + Set perms = new HashSet(); + perms.add(null); + view.setPermissions(perms); + throw new RuntimeException("NullPointerException not thrown"); + } catch (NullPointerException x) { + } + + // ClassCastException + try { + Set perms = new HashSet(); // raw type + perms.add(new Object()); + view.setPermissions(perms); + throw new RuntimeException("ClassCastException not thrown"); + } catch (ClassCastException x) { + } + + System.out.println("OKAY"); + } + + public static void main(String[] args) throws IOException { + Path dir = TestUtil.createTemporaryDirectory(); + try { + if (!dir.getFileStore().supportsFileAttributeView("posix")) { + System.out.println("PosixFileAttributeView not supported"); + return; + } + + permissionTests(dir); + createTests(dir); + ownerTests(dir); + lookupPrincipalTests(dir); + exceptionsTests(dir); + + } finally { + TestUtil.removeAll(dir); + } + } +} diff --git a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java new file mode 100644 index 00000000000..ffdb5b86e89 --- /dev/null +++ b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java @@ -0,0 +1,273 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.attribute.UserDefinedFileAttributeView + * @library ../.. + */ + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.file.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; +import java.util.Arrays; +import java.util.Map; +import java.util.Random; +import java.io.IOException; + +public class Basic { + + private static Random rand = new Random(); + + private static final String ATTR_NAME = "mime_type"; + private static final String ATTR_VALUE = "text/plain"; + private static final String ATTR_VALUE2 = "text/html"; + + static interface Task { + void run() throws Exception; + } + + static void tryCatch(Class ex, Task task) { + boolean caught = false; + try { + task.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) { + caught = true; + } else { + throw new RuntimeException(x); + } + } + if (!caught) + throw new RuntimeException(ex.getName() + " expected"); + } + + static void expectNullPointerException(Task task) { + tryCatch(NullPointerException.class, task); + } + + static boolean hasAttribute(UserDefinedFileAttributeView view, String attr) + throws IOException + { + for (String name: view.list()) { + if (name.equals(ATTR_NAME)) + return true; + } + return false; + } + + static void test(Path file, LinkOption... options) throws IOException { + final UserDefinedFileAttributeView view = file + .getFileAttributeView(UserDefinedFileAttributeView.class, options); + ByteBuffer buf = rand.nextBoolean() ? + ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100); + + // Test: write + buf.put(ATTR_VALUE.getBytes()).flip(); + int size = buf.remaining(); + int nwrote = view.write(ATTR_NAME, buf); + if (nwrote != size) + throw new RuntimeException("Unexpected number of bytes written"); + + // Test: size + if (view.size(ATTR_NAME) != size) + throw new RuntimeException("Unexpected size"); + + // Test: read + buf.clear(); + int nread = view.read(ATTR_NAME, buf); + if (nread != size) + throw new RuntimeException("Unexpected number of bytes read"); + buf.flip(); + String value = Charset.defaultCharset().decode(buf).toString(); + if (!value.equals(ATTR_VALUE)) + throw new RuntimeException("Unexpected attribute value"); + + // Test: read with insufficient space + tryCatch(IOException.class, new Task() { + public void run() throws IOException { + view.read(ATTR_NAME, ByteBuffer.allocateDirect(1)); + }}); + + // Test: replace value + buf.clear(); + buf.put(ATTR_VALUE2.getBytes()).flip(); + size = buf.remaining(); + view.write(ATTR_NAME, buf); + if (view.size(ATTR_NAME) != size) + throw new RuntimeException("Unexpected size"); + + // Test: list + if (!hasAttribute(view, ATTR_NAME)) + throw new RuntimeException("Attribute name not in list"); + + // Test: delete + view.delete(ATTR_NAME); + if (hasAttribute(view, ATTR_NAME)) + throw new RuntimeException("Attribute name in list"); + + // Test: dynamic access + byte[] valueAsBytes = ATTR_VALUE.getBytes(); + view.setAttribute(ATTR_NAME, valueAsBytes); + byte[] actualAsBytes = (byte[])view.getAttribute(ATTR_NAME); + if (!Arrays.equals(valueAsBytes, actualAsBytes)) + throw new RuntimeException("Unexpected attribute value"); + Map map = view.readAttributes(ATTR_NAME); + if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) + throw new RuntimeException("Unexpected attribute value"); + map = view.readAttributes(ATTR_NAME, "*"); + if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) + throw new RuntimeException("Unexpected attribute value"); + map = view.readAttributes("DoesNotExist"); + if (!map.isEmpty()) + throw new RuntimeException("Map expected to be empty"); + } + + static void miscTests(Path file) throws IOException { + final UserDefinedFileAttributeView view = file + .getFileAttributeView(UserDefinedFileAttributeView.class); + view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes())); + + // NullPointerException + final ByteBuffer buf = ByteBuffer.allocate(100); + + expectNullPointerException(new Task() { + public void run() throws IOException { + view.read(null, buf); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.read(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.write(null, buf); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.write(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.size(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.delete(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.getAttribute(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.setAttribute(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.setAttribute(null, new byte[0]); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes("*", (String[])null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes("*", ATTR_NAME, null); + }}); + + // Read-only buffer + tryCatch(IllegalArgumentException.class, new Task() { + public void run() throws IOException { + ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer(); + view.write(ATTR_NAME, buf); + buf.flip(); + view.read(ATTR_NAME, buf); + }}); + + // Zero bytes remaining + tryCatch(IOException.class, new Task() { + public void run() throws IOException { + ByteBuffer buf = buf = ByteBuffer.allocateDirect(100); + buf.position(buf.capacity()); + view.read(ATTR_NAME, buf); + }}); + } + + public static void main(String[] args) throws IOException { + // create temporary directory to run tests + Path dir = TestUtil.createTemporaryDirectory(); + try { + if (!dir.getFileStore().supportsFileAttributeView("xattr")) { + System.out.println("UserDefinedFileAttributeView not supported - skip test"); + return; + } + + // test access to user defined attributes of regular file + Path file = dir.resolve("foo.html").createFile(); + try { + test(file); + } finally { + file.delete(); + } + + // test access to user define attributes of directory + file = dir.resolve("foo").createDirectory(); + try { + test(file); + } finally { + file.delete(); + } + + // test access to user defined attributes of sym link + if (TestUtil.supportsLinks(dir)) { + Path target = dir.resolve("doesnotexist"); + Path link = dir.resolve("link").createSymbolicLink(target); + try { + test(link, NOFOLLOW_LINKS); + } catch (IOException x) { + // access to attributes of sym link may not be supported + } finally { + link.delete(); + } + } + + // misc. tests + try { + file = dir.resolve("foo.txt").createFile(); + miscTests(dir); + } finally { + file.delete(); + } + + } finally { + TestUtil.removeAll(dir); + } + } + } diff --git a/jdk/test/java/nio/file/spi/SetDefaultProvider.java b/jdk/test/java/nio/file/spi/SetDefaultProvider.java new file mode 100644 index 00000000000..fa600b05c9b --- /dev/null +++ b/jdk/test/java/nio/file/spi/SetDefaultProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 4313887 + * @summary Unit test for java.nio.file.spi.FileSystemProvider + * @build TestProvider SetDefaultProvider + * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider SetDefaultProvider + */ + +import java.nio.file.*; +import java.nio.file.spi.*; + +public class SetDefaultProvider { + public static void main(String[] args) throws Exception { + Class c = FileSystems.getDefault().provider().getClass(); + + Class expected = Class.forName("TestProvider", false, + ClassLoader.getSystemClassLoader()); + + if (c != expected) + throw new RuntimeException(); + } +} diff --git a/jdk/test/java/nio/file/spi/TestProvider.java b/jdk/test/java/nio/file/spi/TestProvider.java new file mode 100644 index 00000000000..a6868acb63c --- /dev/null +++ b/jdk/test/java/nio/file/spi/TestProvider.java @@ -0,0 +1,128 @@ +/* + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.nio.file.spi.FileSystemProvider; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.net.URI; +import java.util.*; +import java.io.IOException; + +public class TestProvider extends FileSystemProvider { + + private final FileSystem theFileSystem; + + public TestProvider(FileSystemProvider defaultProvider) { + theFileSystem = new TestFileSystem(this); + + } + + @Override + public String getScheme() { + return "file"; + } + + @Override + public FileSystem newFileSystem(URI uri, Map env) { + throw new RuntimeException("not implemented"); + } + + @Override + public FileSystem getFileSystem(URI uri) { + return theFileSystem; + } + + @Override + public Path getPath(URI uri) { + throw new RuntimeException("not implemented"); + } + + static class TestFileSystem extends FileSystem { + private final TestProvider provider; + + TestFileSystem(TestProvider provider) { + this.provider = provider; + } + + @Override + public FileSystemProvider provider() { + return provider; + } + + @Override + public void close() throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public boolean isOpen() { + throw new RuntimeException("not implemented"); + } + + @Override + public boolean isReadOnly() { + throw new RuntimeException("not implemented"); + } + + @Override + public String getSeparator() { + throw new RuntimeException("not implemented"); + } + + @Override + public Iterable getRootDirectories() { + throw new RuntimeException("not implemented"); + } + + @Override + public Iterable getFileStores() { + throw new RuntimeException("not implemented"); + } + + @Override + public Set supportedFileAttributeViews() { + throw new RuntimeException("not implemented"); + } + + @Override + public Path getPath(String path) { + throw new RuntimeException("not implemented"); + } + + @Override + public PathMatcher getPathMatcher(String syntaxAndPattern) { + throw new RuntimeException("not implemented"); + } + + @Override + public UserPrincipalLookupService getUserPrincipalLookupService() { + throw new RuntimeException("not implemented"); + } + + @Override + public WatchService newWatchService() throws IOException { + throw new RuntimeException("not implemented"); + } + } + +} diff --git a/jdk/test/java/security/cert/CertificateFactory/BadX509CertData.java b/jdk/test/java/security/cert/CertificateFactory/BadX509CertData.java index 6141afd9ade..87f81314578 100644 --- a/jdk/test/java/security/cert/CertificateFactory/BadX509CertData.java +++ b/jdk/test/java/security/cert/CertificateFactory/BadX509CertData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class BadX509CertData { InputStream is = new ByteArrayInputStream(data.getBytes("ISO8859_1")); try { Certificate cert = factory.generateCertificate(is); - } catch (CertificateParsingException ce) { + } catch (CertificateException ce) { return; } throw new Exception("CertificateFactory.generateCertificate() did " diff --git a/jdk/test/java/security/cert/CertificateFactory/openssl/OpenSSLCert.java b/jdk/test/java/security/cert/CertificateFactory/openssl/OpenSSLCert.java new file mode 100644 index 00000000000..5ea5b0bade1 --- /dev/null +++ b/jdk/test/java/security/cert/CertificateFactory/openssl/OpenSSLCert.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6535697 + * @summary keytool can be more flexible on format of PEM-encoded + * X.509 certificates + */ + +import java.io.*; +import java.util.Arrays; +import java.security.cert.CertificateFactory; + +public class OpenSSLCert { + static final String OUTFILE = "6535697.test"; + + public static void main(String[] args) throws Exception { + test("open"); + test("pem"); + test("open", "open"); + test("open", "pem"); + test("pem", "pem"); + test("pem", "open"); + test("open", "pem", "open"); + test("pem", "open", "pem"); + } + + static void test(String... files) throws Exception { + FileOutputStream fout = new FileOutputStream(OUTFILE); + for (String file: files) { + FileInputStream fin = new FileInputStream( + new File(System.getProperty("test.src", "."), file)); + byte[] buffer = new byte[4096]; + while (true) { + int len = fin.read(buffer); + if (len < 0) break; + fout.write(buffer, 0, len); + } + fin.close(); + } + fout.close(); + System.out.println("Testing " + Arrays.toString(files) + "..."); + if (CertificateFactory.getInstance("X509") + .generateCertificates(new FileInputStream(OUTFILE)) + .size() != files.length) { + throw new Exception("Not same number"); + } + } +} diff --git a/jdk/test/java/security/cert/CertificateFactory/openssl/open b/jdk/test/java/security/cert/CertificateFactory/openssl/open new file mode 100644 index 00000000000..c9b0d5e5aa0 --- /dev/null +++ b/jdk/test/java/security/cert/CertificateFactory/openssl/open @@ -0,0 +1,72 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1174535938 (0x4601ff02) + Signature Algorithm: dsaWithSHA1 + Issuer: C=EA, ST=Moon, L=Backside, O=A-B-C, OU=Office, CN=Me + Validity + Not Before: Mar 22 03:58:58 2007 GMT + Not After : Jun 20 03:58:58 2007 GMT + Subject: C=EA, ST=Moon, L=Backside, O=A-B-C, OU=Office, CN=Me + Subject Public Key Info: + Public Key Algorithm: dsaEncryption + DSA Public Key: + pub: + 00:c5:ce:e8:be:f0:de:27:9c:88:92:21:28:cf:a5: + 38:8d:c1:5f:e5:90:d2:0b:ea:d4:12:ca:86:b8:04: + 57:1d:41:74:3e:52:2d:87:b8:76:7b:d2:95:d7:67: + 30:76:35:47:fb:e9:86:bf:05:3f:9b:f2:6e:3a:96: + 9a:58:e1:05:44:78:02:31:ee:5f:67:6c:44:d2:95: + 8f:72:62:a4:3e:27:1c:f3:94:8a:1e:0b:98:4c:c0: + 9c:f4:3d:17:6d:36:e4:a0:12:04:01:e4:38:9e:bd: + 86:99:7b:84:43:9b:58:68:ef:ce:3d:85:e3:93:d1: + 1f:1a:18:a4:1e:59:ca:80:2e + P: + 00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec: + e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6: + 51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf: + c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34: + 6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b: + 10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7: + c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35: + 54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef: + f2:22:03:19:9d:d1:48:01:c7 + Q: + 00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb: + 84:0b:f0:58:1c:f5 + G: + 00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8: + 57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d: + 07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10: + 81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09: + 32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3: + ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62: + f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89: + a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55: + 25:64:01:4c:3b:fe:cf:49:2a + X509v3 extensions: + X509v3 Subject Key Identifier: + ED:BF:8A:CA:57:05:ED:5C:9A:72:65:69:6C:C1:02:F8:30:02:A4:6B + Signature Algorithm: dsaWithSHA1 + 30:2d:02:15:00:85:38:a6:79:d4:70:c8:e1:d8:25:2f:87:f0: + 74:3d:26:59:4c:71:ef:02:14:15:32:10:1d:c0:d1:ce:18:f4: + 8b:ea:c0:8b:d7:da:ba:52:3a:0d:f7 +-----BEGIN CERTIFICATE----- +MIIDGDCCAtWgAwIBAgIERgH/AjALBgcqhkjOOAQDBQAwXTELMAkGA1UEBhMCRUEx +DTALBgNVBAgTBE1vb24xETAPBgNVBAcTCEJhY2tzaWRlMQ4wDAYDVQQKEwVBLUIt +QzEPMA0GA1UECxMGT2ZmaWNlMQswCQYDVQQDEwJNZTAeFw0wNzAzMjIwMzU4NTha +Fw0wNzA2MjAwMzU4NThaMF0xCzAJBgNVBAYTAkVBMQ0wCwYDVQQIEwRNb29uMREw +DwYDVQQHEwhCYWNrc2lkZTEOMAwGA1UEChMFQS1CLUMxDzANBgNVBAsTBk9mZmlj +ZTELMAkGA1UEAxMCTWUwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS +30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuA +HTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVU +E1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKB +gQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGA +tEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoB +JDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEAxc7ovvDe +J5yIkiEoz6U4jcFf5ZDSC+rUEsqGuARXHUF0PlIth7h2e9KV12cwdjVH++mGvwU/ +m/JuOpaaWOEFRHgCMe5fZ2xE0pWPcmKkPicc85SKHguYTMCc9D0XbTbkoBIEAeQ4 +nr2GmXuEQ5tYaO/OPYXjk9EfGhikHlnKgC6jITAfMB0GA1UdDgQWBBTtv4rKVwXt +XJpyZWlswQL4MAKkazALBgcqhkjOOAQDBQADMAAwLQIVAIU4pnnUcMjh2CUvh/B0 +PSZZTHHvAhQVMhAdwNHOGPSL6sCL19q6UjoN9w== +-----END CERTIFICATE----- diff --git a/jdk/test/java/security/cert/CertificateFactory/openssl/pem b/jdk/test/java/security/cert/CertificateFactory/openssl/pem new file mode 100644 index 00000000000..8601bf37256 --- /dev/null +++ b/jdk/test/java/security/cert/CertificateFactory/openssl/pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIDGDCCAtWgAwIBAgIERgH/AjALBgcqhkjOOAQDBQAwXTELMAkGA1UEBhMCRUExDTALBgNVBAgT +BE1vb24xETAPBgNVBAcTCEJhY2tzaWRlMQ4wDAYDVQQKEwVBLUItQzEPMA0GA1UECxMGT2ZmaWNl +MQswCQYDVQQDEwJNZTAeFw0wNzAzMjIwMzU4NThaFw0wNzA2MjAwMzU4NThaMF0xCzAJBgNVBAYT +AkVBMQ0wCwYDVQQIEwRNb29uMREwDwYDVQQHEwhCYWNrc2lkZTEOMAwGA1UEChMFQS1CLUMxDzAN +BgNVBAsTBk9mZmljZTELMAkGA1UEAxMCTWUwggG4MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11 +EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZg +t2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/y +IgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o6 +6oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om +dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhQACgYEA +xc7ovvDeJ5yIkiEoz6U4jcFf5ZDSC+rUEsqGuARXHUF0PlIth7h2e9KV12cwdjVH++mGvwU/m/Ju +OpaaWOEFRHgCMe5fZ2xE0pWPcmKkPicc85SKHguYTMCc9D0XbTbkoBIEAeQ4nr2GmXuEQ5tYaO/O +PYXjk9EfGhikHlnKgC6jITAfMB0GA1UdDgQWBBTtv4rKVwXtXJpyZWlswQL4MAKkazALBgcqhkjO +OAQDBQADMAAwLQIVAIU4pnnUcMjh2CUvh/B0PSZZTHHvAhQVMhAdwNHOGPSL6sCL19q6UjoN9w== +-----END CERTIFICATE----- diff --git a/jdk/test/java/text/Bidi/BidiBug.java b/jdk/test/java/text/Bidi/BidiBug.java new file mode 100644 index 00000000000..36ffcd7e440 --- /dev/null +++ b/jdk/test/java/text/Bidi/BidiBug.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4827312 + * @summary verify that argument validity check is not fooled by overflow + */ +public class BidiBug { + public static void main(String[] args) { + try { + byte buff[] = new byte[3000]; + java.text.Bidi bidi = new java.text.Bidi(new char[20],10,buff,Integer.MAX_VALUE-3,4,1); + } + catch (IllegalArgumentException e) { + System.out.println(e); + return; // success + } + throw new RuntimeException("didn't throw error, though we didn't crash either"); + } +} diff --git a/jdk/test/java/text/Bidi/BidiEmbeddingTest.java b/jdk/test/java/text/Bidi/BidiEmbeddingTest.java new file mode 100644 index 00000000000..3e967be351d --- /dev/null +++ b/jdk/test/java/text/Bidi/BidiEmbeddingTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4396492 4396496 4778510 + * @summary verify that the embedding values processed by the bidi code use negative values to + * indicate overrides, rather than using bit 7. Also tests Bidi without loading awt classes to + * confirm that Bidi can be used without awt. Verify that embedding level 0 is properly mapped + * to the base embedding level. + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.font.TextAttribute; +import java.text.AttributedString; +import java.text.Bidi; + +public class BidiEmbeddingTest { + public static void main(String[] args) { + // to regress embedding test against old fix, call with an arg. A window will pop + // up causing awt lib to be loaded so the vm won't die with the unsatisfied link error. + if (args.length > 0) { + Frame f = new Frame(); + f.setSize(300, 300); + f.setBackground(Color.white); + f.show(); + } + + test1(); + test2(); + } + + static void test1() { + String target = "BACK WARDS"; + String str = "If this text is >" + target + "< the test passed."; + int start = str.indexOf(target); + int limit = start + target.length(); + + System.out.println("start: " + start + " limit: " + limit); + + AttributedString astr = new AttributedString(str); + astr.addAttribute(TextAttribute.BIDI_EMBEDDING, + new Integer(-1), + start, + limit); + + Bidi bidi = new Bidi(astr.getIterator()); + + for (int i = 0; i < bidi.getRunCount(); ++i) { + System.out.println("run " + i + + " from " + bidi.getRunStart(i) + + " to " + bidi.getRunLimit(i) + + " at level " + bidi.getRunLevel(i)); + } + + System.out.println(bidi); + + byte[] embs = new byte[str.length() + 3]; + for (int i = start + 1; i < limit + 1; ++i) { + embs[i] = -1; + } + + Bidi bidi2 = new Bidi(str.toCharArray(), 0, embs, 1, str.length(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); + for (int i = 0; i < bidi2.getRunCount(); ++i) { + System.out.println("run " + i + + " from " + bidi2.getRunStart(i) + + " to " + bidi2.getRunLimit(i) + + " at level " + bidi2.getRunLevel(i)); + } + + System.out.println(bidi2); + + if (bidi.getRunCount() != 3 || bidi2.getRunCount() != 3) { + throw new Error("Bidi run count incorrect"); + } + } + + // make sure BIDI_EMBEDDING values of 0 are mapped to base run direction, instead of flagging an error. + static void test2() { + String target = "BACK WARDS"; + String str = "If this text is >" + target + "< the test passed."; + int length = str.length(); + int start = str.indexOf(target); + int limit = start + target.length(); + + System.out.println("start: " + start + " limit: " + limit); + + AttributedString astr = new AttributedString(str); + astr.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL); + + astr.addAttribute(TextAttribute.BIDI_EMBEDDING, + new Integer(-3), + start, + limit); + + Bidi bidi = new Bidi(astr.getIterator()); + + for (int i = 0; i < bidi.getRunCount(); ++i) { + System.out.println("run " + i + + " from " + bidi.getRunStart(i) + + " to " + bidi.getRunLimit(i) + + " at level " + bidi.getRunLevel(i)); + } + + System.out.println(bidi); + + if (bidi.getRunCount() != 6) { // runs of spaces and angles at embedding bound,s and final period, each get level 1 + throw new Error("Bidi embedding processing failed"); + } + } +} diff --git a/jdk/test/java/text/Bidi/BidiSurrogateTest.java b/jdk/test/java/text/Bidi/BidiSurrogateTest.java new file mode 100644 index 00000000000..b24e1a1123f --- /dev/null +++ b/jdk/test/java/text/Bidi/BidiSurrogateTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4888843 + * @summary verify that surrogate pairs representing codepoints with R or AL directionality + * and correctly recognized and reordered. + */ + +import java.text.Bidi; + +public class BidiSurrogateTest { + private static final String RTLS = new String(Character.toChars(0x10800)); // surrogate code point with R directionality + private static final String LTRS = new String(Character.toChars(0x107ff)); // surrogate code point with L directionality + private static final String LRE = "\u202a"; + private static final String RLE = "\u202b"; + private static final String PDF = "\u202c"; + + + public static void main(String[] args) { + new BidiSurrogateTest().test(); + } + + void test() { + test0(); + test1(); + } + + void test0() { + // test unpaired surrogates - should have L directionality + testRequiresBidi("\ud800", false); // unpaired lead surrogate + testRequiresBidi("\udc00", false); // unpaired trail surrogate + testRequiresBidi("\udc00\ud800", false); // out of order surrogates + testRequiresBidi("a\udc00b\ud800c", false); // out of order surrogates split + testRequiresBidi(LTRS, false); // supplementary with L + testRequiresBidi(RTLS, true); // supplementary with R + testRequiresBidi("a" + RTLS + "b", true); // R supplementary in LTR text + testRequiresBidi(LTRS + RTLS, true); // R supplementary in LTR supplementary text + testRequiresBidi(LRE, false); // LRE lone embedding + testRequiresBidi(RLE, true); // RLE lone embedding + testRequiresBidi(PDF, false); // PDF lone pop embedding + } + + void testRequiresBidi(String string, boolean requiresBidi) { + char[] text = string.toCharArray(); + if (Bidi.requiresBidi(text, 0, text.length) != requiresBidi) { + throw new RuntimeException("testRequiresBidi failed with '" + string + "', " + requiresBidi); + } + } + + void test1() { + // test that strings with surrogate runs process surrogate directionality ok + testBidi("This is a string with " + LTRS + " in it.", false); + testBidi("This is a string with \ud800 in it.", false); + testBidi("This is a string with \u0640 in it.", 22, 1); + testBidi(RTLS, true); + testBidi("This is a string with " + RTLS + RTLS + RTLS + " in it.", 22, 6); + } + + void testBidi(String string, boolean directionIsRTL) { + Bidi bidi = new Bidi(string, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); + if (bidi.isMixed()) { + throw new RuntimeException("bidi is mixed"); + } + if (bidi.isRightToLeft() != directionIsRTL) { + throw new RuntimeException("bidi is not " + (directionIsRTL ? "rtl" : "ltr")); + } + } + + void testBidi(String string, int rtlstart, int rtllength) { + Bidi bidi = new Bidi(string, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT); + for (int i = 0; i < bidi.getRunCount(); ++i) { + if ((bidi.getRunLevel(i) & 1) != 0) { + if (bidi.getRunStart(i) != rtlstart || + bidi.getRunLimit(i) != rtlstart + rtllength) { + throw new RuntimeException("first rtl run didn't match " + rtlstart + ", " + rtllength); + } + break; + } + } + } +} diff --git a/jdk/test/java/text/Format/DateFormat/Bug4823811.java b/jdk/test/java/text/Format/DateFormat/Bug4823811.java index 65b4aa26349..6aa0787bfc2 100644 --- a/jdk/test/java/text/Format/DateFormat/Bug4823811.java +++ b/jdk/test/java/text/Format/DateFormat/Bug4823811.java @@ -25,6 +25,7 @@ * @test * @bug 4823811 * @summary Confirm that text which includes numbers with a trailing minus sign is parsed correctly. + * @run main/othervm -Duser.timezone=GMT+09:00 Bug4823811 */ import java.text.*; diff --git a/jdk/test/java/text/Format/DateFormat/Bug6683975.java b/jdk/test/java/text/Format/DateFormat/Bug6683975.java new file mode 100644 index 00000000000..0638c557158 --- /dev/null +++ b/jdk/test/java/text/Format/DateFormat/Bug6683975.java @@ -0,0 +1,114 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6683975 + * @summary Make sure that date is formatted correctlyin th locale. + */ +import java.text.*; +import java.util.*; + +public class Bug6683975 { + + private static boolean err = false; + + private static Locale th = new Locale("th", ""); + private static Locale th_TH = new Locale("th", "TH"); + private static String expected_th[] = { + "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23\u0e17\u0e35\u0e48 30 \u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19 \u0e04.\u0e28. 2008, 8 \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 0 \u0e19\u0e32\u0e17\u0e35 00 \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35", // 0: FULL + "30 \u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19 2008, 8 \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 0 \u0e19\u0e32\u0e17\u0e35", // 1: LONG + "30 \u0e01.\u0e22. 2008, 8:00:00", // 2: MEDIUM + "30/9/2008, 8:00 \u0e19.", // 3: SHORT + }; + private static String expected_th_TH[] = { + "\u0e27\u0e31\u0e19\u0e2d\u0e31\u0e07\u0e04\u0e32\u0e23\u0e17\u0e35\u0e48 30 \u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19 \u0e1e.\u0e28. 2551, 8 \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 0 \u0e19\u0e32\u0e17\u0e35 00 \u0e27\u0e34\u0e19\u0e32\u0e17\u0e35", // 0: FULL + "30 \u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19 2551, 8 \u0e19\u0e32\u0e2c\u0e34\u0e01\u0e32 0 \u0e19\u0e32\u0e17\u0e35", // 1: LONG + "30 \u0e01.\u0e22. 2551, 8:00:00", // 2: MEDIUM + "30/9/2551, 8:00 \u0e19." // 3: SHORT + }; + private static String stylePattern[] = { + "FULL", "LONG", "MEDIUM", "SHORT" + }; + + private static void test(int style) { + DateFormat df_th = DateFormat.getDateTimeInstance(style, style, th); + DateFormat df_th_TH = DateFormat.getDateTimeInstance(style, style, th_TH); + + String str_th = ((SimpleDateFormat)df_th).toPattern(); + String str_th_TH = ((SimpleDateFormat)df_th_TH).toPattern(); + if (!str_th.equals(str_th_TH)) { + err = true; + System.err.println("Error: Pattern for th locale should be the same as pattern for th_TH locale. (" + stylePattern[style] + ")"); + System.err.println("\tth: " + str_th); + System.err.println("\tth_TH: " + str_th_TH); + } + + Date date = new Date(2008-1900, Calendar.SEPTEMBER, 30, 8, 0, 0); + str_th = df_th.format(date); + if (!expected_th[style].equals(str_th)) { + err = true; + System.err.println("Error: Formatted date in th locale is incorrect in " + stylePattern[style] + " pattern."); + System.err.println("\tExpected: " + expected_th[style]); + System.err.println("\tGot: " + str_th); + } + + str_th_TH = df_th_TH.format(date); + if (!expected_th_TH[style].equals(str_th_TH)) { + err = true; + System.err.println("Error: Formatted date in th_TH locale is incorrect in " + stylePattern[style] + " pattern."); + System.err.println("\tExpected: " + expected_th_TH[style]); + System.err.println("\tGot: " + str_th_TH); + } + } + + public static void main(String[] args) { + TimeZone timezone = TimeZone.getDefault(); + Locale locale = Locale.getDefault(); + + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")); + Locale.setDefault(Locale.US); + + try { + test(DateFormat.FULL); + test(DateFormat.LONG); + test(DateFormat.MEDIUM); + test(DateFormat.SHORT); + } + catch (Exception e) { + err = true; + System.err.println("Unexpected exception was thrown: " + e); + } + finally { + TimeZone.setDefault(timezone); + Locale.setDefault(locale); + + if (err) { + throw new RuntimeException("Failed."); + } else { + System.out.println("Passed."); + } + } + } + +} diff --git a/jdk/test/java/util/Calendar/Bug6645263.java b/jdk/test/java/util/Calendar/Bug6645263.java new file mode 100644 index 00000000000..148926e6210 --- /dev/null +++ b/jdk/test/java/util/Calendar/Bug6645263.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6645263 + * @summary Test field normalization in non-lenient from the partially normalized state + */ + +import java.util.*; + +public class Bug6645263 { + public static void main(String[] args) { + Calendar cal = new GregorianCalendar(Locale.US); + cal.setLenient(false); + cal.set(Calendar.YEAR, 2007); + cal.set(Calendar.MONTH, Calendar.NOVEMBER); + cal.set(Calendar.WEEK_OF_MONTH, 4); + cal.set(Calendar.DAY_OF_WEEK, 1); + // Let cal calculate the time from the given fields + cal.getTime(); + + // Change DAY_OF_MONTH + cal.set(Calendar.DAY_OF_MONTH, 1); + // The following line shouldn't throw an IllegalArgumentException. + cal.getTime(); + } +} diff --git a/jdk/test/java/util/Currency/ValidateISO4217.java b/jdk/test/java/util/Currency/ValidateISO4217.java index ed1f2bc259d..c925554f77b 100644 --- a/jdk/test/java/util/Currency/ValidateISO4217.java +++ b/jdk/test/java/util/Currency/ValidateISO4217.java @@ -22,7 +22,7 @@ */ /* * @test - * @bug 4691089 4819436 4942982 5104960 6544471 + * @bug 4691089 4819436 4942982 5104960 6544471 6627549 * @summary Validate ISO 4217 data for Currency class. */ @@ -86,6 +86,8 @@ public class ValidateISO4217 { {"JE", "GBP", "826", "2"}, // Jersey {"GG", "GBP", "826", "2"}, // Guernsey {"IM", "GBP", "826", "2"}, // Isle of Man + {"BL", "EUR", "978", "2"}, // Saint Barthelemy + {"MF", "EUR", "978", "2"}, // Saint Martin }; /* Codes that are obsolete, do not have related country */ diff --git a/jdk/test/java/util/Formatter/Basic-X.java b/jdk/test/java/util/Formatter/Basic-X.java index b4a603f7bcd..4677062cc14 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java +++ b/jdk/test/java/util/Formatter/Basic-X.java @@ -1054,6 +1054,52 @@ public class Basic$Type$ extends Basic { test("%4.1f", " 1.0", val); test("%4.2f", "0.99", val); test("%4.3f", "0.990", val); + + // #6476425 + val = new BigDecimal("0.00001"); + test("%.0f", "0", val); + test("%.1f", "0.0", val); + test("%.2f", "0.00", val); + test("%.3f", "0.000", val); + test("%.4f", "0.0000", val); + test("%.5f", "0.00001", val); + + val = new BigDecimal("1.00001"); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "1.0000", val); + test("%.5f", "1.00001", val); + + val = new BigDecimal("1.23456"); + test("%.0f", "1", val); + test("%.1f", "1.2", val); + test("%.2f", "1.23", val); + test("%.3f", "1.235", val); + test("%.4f", "1.2346", val); + test("%.5f", "1.23456", val); + test("%.6f", "1.234560", val); + + val = new BigDecimal("9.99999"); + test("%.0f", "10", val); + test("%.1f", "10.0", val); + test("%.2f", "10.00", val); + test("%.3f", "10.000", val); + test("%.4f", "10.0000", val); + test("%.5f", "9.99999", val); + test("%.6f", "9.999990", val); + + + val = new BigDecimal("1.99999"); + test("%.0f", "2", val); + test("%.1f", "2.0", val); + test("%.2f", "2.00", val); + test("%.3f", "2.000", val); + test("%.4f", "2.0000", val); + test("%.5f", "1.99999", val); + test("%.6f", "1.999990", val); + #end[BigDecimal] #if[float] diff --git a/jdk/test/java/util/Formatter/Basic.java b/jdk/test/java/util/Formatter/Basic.java index 22d92495d49..3a957b2f4fa 100644 --- a/jdk/test/java/util/Formatter/Basic.java +++ b/jdk/test/java/util/Formatter/Basic.java @@ -25,7 +25,7 @@ * @summary Unit test for formatter * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937 * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 - * 6344623 6369500 6534606 6282094 6286592 + * 6344623 6369500 6534606 6282094 6286592 6476425 * * @run shell/timeout=240 Basic.sh */ diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index d35da256576..da96391384c 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -1055,6 +1055,52 @@ public class BasicBigDecimal extends Basic { test("%4.2f", "0.99", val); test("%4.3f", "0.990", val); + // #6476425 + val = new BigDecimal("0.00001"); + test("%.0f", "0", val); + test("%.1f", "0.0", val); + test("%.2f", "0.00", val); + test("%.3f", "0.000", val); + test("%.4f", "0.0000", val); + test("%.5f", "0.00001", val); + + val = new BigDecimal("1.00001"); + test("%.0f", "1", val); + test("%.1f", "1.0", val); + test("%.2f", "1.00", val); + test("%.3f", "1.000", val); + test("%.4f", "1.0000", val); + test("%.5f", "1.00001", val); + + val = new BigDecimal("1.23456"); + test("%.0f", "1", val); + test("%.1f", "1.2", val); + test("%.2f", "1.23", val); + test("%.3f", "1.235", val); + test("%.4f", "1.2346", val); + test("%.5f", "1.23456", val); + test("%.6f", "1.234560", val); + + val = new BigDecimal("9.99999"); + test("%.0f", "10", val); + test("%.1f", "10.0", val); + test("%.2f", "10.00", val); + test("%.3f", "10.000", val); + test("%.4f", "10.0000", val); + test("%.5f", "9.99999", val); + test("%.6f", "9.999990", val); + + + val = new BigDecimal("1.99999"); + test("%.0f", "2", val); + test("%.1f", "2.0", val); + test("%.2f", "2.00", val); + test("%.3f", "2.000", val); + test("%.4f", "2.0000", val); + test("%.5f", "1.99999", val); + test("%.6f", "1.999990", val); + + diff --git a/jdk/test/java/util/Formatter/BasicBigInteger.java b/jdk/test/java/util/Formatter/BasicBigInteger.java index e93f60d398d..4bba5a0fbe4 100644 --- a/jdk/test/java/util/Formatter/BasicBigInteger.java +++ b/jdk/test/java/util/Formatter/BasicBigInteger.java @@ -1503,6 +1503,52 @@ public class BasicBigInteger extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicBoolean.java b/jdk/test/java/util/Formatter/BasicBoolean.java index c7af21083aa..ea60e388652 100644 --- a/jdk/test/java/util/Formatter/BasicBoolean.java +++ b/jdk/test/java/util/Formatter/BasicBoolean.java @@ -1503,6 +1503,52 @@ public class BasicBoolean extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicBooleanObject.java b/jdk/test/java/util/Formatter/BasicBooleanObject.java index 81c1f3e1ada..b4fbabb76b8 100644 --- a/jdk/test/java/util/Formatter/BasicBooleanObject.java +++ b/jdk/test/java/util/Formatter/BasicBooleanObject.java @@ -1503,6 +1503,52 @@ public class BasicBooleanObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicByte.java b/jdk/test/java/util/Formatter/BasicByte.java index ff44286fdc3..deaf37957e5 100644 --- a/jdk/test/java/util/Formatter/BasicByte.java +++ b/jdk/test/java/util/Formatter/BasicByte.java @@ -1503,6 +1503,52 @@ public class BasicByte extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicByteObject.java b/jdk/test/java/util/Formatter/BasicByteObject.java index e2b158c3e85..06eb68ebd27 100644 --- a/jdk/test/java/util/Formatter/BasicByteObject.java +++ b/jdk/test/java/util/Formatter/BasicByteObject.java @@ -1503,6 +1503,52 @@ public class BasicByteObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicChar.java b/jdk/test/java/util/Formatter/BasicChar.java index bb1b5037e88..5ada7b166e7 100644 --- a/jdk/test/java/util/Formatter/BasicChar.java +++ b/jdk/test/java/util/Formatter/BasicChar.java @@ -1503,6 +1503,52 @@ public class BasicChar extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicCharObject.java b/jdk/test/java/util/Formatter/BasicCharObject.java index 2d15fa1c528..1e7d05d543f 100644 --- a/jdk/test/java/util/Formatter/BasicCharObject.java +++ b/jdk/test/java/util/Formatter/BasicCharObject.java @@ -1503,6 +1503,52 @@ public class BasicCharObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicDateTime.java b/jdk/test/java/util/Formatter/BasicDateTime.java index 97ae65026bb..fd42da06f70 100644 --- a/jdk/test/java/util/Formatter/BasicDateTime.java +++ b/jdk/test/java/util/Formatter/BasicDateTime.java @@ -1503,6 +1503,52 @@ public class BasicDateTime extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicDouble.java b/jdk/test/java/util/Formatter/BasicDouble.java index abbd093fc0a..d985b46b1a5 100644 --- a/jdk/test/java/util/Formatter/BasicDouble.java +++ b/jdk/test/java/util/Formatter/BasicDouble.java @@ -1053,6 +1053,52 @@ public class BasicDouble extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicDoubleObject.java b/jdk/test/java/util/Formatter/BasicDoubleObject.java index d49f9e60910..70dfd2929e5 100644 --- a/jdk/test/java/util/Formatter/BasicDoubleObject.java +++ b/jdk/test/java/util/Formatter/BasicDoubleObject.java @@ -1053,6 +1053,52 @@ public class BasicDoubleObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicFloat.java b/jdk/test/java/util/Formatter/BasicFloat.java index 61493b59b98..122b44f1e75 100644 --- a/jdk/test/java/util/Formatter/BasicFloat.java +++ b/jdk/test/java/util/Formatter/BasicFloat.java @@ -1056,6 +1056,52 @@ public class BasicFloat extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + //--------------------------------------------------------------------- // %f - float diff --git a/jdk/test/java/util/Formatter/BasicFloatObject.java b/jdk/test/java/util/Formatter/BasicFloatObject.java index fb7bffa150f..64c874cf2d5 100644 --- a/jdk/test/java/util/Formatter/BasicFloatObject.java +++ b/jdk/test/java/util/Formatter/BasicFloatObject.java @@ -1069,6 +1069,52 @@ public class BasicFloatObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicInt.java b/jdk/test/java/util/Formatter/BasicInt.java index 1945d5b612a..4010d2250e0 100644 --- a/jdk/test/java/util/Formatter/BasicInt.java +++ b/jdk/test/java/util/Formatter/BasicInt.java @@ -1503,6 +1503,52 @@ public class BasicInt extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicIntObject.java b/jdk/test/java/util/Formatter/BasicIntObject.java index 267ffd2eb95..fe41ea2964b 100644 --- a/jdk/test/java/util/Formatter/BasicIntObject.java +++ b/jdk/test/java/util/Formatter/BasicIntObject.java @@ -1503,6 +1503,52 @@ public class BasicIntObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicLong.java b/jdk/test/java/util/Formatter/BasicLong.java index 151dcb78975..fe232f1978e 100644 --- a/jdk/test/java/util/Formatter/BasicLong.java +++ b/jdk/test/java/util/Formatter/BasicLong.java @@ -1503,6 +1503,52 @@ public class BasicLong extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicLongObject.java b/jdk/test/java/util/Formatter/BasicLongObject.java index 3944418b3a6..c99e0ba3c2a 100644 --- a/jdk/test/java/util/Formatter/BasicLongObject.java +++ b/jdk/test/java/util/Formatter/BasicLongObject.java @@ -1503,6 +1503,52 @@ public class BasicLongObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicShort.java b/jdk/test/java/util/Formatter/BasicShort.java index 5554c15382d..39079e4ad1e 100644 --- a/jdk/test/java/util/Formatter/BasicShort.java +++ b/jdk/test/java/util/Formatter/BasicShort.java @@ -1503,6 +1503,52 @@ public class BasicShort extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/BasicShortObject.java b/jdk/test/java/util/Formatter/BasicShortObject.java index 629fb573674..e2dcc230174 100644 --- a/jdk/test/java/util/Formatter/BasicShortObject.java +++ b/jdk/test/java/util/Formatter/BasicShortObject.java @@ -1503,6 +1503,52 @@ public class BasicShortObject extends Basic { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/java/util/Formatter/genBasic.sh b/jdk/test/java/util/Formatter/genBasic.sh index 493e0360444..2c352ad39cf 100644 --- a/jdk/test/java/util/Formatter/genBasic.sh +++ b/jdk/test/java/util/Formatter/genBasic.sh @@ -23,14 +23,14 @@ # have any questions. # -SPP='sh ../../../../make/java/nio/spp.sh' +javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java gen() { # if [ $3 = "true" ] # then $SPP -K$1 -Dtype=$1 -DType=$2 -KprimBasic$2.java # else $SPP -K$1 -Dtype=$1 -DType=$2 -K$3 Basic$2.java # fi - $SPP -K$1 -Dtype=$1 -DType=$2 -K$3 -K$4 -K$5 -K$6 Basic$2.java + java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -K$3 -K$4 -K$5 -K$6 Basic$2.java } gen boolean Boolean prim "" "" "" @@ -54,3 +54,5 @@ gen Double DoubleObject "" fp "" "" gen BigDecimal BigDecimal "" fp "" "" gen Calendar DateTime "" "" "" datetime + +rm -rf build diff --git a/jdk/test/java/util/Locale/LocaleTest.java b/jdk/test/java/util/Locale/LocaleTest.java index 1bd3bd1dbe2..99fa44b7842 100644 --- a/jdk/test/java/util/Locale/LocaleTest.java +++ b/jdk/test/java/util/Locale/LocaleTest.java @@ -24,7 +24,7 @@ * @test * @bug 4052404 4052440 4084688 4092475 4101316 4105828 4107014 4107953 4110613 * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 - * 4147315 4147317 4147552 4335196 4778440 5010672 6475525 6544471 + * 4147315 4147317 4147552 4335196 4778440 5010672 6475525 6544471 6627549 6786276 * @summary test Locales */ /* @@ -439,8 +439,8 @@ public class LocaleTest extends LocaleTestFmwk { String[] spotCheck2 = { "US", "CA", "GB", "FR", "DE", "IT", "JP", "KR", "CN", "TW", "TH" }; - if (test.length != 245) - errln("Expected getISOCountries to return 245 countries; it returned " + test.length); + if (test.length != 246) + errln("Expected getISOCountries to return 246 countries; it returned " + test.length); else { for (int i = 0; i < spotCheck2.length; i++) { int j; diff --git a/jdk/test/java/util/Locale/data/deflocale.sol10 b/jdk/test/java/util/Locale/data/deflocale.sol10 index f79d413663d..712a1e159ec 100644 --- a/jdk/test/java/util/Locale/data/deflocale.sol10 +++ b/jdk/test/java/util/Locale/data/deflocale.sol10 @@ -1,7 +1,7 @@ Solaris 10 3/05 s10_74L2a SPARC - Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. - Use is subject to license terms. - Assembled 22 January 2005 + + (copyright from `uname -a` goes here) + SunOS deltas4 5.10 Generic_118833-03 sun4u sparc SUNW,Sun-Blade-2500 OS Locale: C diff --git a/jdk/test/java/util/regex/BMPTestCases.txt b/jdk/test/java/util/regex/BMPTestCases.txt new file mode 100644 index 00000000000..c50f49628e3 --- /dev/null +++ b/jdk/test/java/util/regex/BMPTestCases.txt @@ -0,0 +1,951 @@ +// +// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// +// +// This file contains test cases with BMP characters for regular expressions. +// A test case consists of three lines: +// The first line is a pattern used in the test +// The second line is the input to search for the pattern in +// The third line is a concatentation of the match, the number of groups, +// and the contents of the first four subexpressions. +// Empty lines and lines beginning with comment slashes are ignored. + +// Test unsetting of backed off groups +^(\u3042)?\u3042 +\u3042 +true \u3042 1 + +^(\u3042\u3042(\u3043\u3043)?)+$ +\u3042\u3042\u3043\u3043\u3042\u3042 +true \u3042\u3042\u3043\u3043\u3042\u3042 2 \u3042\u3042 \u3043\u3043 + +((\u3042|\u3043)?\u3043)+ +\u3043 +true \u3043 2 \u3043 + +(\u3042\u3042\u3042)?\u3042\u3042\u3042 +\u3042\u3042\u3042 +true \u3042\u3042\u3042 1 + +^(\u3042(\u3043)?)+$ +\u3042\u3043\u3042 +true \u3042\u3043\u3042 2 \u3042 \u3043 + +^(\u3042(\u3043(\u3044)?)?)?\u3042\u3043\u3044 +\u3042\u3043\u3044 +true \u3042\u3043\u3044 3 + +^(\u3042(\u3043(\u3044))).* +\u3042\u3043\u3044 +true \u3042\u3043\u3044 3 \u3042\u3043\u3044 \u3043\u3044 \u3044 + +// use of x modifier +\u3042\u3043\u3044(?x)\u3043la\u3049 +\u3042\u3043\u3044\u3043la\u3049 +true \u3042\u3043\u3044\u3043la\u3049 0 + +\u3042\u3043\u3044(?x) bla\u3049 +\u3042\u3043\u3044bla\u3049 +true \u3042\u3043\u3044bla\u3049 0 + +\u3042\u3043\u3044(?x) bla\u3049 ble\u3044\u3049 +\u3042\u3043\u3044bla\u3049ble\u3044\u3049 +true \u3042\u3043\u3044bla\u3049ble\u3044\u3049 0 + +\u3042\u3043\u3044(?x) bla\u3049 # ignore comment +\u3042\u3043\u3044bla\u3049 +true \u3042\u3043\u3044bla\u3049 0 + +// Simple alternation +\u3042|\u3043 +\u3042 +true \u3042 0 + +\u3042|\u3043 +\u305B +false 0 + +\u3042|\u3043 +\u3043 +true \u3043 0 + +\u3042|\u3043|\u3044\u3045 +\u3044\u3045 +true \u3044\u3045 0 + +\u3042|\u3042\u3045 +\u3042\u3045 +true \u3042 0 + +\u305B(\u3042|\u3042\u3044)\u3043 +\u305B\u3042\u3044\u3043 +true \u305B\u3042\u3044\u3043 1 \u3042\u3044 + +// Simple char class +[\u3042\u3043\u3044]+ +\u3042\u3043\u3042\u3043\u3042\u3043 +true \u3042\u3043\u3042\u3043\u3042\u3043 0 + +[\u3042\u3043\u3044]+ +\u3045\u3046\u3047\u3048 +false 0 + +[\u3042\u3043\u3044]+[\u3045\u3046\u3047]+[\u3048\u3049\u304A]+ +\u305B\u305B\u305B\u3042\u3042\u3045\u3045\u3048\u3048\u305B\u305B\u305B +true \u3042\u3042\u3045\u3045\u3048\u3048 0 + +// Range char class +[\u3042-\u3048]+ +\u305B\u305B\u305B\u3048\u3048\u3048 +true \u3048\u3048\u3048 0 + +[\u3042-\u3048]+ +mmm +false 0 + +[\u3042-]+ +\u305B\u3042-9\u305B +true \u3042- 0 + +[\u3042-\\u4444]+ +\u305B\u3042-9\u305B +true \u305B\u3042 0 + +// Negated char class +[^\u3042\u3043\u3044]+ +\u3042\u3043\u3042\u3043\u3042\u3043 +false 0 + +[^\u3042\u3043\u3044]+ +\u3042\u3042\u3042\u3043\u3043\u3043\u3044\u3044\u3044\u3045\u3046\u3047\u3048 +true \u3045\u3046\u3047\u3048 0 + +// Making sure a ^ not in first position matches literal ^ +[\u3042\u3043\u3044^\u3043] +\u3043 +true \u3043 0 + +[\u3042\u3043\u3044^\u3043] +^ +true ^ 0 + +// Class union and intersection +[\u3042\u3043\u3044[\u3045\u3046\u3047]] +\u3043 +true \u3043 0 + +[\u3042\u3043\u3044[\u3045\u3046\u3047]] +\u3046 +true \u3046 0 + +[\u3042-\u3045[0-9][\u304e-\u3051]] +\u3042 +true \u3042 0 + +[\u3042-\u3045[0-9][\u304e-\u3051]] +\u3050 +true \u3050 0 + +[\u3042-\u3045[0-9][\u304e-\u3051]] +4 +true 4 0 + +[\u3042-\u3045[0-9][\u304e-\u3051]] +\u3046 +false 0 + +[\u3042-\u3045[0-9][\u304e-\u3051]] +\u3056 +false 0 + +[[\u3042-\u3045][0-9][\u304e-\u3051]] +\u3043 +true \u3043 0 + +[[\u3042-\u3045][0-9][\u304e-\u3051]] +\u305B +false 0 + +[\u3042-\u3044[\u3045-\u3047[\u3048-\u304A]]] +\u3042 +true \u3042 0 + +[\u3042-\u3044[\u3045-\u3047[\u3048-\u304A]]] +\u3046 +true \u3046 0 + +[\u3042-\u3044[\u3045-\u3047[\u3048-\u304A]]] +\u3049 +true \u3049 0 + +[\u3042-\u3044[\u3045-\u3047[\u3048-\u304A]]] +m +false 0 + +[\u3042-\u3044[\u3045-\u3047[\u3048-\u304A]]m] +m +true m 0 + +[\u3042\u3043\u3044[\u3045\u3046\u3047]\u3048\u3049\u304A] +\u3042 +true \u3042 0 + +[\u3042\u3043\u3044[\u3045\u3046\u3047]\u3048\u3049\u304A] +\u3045 +true \u3045 0 + +[\u3042\u3043\u3044[\u3045\u3046\u3047]\u3048\u3049\u304A] +\u3049 +true \u3049 0 + +[\u3042\u3043\u3044[\u3045\u3046\u3047]\u3048\u3049\u304A] +w +false 0 + +[\u3042-\u3044&&[\u3045-\u3047]] +\u3042 +false 0 + +[\u3042-\u3044&&[\u3045-\u3047]] +\u3046 +false 0 + +[\u3042-\u3044&&[\u3045-\u3047]] +\u305B +false 0 + +[[\u3042-\u3044]&&[\u3045-\u3047]] +\u3042 +false 0 + +[[\u3042-\u3044]&&[\u3045-\u3047]] +\u3046 +false 0 + +[[\u3042-\u3044]&&[\u3045-\u3047]] +\u305B +false 0 + +[\u3042-\u3044&&\u3045-\u3047] +\u3042 +false 0 + +[\u3042-\u304e&&\u304e-\u305B] +\u304e +true \u304e 0 + +[\u3042-\u304e&&\u304e-\u305B&&\u3042-\u3044] +\u304e +false 0 + +[\u3042-\u304e&&\u304e-\u305B&&\u3042-\u305B] +\u304e +true \u304e 0 + +[[\u3042-\u304e]&&[\u304e-\u305B]] +\u3042 +false 0 + +[[\u3042-\u304e]&&[\u304e-\u305B]] +\u304e +true \u304e 0 + +[[\u3042-\u304e]&&[\u304e-\u305B]] +\u305B +false 0 + +[[\u3042-\u304e]&&[^\u3042-\u3044]] +\u3042 +false 0 + +[[\u3042-\u304e]&&[^\u3042-\u3044]] +\u3045 +true \u3045 0 + +[\u3042-\u304e&&[^\u3042-\u3044]] +\u3042 +false 0 + +[\u3042-\u304e&&[^\u3042-\u3044]] +\u3045 +true \u3045 0 + +[\u3042-\u3044\u3045-\u3047&&[\u3045-\u3047]] +\u3042 +false 0 + +[\u3042-\u3044\u3045-\u3047&&[\u3045-\u3047]] +\u3046 +true \u3046 0 + +[[\u3042-\u3044]&&\u3045-\u3047\u3042-\u3044] +\u3042 +true \u3042 0 + +[[\u3042-\u3044]&&[\u3045-\u3047][\u3042-\u3044]] +\u3042 +true \u3042 0 + +[[\u3042-\u3044][\u3045-\u3047]&&\u3042\u3043\u3044] +\u3042 +true \u3042 0 + +[[\u3042-\u3044][\u3045-\u3047]&&\u3042\u3043\u3044[\u3045\u3046\u3047]] +\u3046 +true \u3046 0 + +[[\u3042-\u3044]&&[\u3043-\u3045]&&[\u3044-\u3046]] +\u3042 +false 0 + +[[\u3042-\u3044]&&[\u3043-\u3045]&&[\u3044-\u3046]] +\u3044 +true \u3044 0 + +[[\u3042-\u3044]&&[\u3043-\u3045][\u3044-\u3046]&&[\u3056-\u305B]] +\u3044 +false 0 + +[\u3042\u3043\u3044[^\u3043\u3044\u3045]] +\u3042 +true \u3042 0 + +[\u3042\u3043\u3044[^\u3043\u3044\u3045]] +\u3045 +false 0 + +[\u3042-\u3044&&\u3042-\u3045&&\u3042-\u3046\u3048\u3049\u304A] +\u3043 +true \u3043 0 + +[\u3042-\u3044&&\u3042-\u3045&&\u3042-\u3046\u3048\u3049\u304A] +\u3048 +false 0 + +[[\u3042[\u3043]]&&[\u3043[\u3042]]] +\u3042 +true \u3042 0 + +[[\u3042]&&[\u3043][\u3044][\u3042]&&[^\u3045]] +\u3042 +true \u3042 0 + +[[\u3042]&&[b][c][\u3042]&&[^d]] +\u3042 +true \u3042 0 + +[[\u3042]&&[\u3043][\u3044][\u3042]&&[^\u3045]] +\u3045 +false 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]] +\u3042 +false 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]] +\u3044 +true \u3044 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]&&[\u3044]] +\u3044 +true \u3044 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]&&[\u3044]&&\u3044] +\u3044 +true \u3044 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]&&[\u3044]&&\u3044&&\u3044] +\u3044 +true \u3044 0 + +[[[\u3042-\u3045]&&[\u3044-\u3047]]&&[\u3044]&&\u3044&&[\u3044\u3045\u3046]] +\u3044 +true \u3044 0 + +[\u305B[\u3042\u3043\u3044&&\u3043\u3044\u3045]] +\u3044 +true \u3044 0 + +[\u305B[\u3042\u3043\u3044&&\u3043\u3044\u3045]&&[\u3056-\u305B]] +\u305B +true \u305B 0 + +[\u3059[\u3042\u3043\u3044&&\u3043\u3044\u3045[\u305B]]&&[\u3056-\u305B]] +\u305B +false 0 + +[\u3059[[w\u305B]\u3042\u3043\u3044&&\u3043\u3044\u3045[\u305B]]&&[\u3056-\u305B]] +\u305B +true \u305B 0 + +[[\u3042\u3043\u3044]&&[\u3045\u3046\u3047]\u3042\u3043\u3044] +\u3042 +true \u3042 0 + +[[\u3042\u3043\u3044]&&[\u3045\u3046\u3047]\u3059\u305A\u305B[\u3042\u3043\u3044]] +\u3042 +true \u3042 0 + +\pL +\u3042 +true \u3042 0 + +\pL +7 +false 0 + +\p{L} +\u3042 +true \u3042 0 + +\p{IsL} +\u3042 +true \u3042 0 + +\p{InHiragana} +\u3042 +true \u3042 0 + +\p{InHiragana} +\u0370 +false 0 + +\pL\u3043\u3044 +\u3042\u3043\u3044 +true \u3042\u3043\u3044 0 + +\u3042[r\p{InGreek}]\u3044 +\u3042\u0370\u3044 +true \u3042\u0370\u3044 0 + +\u3042\p{InGreek} +\u3042\u0370 +true \u3042\u0370 0 + +\u3042\P{InGreek} +\u3042\u0370 +false 0 + +\u3042\P{InGreek} +\u3042\u3043 +true \u3042\u3043 0 + +\u3042{^InGreek} +- +error + +\u3042\p{^InGreek} +- +error + +\u3042\P{^InGreek} +- +error + +\u3042\p{InGreek} +\u3042\u0370 +true \u3042\u0370 0 + +\u3042[\p{InGreek}]\u3044 +\u3042\u0370\u3044 +true \u3042\u0370\u3044 0 + +\u3042[\P{InGreek}]\u3044 +\u3042\u0370\u3044 +false 0 + +\u3042[\P{InGreek}]\u3044 +\u3042\u3043\u3044 +true \u3042\u3043\u3044 0 + +\u3042[{^InGreek}]\u3044 +\u3042n\u3044 +true \u3042n\u3044 0 + +\u3042[{^InGreek}]\u3044 +\u3042\u305B\u3044 +false 0 + +\u3042[\p{^InGreek}]\u3044 +- +error + +\u3042[\P{^InGreek}]\u3044 +- +error + +\u3042[\p{InGreek}] +\u3042\u0370 +true \u3042\u0370 0 + +\u3042[r\p{InGreek}]\u3044 +\u3042r\u3044 +true \u3042r\u3044 0 + +\u3042[\p{InGreek}r]\u3044 +\u3042r\u3044 +true \u3042r\u3044 0 + +\u3042[r\p{InGreek}]\u3044 +\u3042r\u3044 +true \u3042r\u3044 0 + +\u3042[^\p{InGreek}]\u3044 +\u3042\u0370\u3044 +false 0 + +\u3042[^\P{InGreek}]\u3044 +\u3042\u0370\u3044 +true \u3042\u0370\u3044 0 + +\u3042[\p{InGreek}&&[^\u0370]]\u3044 +\u3042\u0370\u3044 +false 0 + +// Test the dot metacharacter +\u3042.\u3044.+ +\u3042#\u3044%& +true \u3042#\u3044%& 0 + +\u3042\u3043. +\u3042\u3043\n +false 0 + +(?s)\u3042\u3043. +\u3042\u3043\n +true \u3042\u3043\n 0 + +\u3042[\p{L}&&[\P{InGreek}]]\u3044 +\u3042\u6000\u3044 +true \u3042\u6000\u3044 0 + +\u3042[\p{L}&&[\P{InGreek}]]\u3044 +\u3042r\u3044 +true \u3042r\u3044 0 + +\u3042[\p{L}&&[\P{InGreek}]]\u3044 +\u3042\u0370\u3044 +false 0 + +\u3042\p{InGreek}\u3044 +\u3042\u0370\u3044 +true \u3042\u0370\u3044 0 + +\u3042\p{Sc} +\u3042$ +true \u3042$ 0 + +\W\w\W +rrrr#\u3048\u3048\u3048 +false 0 + +\u3042\u3043\u3044[\s\u3045\u3046\u3047]* +\u3042\u3043\u3044 \u3045\u3046\u3047 +true \u3042\u3043\u3044 \u3045\u3046\u3047 0 + +\u3042\u3043\u3044[\s\u305A-\u305B]* +\u3042\u3043\u3044 \u305A \u305B +true \u3042\u3043\u3044 \u305A \u305B 0 + +\u3042\u3043\u3044[\u3042-\u3045\s\u304e-\u3051]* +\u3042\u3043\u3044\u3042\u3042 \u304e\u304f \u3051 +true \u3042\u3043\u3044\u3042\u3042 \u304e\u304f \u3051 0 + +// Test the whitespace escape sequence +\u3042\u3043\s\u3044 +\u3042\u3043 \u3044 +true \u3042\u3043 \u3044 0 + +\s\s\s +\u3043l\u3042\u3049 \u3046rr +false 0 + +\S\S\s +\u3043l\u3042\u3049 \u3046rr +true \u3042\u3049 0 + +// Test the digit escape sequence +\u3042\u3043\d\u3044 +\u3042\u30439\u3044 +true \u3042\u30439\u3044 0 + +\d\d\d +\u3043l\u3042\u304945 +false 0 + +// Test the caret metacharacter +^\u3042\u3043\u3044 +\u3042\u3043\u3044\u3045\u3046\u3047 +true \u3042\u3043\u3044 0 + +^\u3042\u3043\u3044 +\u3043\u3044\u3045\u3042\u3043\u3044 +false 0 + +// Greedy ? metacharacter +\u3042?\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +\u3042?\u3043 +\u3043 +true \u3043 0 + +\u3042?\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.?\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +// Reluctant ? metacharacter +\u3042??\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +\u3042??\u3043 +\u3043 +true \u3043 0 + +\u3042??\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.??\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +// Possessive ? metacharacter +\u3042?+\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +\u3042?+\u3043 +\u3043 +true \u3043 0 + +\u3042?+\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.?+\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3043 0 + +// Greedy + metacharacter +\u3042+\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3042\u3042\u3042\u3043 0 + +\u3042+\u3043 +\u3043 +false 0 + +\u3042+\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.+\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3042\u3042\u3042\u3043 0 + +// Reluctant + metacharacter +\u3042+?\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3042\u3042\u3042\u3043 0 + +\u3042+?\u3043 +\u3043 +false 0 + +\u3042+?\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.+?\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3042\u3042\u3042\u3043 0 + +// Possessive + metacharacter +\u3042++\u3043 +\u3042\u3042\u3042\u3042\u3043 +true \u3042\u3042\u3042\u3042\u3043 0 + +\u3042++\u3043 +\u3043 +false 0 + +\u3042++\u3043 +\u3042\u3042\u3042\u3044\u3044\u3044 +false 0 + +.++\u3043 +\u3042\u3042\u3042\u3042\u3043 +false 0 + +// Greedy Repetition +\u3042{2,3} +\u3042 +false 0 + +\u3042{2,3} +\u3042\u3042 +true \u3042\u3042 0 + +\u3042{2,3} +\u3042\u3042\u3042 +true \u3042\u3042\u3042 0 + +\u3042{2,3} +\u3042\u3042\u3042\u3042 +true \u3042\u3042\u3042 0 + +\u3042{3,} +\u305B\u305B\u305B\u3042\u3042\u3042\u3042\u305B\u305B\u305B +true \u3042\u3042\u3042\u3042 0 + +\u3042{3,} +\u305B\u305B\u305B\u3042\u3042\u305B\u305B\u305B +false 0 + +// Reluctant Repetition +\u3042{2,3}? +\u3042 +false 0 + +\u3042{2,3}? +\u3042\u3042 +true \u3042\u3042 0 + +\u3042{2,3}? +\u3042\u3042\u3042 +true \u3042\u3042 0 + +\u3042{2,3}? +\u3042\u3042\u3042\u3042 +true \u3042\u3042 0 + +// Zero width Positive lookahead +\u3042\u3043\u3044(?=\u3045) +\u305B\u305B\u305B\u3042\u3043\u3044\u3045 +true \u3042\u3043\u3044 0 + +\u3042\u3043\u3044(?=\u3045) +\u305B\u305B\u305B\u3042\u3043\u3044\u3046\u3045 +false 0 + +// Zero width Negative lookahead +\u3042\u3043\u3044(?!\u3045) +\u305B\u305B\u3042\u3043\u3044\u3045 +false 0 + +\u3042\u3043\u3044(?!\u3045) +\u305B\u305B\u3042\u3043\u3044\u3046\u3045 +true \u3042\u3043\u3044 0 + +// Zero width Positive lookbehind +\u3042(?<=\u3042) +###\u3042\u3043\u3044 +true \u3042 0 + +\u3042(?<=\u3042) +###\u3043\u3044### +false 0 + +// Zero width Negative lookbehind +(?3 +// So that the BM optimization is part of test +\Q***\E\u3042\u3043\u3044 +***\u3042\u3043\u3044 +true ***\u3042\u3043\u3044 0 + +\u3043l\Q***\E\u3042\u3043\u3044 +\u3043l***\u3042\u3043\u3044 +true \u3043l***\u3042\u3043\u3044 0 + +\Q***\u3042\u3043\u3044 +***\u3042\u3043\u3044 +true ***\u3042\u3043\u3044 0 + +\u3043l\u3042\u3049\Q***\E\u3042\u3043\u3044 +\u3043l\u3042\u3049***\u3042\u3043\u3044 +true \u3043l\u3042\u3049***\u3042\u3043\u3044 0 + +\Q***\u3042\u3043\u3044 +***\u3042\u3043\u3044 +true ***\u3042\u3043\u3044 0 + +\Q*\u3042\u3043 +*\u3042\u3043 +true *\u3042\u3043 0 + +\u3043l\u3042\u3049\Q***\u3042\u3043\u3044 +\u3043l\u3042\u3049***\u3042\u3043\u3044 +true \u3043l\u3042\u3049***\u3042\u3043\u3044 0 + +\u3043l\u3042\Q***\u3042\u3043\u3044 +\u3043l\u3042***\u3042\u3043\u3044 +true \u3043l\u3042***\u3042\u3043\u3044 0 + +[\043]+ +\u3043l\u3042\u3049\u3043l\u3042\u3049#\u3043le\u3044\u3049 +true # 0 + +[\042-\044]+ +\u3043l\u3042\u3049\u3043l\u3042\u3049#\u3043le\u3044\u3049 +true # 0 + +[\u1234-\u1236] +\u3043l\u3042\u3049\u3043l\u3042\u3049\u1235\u3043le\u3044\u3049 +true \u1235 0 + +[^\043]* +\u3043l\u3042\u3049\u3043l\u3042\u3049#\u3043le\u3044\u3049 +true \u3043l\u3042\u3049\u3043l\u3042\u3049 0 diff --git a/jdk/test/java/util/regex/RegExTest.java b/jdk/test/java/util/regex/RegExTest.java new file mode 100644 index 00000000000..29d8b55c437 --- /dev/null +++ b/jdk/test/java/util/regex/RegExTest.java @@ -0,0 +1,3511 @@ +/* + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @summary tests RegExp framework + * @author Mike McCloskey + * @bug 4481568 4482696 4495089 4504687 4527731 4599621 4631553 4619345 + * 4630911 4672616 4711773 4727935 4750573 4792284 4803197 4757029 4808962 + * 4872664 4803179 4892980 4900747 4945394 4938995 4979006 4994840 4997476 + * 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940 + * 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133 + * 6350801 6676425 + */ + +import java.util.regex.*; +import java.util.Random; +import java.io.*; +import java.util.*; +import java.nio.CharBuffer; + +/** + * This is a test class created to check the operation of + * the Pattern and Matcher classes. + */ +public class RegExTest { + + private static Random generator = new Random(); + private static boolean failure = false; + private static int failCount = 0; + + /** + * Main to interpret arguments and run several tests. + * + */ + public static void main(String[] args) throws Exception { + // Most of the tests are in a file + processFile("TestCases.txt"); + //processFile("PerlCases.txt"); + processFile("BMPTestCases.txt"); + processFile("SupplementaryTestCases.txt"); + + // These test many randomly generated char patterns + bm(); + slice(); + + // These are hard to put into the file + escapes(); + blankInput(); + + // Substitition tests on randomly generated sequences + globalSubstitute(); + stringbufferSubstitute(); + substitutionBasher(); + + // Canonical Equivalence + ceTest(); + + // Anchors + anchorTest(); + + // boolean match calls + matchesTest(); + lookingAtTest(); + + // Pattern API + patternMatchesTest(); + + // Misc + lookbehindTest(); + nullArgumentTest(); + backRefTest(); + groupCaptureTest(); + caretTest(); + charClassTest(); + emptyPatternTest(); + findIntTest(); + group0Test(); + longPatternTest(); + octalTest(); + ampersandTest(); + negationTest(); + splitTest(); + appendTest(); + caseFoldingTest(); + commentsTest(); + unixLinesTest(); + replaceFirstTest(); + gTest(); + zTest(); + serializeTest(); + reluctantRepetitionTest(); + multilineDollarTest(); + dollarAtEndTest(); + caretBetweenTerminatorsTest(); + // This RFE rejected in Tiger numOccurrencesTest(); + javaCharClassTest(); + nonCaptureRepetitionTest(); + notCapturedGroupCurlyMatchTest(); + escapedSegmentTest(); + literalPatternTest(); + literalReplacementTest(); + regionTest(); + toStringTest(); + negatedCharClassTest(); + findFromTest(); + boundsTest(); + unicodeWordBoundsTest(); + caretAtEndTest(); + wordSearchTest(); + hitEndTest(); + toMatchResultTest(); + surrogatesInClassTest(); + namedGroupCaptureTest(); + + if (failure) + throw new RuntimeException("Failure in the RE handling."); + else + System.err.println("OKAY: All tests passed."); + } + + // Utility functions + + private static String getRandomAlphaString(int length) { + StringBuffer buf = new StringBuffer(length); + for (int i=0; i 0) + failure = true; + failCount = 0; + } + + /** + * Converts ASCII alphabet characters [A-Za-z] in the given 's' to + * supplementary characters. This method does NOT fully take care + * of the regex syntax. + */ + private static String toSupplementaries(String s) { + int length = s.length(); + StringBuffer sb = new StringBuffer(length * 2); + + for (int i = 0; i < length; ) { + char c = s.charAt(i++); + if (c == '\\') { + sb.append(c); + if (i < length) { + c = s.charAt(i++); + sb.append(c); + if (c == 'u') { + // assume no syntax error + sb.append(s.charAt(i++)); + sb.append(s.charAt(i++)); + sb.append(s.charAt(i++)); + sb.append(s.charAt(i++)); + } + } + } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + sb.append('\ud800').append((char)('\udc00'+c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + // Regular expression tests + + // This is for bug 6178785 + // Test if an expected NPE gets thrown when passing in a null argument + private static boolean check(Runnable test) { + try { + test.run(); + failCount++; + return false; + } catch (NullPointerException npe) { + return true; + } + } + + private static void nullArgumentTest() { + check(new Runnable() { public void run() { Pattern.compile(null); }}); + check(new Runnable() { public void run() { Pattern.matches(null, null); }}); + check(new Runnable() { public void run() { Pattern.matches("xyz", null);}}); + check(new Runnable() { public void run() { Pattern.quote(null);}}); + check(new Runnable() { public void run() { Pattern.compile("xyz").split(null);}}); + check(new Runnable() { public void run() { Pattern.compile("xyz").matcher(null);}}); + + final Matcher m = Pattern.compile("xyz").matcher("xyz"); + m.matches(); + check(new Runnable() { public void run() { m.appendTail(null);}}); + check(new Runnable() { public void run() { m.replaceAll(null);}}); + check(new Runnable() { public void run() { m.replaceFirst(null);}}); + check(new Runnable() { public void run() { m.appendReplacement(null, null);}}); + check(new Runnable() { public void run() { m.reset(null);}}); + check(new Runnable() { public void run() { Matcher.quoteReplacement(null);}}); + //check(new Runnable() { public void run() { m.usePattern(null);}}); + + report("Null Argument"); + } + + // This is for bug6635133 + // Test if surrogate pair in Unicode escapes can be handled correctly. + private static void surrogatesInClassTest() throws Exception { + Pattern pattern = Pattern.compile("[\\ud834\\udd21-\\ud834\\udd24]"); + Matcher matcher = pattern.matcher("\ud834\udd22"); + if (!matcher.find()) + failCount++; + } + + // This is for bug 4988891 + // Test toMatchResult to see that it is a copy of the Matcher + // that is not affected by subsequent operations on the original + private static void toMatchResultTest() throws Exception { + Pattern pattern = Pattern.compile("squid"); + Matcher matcher = pattern.matcher( + "agiantsquidofdestinyasmallsquidoffate"); + matcher.find(); + int matcherStart1 = matcher.start(); + MatchResult mr = matcher.toMatchResult(); + if (mr == matcher) + failCount++; + int resultStart1 = mr.start(); + if (matcherStart1 != resultStart1) + failCount++; + matcher.find(); + int matcherStart2 = matcher.start(); + int resultStart2 = mr.start(); + if (matcherStart2 == resultStart2) + failCount++; + if (resultStart1 != resultStart2) + failCount++; + MatchResult mr2 = matcher.toMatchResult(); + if (mr == mr2) + failCount++; + if (mr2.start() != matcherStart2) + failCount++; + report("toMatchResult is a copy"); + } + + // This is for bug 5013885 + // Must test a slice to see if it reports hitEnd correctly + private static void hitEndTest() throws Exception { + // Basic test of Slice node + Pattern p = Pattern.compile("^squidattack"); + Matcher m = p.matcher("squack"); + m.find(); + if (m.hitEnd()) + failCount++; + m.reset("squid"); + m.find(); + if (!m.hitEnd()) + failCount++; + + // Test Slice, SliceA and SliceU nodes + for (int i=0; i<3; i++) { + int flags = 0; + if (i==1) flags = Pattern.CASE_INSENSITIVE; + if (i==2) flags = Pattern.UNICODE_CASE; + p = Pattern.compile("^abc", flags); + m = p.matcher("ad"); + m.find(); + if (m.hitEnd()) + failCount++; + m.reset("ab"); + m.find(); + if (!m.hitEnd()) + failCount++; + } + + // Test Boyer-Moore node + p = Pattern.compile("catattack"); + m = p.matcher("attack"); + m.find(); + if (!m.hitEnd()) + failCount++; + + p = Pattern.compile("catattack"); + m = p.matcher("attackattackattackcatatta"); + m.find(); + if (!m.hitEnd()) + failCount++; + + report("hitEnd from a Slice"); + } + + // This is for bug 4997476 + // It is weird code submitted by customer demonstrating a regression + private static void wordSearchTest() throws Exception { + String testString = new String("word1 word2 word3"); + Pattern p = Pattern.compile("\\b"); + Matcher m = p.matcher(testString); + int position = 0; + int start = 0; + while (m.find(position)) { + start = m.start(); + if (start == testString.length()) + break; + if (m.find(start+1)) { + position = m.start(); + } else { + position = testString.length(); + } + if (testString.substring(start, position).equals(" ")) + continue; + if (!testString.substring(start, position-1).startsWith("word")) + failCount++; + } + report("Customer word search"); + } + + // This is for bug 4994840 + private static void caretAtEndTest() throws Exception { + // Problem only occurs with multiline patterns + // containing a beginning-of-line caret "^" followed + // by an expression that also matches the empty string. + Pattern pattern = Pattern.compile("^x?", Pattern.MULTILINE); + Matcher matcher = pattern.matcher("\r"); + matcher.find(); + matcher.find(); + report("Caret at end"); + } + + // This test is for 4979006 + // Check to see if word boundary construct properly handles unicode + // non spacing marks + private static void unicodeWordBoundsTest() throws Exception { + String spaces = " "; + String wordChar = "a"; + String nsm = "\u030a"; + + assert (Character.getType('\u030a') == Character.NON_SPACING_MARK); + + Pattern pattern = Pattern.compile("\\b"); + Matcher matcher = pattern.matcher(""); + // S=other B=word character N=non spacing mark .=word boundary + // SS.BB.SS + String input = spaces + wordChar + wordChar + spaces; + twoFindIndexes(input, matcher, 2, 4); + // SS.BBN.SS + input = spaces + wordChar +wordChar + nsm + spaces; + twoFindIndexes(input, matcher, 2, 5); + // SS.BN.SS + input = spaces + wordChar + nsm + spaces; + twoFindIndexes(input, matcher, 2, 4); + // SS.BNN.SS + input = spaces + wordChar + nsm + nsm + spaces; + twoFindIndexes(input, matcher, 2, 5); + // SSN.BB.SS + input = spaces + nsm + wordChar + wordChar + spaces; + twoFindIndexes(input, matcher, 3, 5); + // SS.BNB.SS + input = spaces + wordChar + nsm + wordChar + spaces; + twoFindIndexes(input, matcher, 2, 5); + // SSNNSS + input = spaces + nsm + nsm + spaces; + matcher.reset(input); + if (matcher.find()) + failCount++; + // SSN.BBN.SS + input = spaces + nsm + wordChar + wordChar + nsm + spaces; + twoFindIndexes(input, matcher, 3, 6); + + report("Unicode word boundary"); + } + + private static void twoFindIndexes(String input, Matcher matcher, int a, + int b) throws Exception + { + matcher.reset(input); + matcher.find(); + if (matcher.start() != a) + failCount++; + matcher.find(); + if (matcher.start() != b) + failCount++; + } + + // This test is for 6284152 + static void check(String regex, String input, String[] expected) { + List result = new ArrayList(); + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(input); + while (m.find()) { + result.add(m.group()); + } + if (!Arrays.asList(expected).equals(result)) + failCount++; + } + + private static void lookbehindTest() throws Exception { + //Positive + check("(?<=%.{0,5})foo\\d", + "%foo1\n%bar foo2\n%bar foo3\n%blahblah foo4\nfoo5", + new String[]{"foo1", "foo2", "foo3"}); + + //boundary at end of the lookbehind sub-regex should work consistently + //with the boundary just after the lookbehind sub-regex + check("(?<=.*\\b)foo", "abcd foo", new String[]{"foo"}); + check("(?<=.*)\\bfoo", "abcd foo", new String[]{"foo"}); + check("(?]"); + Matcher matcher = pattern.matcher("\u203A"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("[^fr]"); + matcher = pattern.matcher("a"); + if (!matcher.find()) + failCount++; + matcher.reset("\u203A"); + if (!matcher.find()) + failCount++; + String s = "for"; + String result[] = s.split("[^fr]"); + if (!result[0].equals("f")) + failCount++; + if (!result[1].equals("r")) + failCount++; + s = "f\u203Ar"; + result = s.split("[^fr]"); + if (!result[0].equals("f")) + failCount++; + if (!result[1].equals("r")) + failCount++; + + // Test adding to bits, subtracting a node, then adding to bits again + pattern = Pattern.compile("[^f\u203Ar]"); + matcher = pattern.matcher("a"); + if (!matcher.find()) + failCount++; + matcher.reset("f"); + if (matcher.find()) + failCount++; + matcher.reset("\u203A"); + if (matcher.find()) + failCount++; + matcher.reset("r"); + if (matcher.find()) + failCount++; + matcher.reset("\u203B"); + if (!matcher.find()) + failCount++; + + // Test subtracting a node, adding to bits, subtracting again + pattern = Pattern.compile("[^\u203Ar\u203B]"); + matcher = pattern.matcher("a"); + if (!matcher.find()) + failCount++; + matcher.reset("\u203A"); + if (matcher.find()) + failCount++; + matcher.reset("r"); + if (matcher.find()) + failCount++; + matcher.reset("\u203B"); + if (matcher.find()) + failCount++; + matcher.reset("\u203C"); + if (!matcher.find()) + failCount++; + + report("Negated Character Class"); + } + + // This test is for 4628291 + private static void toStringTest() throws Exception { + Pattern pattern = Pattern.compile("b+"); + if (pattern.toString() != "b+") + failCount++; + Matcher matcher = pattern.matcher("aaabbbccc"); + String matcherString = matcher.toString(); // unspecified + matcher.find(); + matcherString = matcher.toString(); // unspecified + matcher.region(0,3); + matcherString = matcher.toString(); // unspecified + matcher.reset(); + matcherString = matcher.toString(); // unspecified + report("toString"); + } + + // This test is for 4808962 + private static void literalPatternTest() throws Exception { + int flags = Pattern.LITERAL; + + Pattern pattern = Pattern.compile("abc\\t$^", flags); + check(pattern, "abc\\t$^", true); + + pattern = Pattern.compile(Pattern.quote("abc\\t$^")); + check(pattern, "abc\\t$^", true); + + pattern = Pattern.compile("\\Qa^$bcabc\\E", flags); + check(pattern, "\\Qa^$bcabc\\E", true); + check(pattern, "a^$bcabc", false); + + pattern = Pattern.compile("\\\\Q\\\\E"); + check(pattern, "\\Q\\E", true); + + pattern = Pattern.compile("\\Qabc\\Eefg\\\\Q\\\\Ehij"); + check(pattern, "abcefg\\Q\\Ehij", true); + + pattern = Pattern.compile("\\\\\\Q\\\\E"); + check(pattern, "\\\\\\\\", true); + + pattern = Pattern.compile(Pattern.quote("\\Qa^$bcabc\\E")); + check(pattern, "\\Qa^$bcabc\\E", true); + check(pattern, "a^$bcabc", false); + + pattern = Pattern.compile(Pattern.quote("\\Qabc\\Edef")); + check(pattern, "\\Qabc\\Edef", true); + check(pattern, "abcdef", false); + + pattern = Pattern.compile(Pattern.quote("abc\\Edef")); + check(pattern, "abc\\Edef", true); + check(pattern, "abcdef", false); + + pattern = Pattern.compile(Pattern.quote("\\E")); + check(pattern, "\\E", true); + + pattern = Pattern.compile("((((abc.+?:)", flags); + check(pattern, "((((abc.+?:)", true); + + flags |= Pattern.MULTILINE; + + pattern = Pattern.compile("^cat$", flags); + check(pattern, "abc^cat$def", true); + check(pattern, "cat", false); + + flags |= Pattern.CASE_INSENSITIVE; + + pattern = Pattern.compile("abcdef", flags); + check(pattern, "ABCDEF", true); + check(pattern, "AbCdEf", true); + + flags |= Pattern.DOTALL; + + pattern = Pattern.compile("a...b", flags); + check(pattern, "A...b", true); + check(pattern, "Axxxb", false); + + flags |= Pattern.CANON_EQ; + + Pattern p = Pattern.compile("testa\u030a", flags); + check(pattern, "testa\u030a", false); + check(pattern, "test\u00e5", false); + + // Supplementary character test + flags = Pattern.LITERAL; + + pattern = Pattern.compile(toSupplementaries("abc\\t$^"), flags); + check(pattern, toSupplementaries("abc\\t$^"), true); + + pattern = Pattern.compile(Pattern.quote(toSupplementaries("abc\\t$^"))); + check(pattern, toSupplementaries("abc\\t$^"), true); + + pattern = Pattern.compile(toSupplementaries("\\Qa^$bcabc\\E"), flags); + check(pattern, toSupplementaries("\\Qa^$bcabc\\E"), true); + check(pattern, toSupplementaries("a^$bcabc"), false); + + pattern = Pattern.compile(Pattern.quote(toSupplementaries("\\Qa^$bcabc\\E"))); + check(pattern, toSupplementaries("\\Qa^$bcabc\\E"), true); + check(pattern, toSupplementaries("a^$bcabc"), false); + + pattern = Pattern.compile(Pattern.quote(toSupplementaries("\\Qabc\\Edef"))); + check(pattern, toSupplementaries("\\Qabc\\Edef"), true); + check(pattern, toSupplementaries("abcdef"), false); + + pattern = Pattern.compile(Pattern.quote(toSupplementaries("abc\\Edef"))); + check(pattern, toSupplementaries("abc\\Edef"), true); + check(pattern, toSupplementaries("abcdef"), false); + + pattern = Pattern.compile(toSupplementaries("((((abc.+?:)"), flags); + check(pattern, toSupplementaries("((((abc.+?:)"), true); + + flags |= Pattern.MULTILINE; + + pattern = Pattern.compile(toSupplementaries("^cat$"), flags); + check(pattern, toSupplementaries("abc^cat$def"), true); + check(pattern, toSupplementaries("cat"), false); + + flags |= Pattern.DOTALL; + + // note: this is case-sensitive. + pattern = Pattern.compile(toSupplementaries("a...b"), flags); + check(pattern, toSupplementaries("a...b"), true); + check(pattern, toSupplementaries("axxxb"), false); + + flags |= Pattern.CANON_EQ; + + String t = toSupplementaries("test"); + p = Pattern.compile(t + "a\u030a", flags); + check(pattern, t + "a\u030a", false); + check(pattern, t + "\u00e5", false); + + report("Literal pattern"); + } + + // This test is for 4803179 + // This test is also for 4808962, replacement parts + private static void literalReplacementTest() throws Exception { + int flags = Pattern.LITERAL; + + Pattern pattern = Pattern.compile("abc", flags); + Matcher matcher = pattern.matcher("zzzabczzz"); + String replaceTest = "$0"; + String result = matcher.replaceAll(replaceTest); + if (!result.equals("zzzabczzz")) + failCount++; + + matcher.reset(); + String literalReplacement = matcher.quoteReplacement(replaceTest); + result = matcher.replaceAll(literalReplacement); + if (!result.equals("zzz$0zzz")) + failCount++; + + matcher.reset(); + replaceTest = "\\t$\\$"; + literalReplacement = matcher.quoteReplacement(replaceTest); + result = matcher.replaceAll(literalReplacement); + if (!result.equals("zzz\\t$\\$zzz")) + failCount++; + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("abc"), flags); + matcher = pattern.matcher(toSupplementaries("zzzabczzz")); + replaceTest = "$0"; + result = matcher.replaceAll(replaceTest); + if (!result.equals(toSupplementaries("zzzabczzz"))) + failCount++; + + matcher.reset(); + literalReplacement = matcher.quoteReplacement(replaceTest); + result = matcher.replaceAll(literalReplacement); + if (!result.equals(toSupplementaries("zzz$0zzz"))) + failCount++; + + matcher.reset(); + replaceTest = "\\t$\\$"; + literalReplacement = matcher.quoteReplacement(replaceTest); + result = matcher.replaceAll(literalReplacement); + if (!result.equals(toSupplementaries("zzz\\t$\\$zzz"))) + failCount++; + + report("Literal replacement"); + } + + // This test is for 4757029 + private static void regionTest() throws Exception { + Pattern pattern = Pattern.compile("abc"); + Matcher matcher = pattern.matcher("abcdefabc"); + + matcher.region(0,9); + if (!matcher.find()) + failCount++; + if (!matcher.find()) + failCount++; + matcher.region(0,3); + if (!matcher.find()) + failCount++; + matcher.region(3,6); + if (matcher.find()) + failCount++; + matcher.region(0,2); + if (matcher.find()) + failCount++; + + expectRegionFail(matcher, 1, -1); + expectRegionFail(matcher, -1, -1); + expectRegionFail(matcher, -1, 1); + expectRegionFail(matcher, 5, 3); + expectRegionFail(matcher, 5, 12); + expectRegionFail(matcher, 12, 12); + + pattern = Pattern.compile("^abc$"); + matcher = pattern.matcher("zzzabczzz"); + matcher.region(0,9); + if (matcher.find()) + failCount++; + matcher.region(3,6); + if (!matcher.find()) + failCount++; + matcher.region(3,6); + matcher.useAnchoringBounds(false); + if (matcher.find()) + failCount++; + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("abc")); + matcher = pattern.matcher(toSupplementaries("abcdefabc")); + matcher.region(0,9*2); + if (!matcher.find()) + failCount++; + if (!matcher.find()) + failCount++; + matcher.region(0,3*2); + if (!matcher.find()) + failCount++; + matcher.region(1,3*2); + if (matcher.find()) + failCount++; + matcher.region(3*2,6*2); + if (matcher.find()) + failCount++; + matcher.region(0,2*2); + if (matcher.find()) + failCount++; + matcher.region(0,2*2+1); + if (matcher.find()) + failCount++; + + expectRegionFail(matcher, 1*2, -1); + expectRegionFail(matcher, -1, -1); + expectRegionFail(matcher, -1, 1*2); + expectRegionFail(matcher, 5*2, 3*2); + expectRegionFail(matcher, 5*2, 12*2); + expectRegionFail(matcher, 12*2, 12*2); + + pattern = Pattern.compile(toSupplementaries("^abc$")); + matcher = pattern.matcher(toSupplementaries("zzzabczzz")); + matcher.region(0,9*2); + if (matcher.find()) + failCount++; + matcher.region(3*2,6*2); + if (!matcher.find()) + failCount++; + matcher.region(3*2+1,6*2); + if (matcher.find()) + failCount++; + matcher.region(3*2,6*2-1); + if (matcher.find()) + failCount++; + matcher.region(3*2,6*2); + matcher.useAnchoringBounds(false); + if (matcher.find()) + failCount++; + report("Regions"); + } + + private static void expectRegionFail(Matcher matcher, int index1, + int index2) + { + try { + matcher.region(index1, index2); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Correct result + } catch (IllegalStateException ise) { + // Correct result + } + } + + // This test is for 4803197 + private static void escapedSegmentTest() throws Exception { + + Pattern pattern = Pattern.compile("\\Qdir1\\dir2\\E"); + check(pattern, "dir1\\dir2", true); + + pattern = Pattern.compile("\\Qdir1\\dir2\\\\E"); + check(pattern, "dir1\\dir2\\", true); + + pattern = Pattern.compile("(\\Qdir1\\dir2\\\\E)"); + check(pattern, "dir1\\dir2\\", true); + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("\\Qdir1\\dir2\\E")); + check(pattern, toSupplementaries("dir1\\dir2"), true); + + pattern = Pattern.compile(toSupplementaries("\\Qdir1\\dir2")+"\\\\E"); + check(pattern, toSupplementaries("dir1\\dir2\\"), true); + + pattern = Pattern.compile(toSupplementaries("(\\Qdir1\\dir2")+"\\\\E)"); + check(pattern, toSupplementaries("dir1\\dir2\\"), true); + + report("Escaped segment"); + } + + // This test is for 4792284 + private static void nonCaptureRepetitionTest() throws Exception { + String input = "abcdefgh;"; + + String[] patterns = new String[] { + "(?:\\w{4})+;", + "(?:\\w{8})*;", + "(?:\\w{2}){2,4};", + "(?:\\w{4}){2,};", // only matches the + ".*?(?:\\w{5})+;", // specified minimum + ".*?(?:\\w{9})*;", // number of reps - OK + "(?:\\w{4})+?;", // lazy repetition - OK + "(?:\\w{4})++;", // possessive repetition - OK + "(?:\\w{2,}?)+;", // non-deterministic - OK + "(\\w{4})+;", // capturing group - OK + }; + + for (int i = 0; i < patterns.length; i++) { + // Check find() + check(patterns[i], 0, input, input, true); + // Check matches() + Pattern p = Pattern.compile(patterns[i]); + Matcher m = p.matcher(input); + + if (m.matches()) { + if (!m.group(0).equals(input)) + failCount++; + } else { + failCount++; + } + } + + report("Non capturing repetition"); + } + + // This test is for 6358731 + private static void notCapturedGroupCurlyMatchTest() throws Exception { + Pattern pattern = Pattern.compile("(abc)+|(abcd)+"); + Matcher matcher = pattern.matcher("abcd"); + if (!matcher.matches() || + matcher.group(1) != null || + !matcher.group(2).equals("abcd")) { + failCount++; + } + report("Not captured GroupCurly"); + } + + // This test is for 4706545 + private static void javaCharClassTest() throws Exception { + for (int i=0; i<1000; i++) { + char c = (char)generator.nextInt(); + check("{javaLowerCase}", c, Character.isLowerCase(c)); + check("{javaUpperCase}", c, Character.isUpperCase(c)); + check("{javaUpperCase}+", c, Character.isUpperCase(c)); + check("{javaTitleCase}", c, Character.isTitleCase(c)); + check("{javaDigit}", c, Character.isDigit(c)); + check("{javaDefined}", c, Character.isDefined(c)); + check("{javaLetter}", c, Character.isLetter(c)); + check("{javaLetterOrDigit}", c, Character.isLetterOrDigit(c)); + check("{javaJavaIdentifierStart}", c, + Character.isJavaIdentifierStart(c)); + check("{javaJavaIdentifierPart}", c, + Character.isJavaIdentifierPart(c)); + check("{javaUnicodeIdentifierStart}", c, + Character.isUnicodeIdentifierStart(c)); + check("{javaUnicodeIdentifierPart}", c, + Character.isUnicodeIdentifierPart(c)); + check("{javaIdentifierIgnorable}", c, + Character.isIdentifierIgnorable(c)); + check("{javaSpaceChar}", c, Character.isSpaceChar(c)); + check("{javaWhitespace}", c, Character.isWhitespace(c)); + check("{javaISOControl}", c, Character.isISOControl(c)); + check("{javaMirrored}", c, Character.isMirrored(c)); + + } + + // Supplementary character test + for (int i=0; i<1000; i++) { + int c = generator.nextInt(Character.MAX_CODE_POINT + - Character.MIN_SUPPLEMENTARY_CODE_POINT) + + Character.MIN_SUPPLEMENTARY_CODE_POINT; + check("{javaLowerCase}", c, Character.isLowerCase(c)); + check("{javaUpperCase}", c, Character.isUpperCase(c)); + check("{javaUpperCase}+", c, Character.isUpperCase(c)); + check("{javaTitleCase}", c, Character.isTitleCase(c)); + check("{javaDigit}", c, Character.isDigit(c)); + check("{javaDefined}", c, Character.isDefined(c)); + check("{javaLetter}", c, Character.isLetter(c)); + check("{javaLetterOrDigit}", c, Character.isLetterOrDigit(c)); + check("{javaJavaIdentifierStart}", c, + Character.isJavaIdentifierStart(c)); + check("{javaJavaIdentifierPart}", c, + Character.isJavaIdentifierPart(c)); + check("{javaUnicodeIdentifierStart}", c, + Character.isUnicodeIdentifierStart(c)); + check("{javaUnicodeIdentifierPart}", c, + Character.isUnicodeIdentifierPart(c)); + check("{javaIdentifierIgnorable}", c, + Character.isIdentifierIgnorable(c)); + check("{javaSpaceChar}", c, Character.isSpaceChar(c)); + check("{javaWhitespace}", c, Character.isWhitespace(c)); + check("{javaISOControl}", c, Character.isISOControl(c)); + check("{javaMirrored}", c, Character.isMirrored(c)); + } + + report("Java character classes"); + } + + // This test is for 4523620 + /* + private static void numOccurrencesTest() throws Exception { + Pattern pattern = Pattern.compile("aaa"); + + if (pattern.numOccurrences("aaaaaa", false) != 2) + failCount++; + if (pattern.numOccurrences("aaaaaa", true) != 4) + failCount++; + + pattern = Pattern.compile("^"); + if (pattern.numOccurrences("aaaaaa", false) != 1) + failCount++; + if (pattern.numOccurrences("aaaaaa", true) != 1) + failCount++; + + report("Number of Occurrences"); + } + */ + + // This test is for 4776374 + private static void caretBetweenTerminatorsTest() throws Exception { + int flags1 = Pattern.DOTALL; + int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES; + int flags3 = Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.MULTILINE; + int flags4 = Pattern.DOTALL | Pattern.MULTILINE; + + check("^....", flags1, "test\ntest", "test", true); + check(".....^", flags1, "test\ntest", "test", false); + check(".....^", flags1, "test\n", "test", false); + check("....^", flags1, "test\r\n", "test", false); + + check("^....", flags2, "test\ntest", "test", true); + check("....^", flags2, "test\ntest", "test", false); + check(".....^", flags2, "test\n", "test", false); + check("....^", flags2, "test\r\n", "test", false); + + check("^....", flags3, "test\ntest", "test", true); + check(".....^", flags3, "test\ntest", "test\n", true); + check(".....^", flags3, "test\u0085test", "test\u0085", false); + check(".....^", flags3, "test\n", "test", false); + check(".....^", flags3, "test\r\n", "test", false); + check("......^", flags3, "test\r\ntest", "test\r\n", true); + + check("^....", flags4, "test\ntest", "test", true); + check(".....^", flags3, "test\ntest", "test\n", true); + check(".....^", flags4, "test\u0085test", "test\u0085", true); + check(".....^", flags4, "test\n", "test\n", false); + check(".....^", flags4, "test\r\n", "test\r", false); + + // Supplementary character test + String t = toSupplementaries("test"); + check("^....", flags1, t+"\n"+t, t, true); + check(".....^", flags1, t+"\n"+t, t, false); + check(".....^", flags1, t+"\n", t, false); + check("....^", flags1, t+"\r\n", t, false); + + check("^....", flags2, t+"\n"+t, t, true); + check("....^", flags2, t+"\n"+t, t, false); + check(".....^", flags2, t+"\n", t, false); + check("....^", flags2, t+"\r\n", t, false); + + check("^....", flags3, t+"\n"+t, t, true); + check(".....^", flags3, t+"\n"+t, t+"\n", true); + check(".....^", flags3, t+"\u0085"+t, t+"\u0085", false); + check(".....^", flags3, t+"\n", t, false); + check(".....^", flags3, t+"\r\n", t, false); + check("......^", flags3, t+"\r\n"+t, t+"\r\n", true); + + check("^....", flags4, t+"\n"+t, t, true); + check(".....^", flags3, t+"\n"+t, t+"\n", true); + check(".....^", flags4, t+"\u0085"+t, t+"\u0085", true); + check(".....^", flags4, t+"\n", t+"\n", false); + check(".....^", flags4, t+"\r\n", t+"\r", false); + + report("Caret between terminators"); + } + + // This test is for 4727935 + private static void dollarAtEndTest() throws Exception { + int flags1 = Pattern.DOTALL; + int flags2 = Pattern.DOTALL | Pattern.UNIX_LINES; + int flags3 = Pattern.DOTALL | Pattern.MULTILINE; + + check("....$", flags1, "test\n", "test", true); + check("....$", flags1, "test\r\n", "test", true); + check(".....$", flags1, "test\n", "test\n", true); + check(".....$", flags1, "test\u0085", "test\u0085", true); + check("....$", flags1, "test\u0085", "test", true); + + check("....$", flags2, "test\n", "test", true); + check(".....$", flags2, "test\n", "test\n", true); + check(".....$", flags2, "test\u0085", "test\u0085", true); + check("....$", flags2, "test\u0085", "est\u0085", true); + + check("....$.blah", flags3, "test\nblah", "test\nblah", true); + check(".....$.blah", flags3, "test\n\nblah", "test\n\nblah", true); + check("....$blah", flags3, "test\nblah", "!!!!", false); + check(".....$blah", flags3, "test\nblah", "!!!!", false); + + // Supplementary character test + String t = toSupplementaries("test"); + String b = toSupplementaries("blah"); + check("....$", flags1, t+"\n", t, true); + check("....$", flags1, t+"\r\n", t, true); + check(".....$", flags1, t+"\n", t+"\n", true); + check(".....$", flags1, t+"\u0085", t+"\u0085", true); + check("....$", flags1, t+"\u0085", t, true); + + check("....$", flags2, t+"\n", t, true); + check(".....$", flags2, t+"\n", t+"\n", true); + check(".....$", flags2, t+"\u0085", t+"\u0085", true); + check("....$", flags2, t+"\u0085", toSupplementaries("est\u0085"), true); + + check("....$."+b, flags3, t+"\n"+b, t+"\n"+b, true); + check(".....$."+b, flags3, t+"\n\n"+b, t+"\n\n"+b, true); + check("....$"+b, flags3, t+"\n"+b, "!!!!", false); + check(".....$"+b, flags3, t+"\n"+b, "!!!!", false); + + report("Dollar at End"); + } + + // This test is for 4711773 + private static void multilineDollarTest() throws Exception { + Pattern findCR = Pattern.compile("$", Pattern.MULTILINE); + Matcher matcher = findCR.matcher("first bit\nsecond bit"); + matcher.find(); + if (matcher.start(0) != 9) + failCount++; + matcher.find(); + if (matcher.start(0) != 20) + failCount++; + + // Supplementary character test + matcher = findCR.matcher(toSupplementaries("first bit\n second bit")); // double BMP chars + matcher.find(); + if (matcher.start(0) != 9*2) + failCount++; + matcher.find(); + if (matcher.start(0) != 20*2) + failCount++; + + report("Multiline Dollar"); + } + + private static void reluctantRepetitionTest() throws Exception { + Pattern p = Pattern.compile("1(\\s\\S+?){1,3}?[\\s,]2"); + check(p, "1 word word word 2", true); + check(p, "1 wor wo w 2", true); + check(p, "1 word word 2", true); + check(p, "1 word 2", true); + check(p, "1 wo w w 2", true); + check(p, "1 wo w 2", true); + check(p, "1 wor w 2", true); + + p = Pattern.compile("([a-z])+?c"); + Matcher m = p.matcher("ababcdefdec"); + check(m, "ababc"); + + // Supplementary character test + p = Pattern.compile(toSupplementaries("([a-z])+?c")); + m = p.matcher(toSupplementaries("ababcdefdec")); + check(m, toSupplementaries("ababc")); + + report("Reluctant Repetition"); + } + + private static void serializeTest() throws Exception { + String patternStr = "(b)"; + String matchStr = "b"; + Pattern pattern = Pattern.compile(patternStr); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(pattern); + oos.close(); + ObjectInputStream ois = new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())); + Pattern serializedPattern = (Pattern)ois.readObject(); + ois.close(); + Matcher matcher = serializedPattern.matcher(matchStr); + if (!matcher.matches()) + failCount++; + if (matcher.groupCount() != 1) + failCount++; + + report("Serialization"); + } + + private static void gTest() { + Pattern pattern = Pattern.compile("\\G\\w"); + Matcher matcher = pattern.matcher("abc#x#x"); + matcher.find(); + matcher.find(); + matcher.find(); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("\\GA*"); + matcher = pattern.matcher("1A2AA3"); + matcher.find(); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("\\GA*"); + matcher = pattern.matcher("1A2AA3"); + if (!matcher.find(1)) + failCount++; + matcher.find(); + if (matcher.find()) + failCount++; + + report("\\G"); + } + + private static void zTest() { + Pattern pattern = Pattern.compile("foo\\Z"); + // Positives + check(pattern, "foo\u0085", true); + check(pattern, "foo\u2028", true); + check(pattern, "foo\u2029", true); + check(pattern, "foo\n", true); + check(pattern, "foo\r", true); + check(pattern, "foo\r\n", true); + // Negatives + check(pattern, "fooo", false); + check(pattern, "foo\n\r", false); + + pattern = Pattern.compile("foo\\Z", Pattern.UNIX_LINES); + // Positives + check(pattern, "foo", true); + check(pattern, "foo\n", true); + // Negatives + check(pattern, "foo\r", false); + check(pattern, "foo\u0085", false); + check(pattern, "foo\u2028", false); + check(pattern, "foo\u2029", false); + + report("\\Z"); + } + + private static void replaceFirstTest() { + Pattern pattern = Pattern.compile("(ab)(c*)"); + Matcher matcher = pattern.matcher("abccczzzabcczzzabccc"); + if (!matcher.replaceFirst("test").equals("testzzzabcczzzabccc")) + failCount++; + + matcher.reset("zzzabccczzzabcczzzabccczzz"); + if (!matcher.replaceFirst("test").equals("zzztestzzzabcczzzabccczzz")) + failCount++; + + matcher.reset("zzzabccczzzabcczzzabccczzz"); + String result = matcher.replaceFirst("$1"); + if (!result.equals("zzzabzzzabcczzzabccczzz")) + failCount++; + + matcher.reset("zzzabccczzzabcczzzabccczzz"); + result = matcher.replaceFirst("$2"); + if (!result.equals("zzzccczzzabcczzzabccczzz")) + failCount++; + + pattern = Pattern.compile("a*"); + matcher = pattern.matcher("aaaaaaaaaa"); + if (!matcher.replaceFirst("test").equals("test")) + failCount++; + + pattern = Pattern.compile("a+"); + matcher = pattern.matcher("zzzaaaaaaaaaa"); + if (!matcher.replaceFirst("test").equals("zzztest")) + failCount++; + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("(ab)(c*)")); + matcher = pattern.matcher(toSupplementaries("abccczzzabcczzzabccc")); + if (!matcher.replaceFirst(toSupplementaries("test")) + .equals(toSupplementaries("testzzzabcczzzabccc"))) + failCount++; + + matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + if (!matcher.replaceFirst(toSupplementaries("test")). + equals(toSupplementaries("zzztestzzzabcczzzabccczzz"))) + failCount++; + + matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + result = matcher.replaceFirst("$1"); + if (!result.equals(toSupplementaries("zzzabzzzabcczzzabccczzz"))) + failCount++; + + matcher.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + result = matcher.replaceFirst("$2"); + if (!result.equals(toSupplementaries("zzzccczzzabcczzzabccczzz"))) + failCount++; + + pattern = Pattern.compile(toSupplementaries("a*")); + matcher = pattern.matcher(toSupplementaries("aaaaaaaaaa")); + if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("test"))) + failCount++; + + pattern = Pattern.compile(toSupplementaries("a+")); + matcher = pattern.matcher(toSupplementaries("zzzaaaaaaaaaa")); + if (!matcher.replaceFirst(toSupplementaries("test")).equals(toSupplementaries("zzztest"))) + failCount++; + + report("Replace First"); + } + + private static void unixLinesTest() { + Pattern pattern = Pattern.compile(".*"); + Matcher matcher = pattern.matcher("aa\u2028blah"); + matcher.find(); + if (!matcher.group(0).equals("aa")) + failCount++; + + pattern = Pattern.compile(".*", Pattern.UNIX_LINES); + matcher = pattern.matcher("aa\u2028blah"); + matcher.find(); + if (!matcher.group(0).equals("aa\u2028blah")) + failCount++; + + pattern = Pattern.compile("[az]$", + Pattern.MULTILINE | Pattern.UNIX_LINES); + matcher = pattern.matcher("aa\u2028zz"); + check(matcher, "a\u2028", false); + + // Supplementary character test + pattern = Pattern.compile(".*"); + matcher = pattern.matcher(toSupplementaries("aa\u2028blah")); + matcher.find(); + if (!matcher.group(0).equals(toSupplementaries("aa"))) + failCount++; + + pattern = Pattern.compile(".*", Pattern.UNIX_LINES); + matcher = pattern.matcher(toSupplementaries("aa\u2028blah")); + matcher.find(); + if (!matcher.group(0).equals(toSupplementaries("aa\u2028blah"))) + failCount++; + + pattern = Pattern.compile(toSupplementaries("[az]$"), + Pattern.MULTILINE | Pattern.UNIX_LINES); + matcher = pattern.matcher(toSupplementaries("aa\u2028zz")); + check(matcher, toSupplementaries("a\u2028"), false); + + report("Unix Lines"); + } + + private static void commentsTest() { + int flags = Pattern.COMMENTS; + + Pattern pattern = Pattern.compile("aa \\# aa", flags); + Matcher matcher = pattern.matcher("aa#aa"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah", flags); + matcher = pattern.matcher("aa"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa blah", flags); + matcher = pattern.matcher("aablah"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah blech ", flags); + matcher = pattern.matcher("aa"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah\n ", flags); + matcher = pattern.matcher("aa"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah\nbc # blech", flags); + matcher = pattern.matcher("aabc"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah\nbc# blech", flags); + matcher = pattern.matcher("aabc"); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa # blah\nbc\\# blech", flags); + matcher = pattern.matcher("aabc#blech"); + if (!matcher.matches()) + failCount++; + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("aa \\# aa"), flags); + matcher = pattern.matcher(toSupplementaries("aa#aa")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah"), flags); + matcher = pattern.matcher(toSupplementaries("aa")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa blah"), flags); + matcher = pattern.matcher(toSupplementaries("aablah")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah blech "), flags); + matcher = pattern.matcher(toSupplementaries("aa")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah\n "), flags); + matcher = pattern.matcher(toSupplementaries("aa")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah\nbc # blech"), flags); + matcher = pattern.matcher(toSupplementaries("aabc")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah\nbc# blech"), flags); + matcher = pattern.matcher(toSupplementaries("aabc")); + if (!matcher.matches()) + failCount++; + + pattern = Pattern.compile(toSupplementaries("aa # blah\nbc\\# blech"), flags); + matcher = pattern.matcher(toSupplementaries("aabc#blech")); + if (!matcher.matches()) + failCount++; + + report("Comments"); + } + + private static void caseFoldingTest() { // bug 4504687 + int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; + Pattern pattern = Pattern.compile("aa", flags); + Matcher matcher = pattern.matcher("ab"); + if (matcher.matches()) + failCount++; + + pattern = Pattern.compile("aA", flags); + matcher = pattern.matcher("ab"); + if (matcher.matches()) + failCount++; + + pattern = Pattern.compile("aa", flags); + matcher = pattern.matcher("aB"); + if (matcher.matches()) + failCount++; + matcher = pattern.matcher("Ab"); + if (matcher.matches()) + failCount++; + + // ASCII "a" + // Latin-1 Supplement "a" + grave + // Cyrillic "a" + String[] patterns = new String[] { + //single + "a", "\u00e0", "\u0430", + //slice + "ab", "\u00e0\u00e1", "\u0430\u0431", + //class single + "[a]", "[\u00e0]", "[\u0430]", + //class range + "[a-b]", "[\u00e0-\u00e5]", "[\u0430-\u0431]", + //back reference + "(a)\\1", "(\u00e0)\\1", "(\u0430)\\1" + }; + + String[] texts = new String[] { + "A", "\u00c0", "\u0410", + "AB", "\u00c0\u00c1", "\u0410\u0411", + "A", "\u00c0", "\u0410", + "B", "\u00c2", "\u0411", + "aA", "\u00e0\u00c0", "\u0430\u0410" + }; + + boolean[] expected = new boolean[] { + true, false, false, + true, false, false, + true, false, false, + true, false, false, + true, false, false + }; + + flags = Pattern.CASE_INSENSITIVE; + for (int i = 0; i < patterns.length; i++) { + pattern = Pattern.compile(patterns[i], flags); + matcher = pattern.matcher(texts[i]); + if (matcher.matches() != expected[i]) { + System.out.println("<1> Failed at " + i); + failCount++; + } + } + + flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; + for (int i = 0; i < patterns.length; i++) { + pattern = Pattern.compile(patterns[i], flags); + matcher = pattern.matcher(texts[i]); + if (!matcher.matches()) { + System.out.println("<2> Failed at " + i); + failCount++; + } + } + // flag unicode_case alone should do nothing + flags = Pattern.UNICODE_CASE; + for (int i = 0; i < patterns.length; i++) { + pattern = Pattern.compile(patterns[i], flags); + matcher = pattern.matcher(texts[i]); + if (matcher.matches()) { + System.out.println("<3> Failed at " + i); + failCount++; + } + } + + // Special cases: i, I, u+0131 and u+0130 + flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; + pattern = Pattern.compile("[h-j]+", flags); + if (!pattern.matcher("\u0131\u0130").matches()) + failCount++; + report("Case Folding"); + } + + private static void appendTest() { + Pattern pattern = Pattern.compile("(ab)(cd)"); + Matcher matcher = pattern.matcher("abcd"); + String result = matcher.replaceAll("$2$1"); + if (!result.equals("cdab")) + failCount++; + + String s1 = "Swap all: first = 123, second = 456"; + String s2 = "Swap one: first = 123, second = 456"; + String r = "$3$2$1"; + pattern = Pattern.compile("([a-z]+)( *= *)([0-9]+)"); + matcher = pattern.matcher(s1); + + result = matcher.replaceAll(r); + if (!result.equals("Swap all: 123 = first, 456 = second")) + failCount++; + + matcher = pattern.matcher(s2); + + if (matcher.find()) { + StringBuffer sb = new StringBuffer(); + matcher.appendReplacement(sb, r); + matcher.appendTail(sb); + result = sb.toString(); + if (!result.equals("Swap one: 123 = first, second = 456")) + failCount++; + } + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("(ab)(cd)")); + matcher = pattern.matcher(toSupplementaries("abcd")); + result = matcher.replaceAll("$2$1"); + if (!result.equals(toSupplementaries("cdab"))) + failCount++; + + s1 = toSupplementaries("Swap all: first = 123, second = 456"); + s2 = toSupplementaries("Swap one: first = 123, second = 456"); + r = toSupplementaries("$3$2$1"); + pattern = Pattern.compile(toSupplementaries("([a-z]+)( *= *)([0-9]+)")); + matcher = pattern.matcher(s1); + + result = matcher.replaceAll(r); + if (!result.equals(toSupplementaries("Swap all: 123 = first, 456 = second"))) + failCount++; + + matcher = pattern.matcher(s2); + + if (matcher.find()) { + StringBuffer sb = new StringBuffer(); + matcher.appendReplacement(sb, r); + matcher.appendTail(sb); + result = sb.toString(); + if (!result.equals(toSupplementaries("Swap one: 123 = first, second = 456"))) + failCount++; + } + report("Append"); + } + + private static void splitTest() { + Pattern pattern = Pattern.compile(":"); + String[] result = pattern.split("foo:and:boo", 2); + if (!result[0].equals("foo")) + failCount++; + if (!result[1].equals("and:boo")) + failCount++; + // Supplementary character test + Pattern patternX = Pattern.compile(toSupplementaries("X")); + result = patternX.split(toSupplementaries("fooXandXboo"), 2); + if (!result[0].equals(toSupplementaries("foo"))) + failCount++; + if (!result[1].equals(toSupplementaries("andXboo"))) + failCount++; + + CharBuffer cb = CharBuffer.allocate(100); + cb.put("foo:and:boo"); + cb.flip(); + result = pattern.split(cb); + if (!result[0].equals("foo")) + failCount++; + if (!result[1].equals("and")) + failCount++; + if (!result[2].equals("boo")) + failCount++; + + // Supplementary character test + CharBuffer cbs = CharBuffer.allocate(100); + cbs.put(toSupplementaries("fooXandXboo")); + cbs.flip(); + result = patternX.split(cbs); + if (!result[0].equals(toSupplementaries("foo"))) + failCount++; + if (!result[1].equals(toSupplementaries("and"))) + failCount++; + if (!result[2].equals(toSupplementaries("boo"))) + failCount++; + + String source = "0123456789"; + for (int limit=-2; limit<3; limit++) { + for (int x=0; x<10; x++) { + result = source.split(Integer.toString(x), limit); + int expectedLength = limit < 1 ? 2 : limit; + + if ((limit == 0) && (x == 9)) { + // expected dropping of "" + if (result.length != 1) + failCount++; + if (!result[0].equals("012345678")) { + failCount++; + } + } else { + if (result.length != expectedLength) { + failCount++; + } + if (!result[0].equals(source.substring(0,x))) { + if (limit != 1) { + failCount++; + } else { + if (!result[0].equals(source.substring(0,10))) { + failCount++; + } + } + } + if (expectedLength > 1) { // Check segment 2 + if (!result[1].equals(source.substring(x+1,10))) + failCount++; + } + } + } + } + // Check the case for no match found + for (int limit=-2; limit<3; limit++) { + result = source.split("e", limit); + if (result.length != 1) + failCount++; + if (!result[0].equals(source)) + failCount++; + } + // Check the case for limit == 0, source = ""; + source = ""; + result = source.split("e", 0); + if (result.length != 1) + failCount++; + if (!result[0].equals(source)) + failCount++; + + report("Split"); + } + + private static void negationTest() { + Pattern pattern = Pattern.compile("[\\[@^]+"); + Matcher matcher = pattern.matcher("@@@@[[[[^^^^"); + if (!matcher.find()) + failCount++; + if (!matcher.group(0).equals("@@@@[[[[^^^^")) + failCount++; + pattern = Pattern.compile("[@\\[^]+"); + matcher = pattern.matcher("@@@@[[[[^^^^"); + if (!matcher.find()) + failCount++; + if (!matcher.group(0).equals("@@@@[[[[^^^^")) + failCount++; + pattern = Pattern.compile("[@\\[^@]+"); + matcher = pattern.matcher("@@@@[[[[^^^^"); + if (!matcher.find()) + failCount++; + if (!matcher.group(0).equals("@@@@[[[[^^^^")) + failCount++; + + pattern = Pattern.compile("\\)"); + matcher = pattern.matcher("xxx)xxx"); + if (!matcher.find()) + failCount++; + + report("Negation"); + } + + private static void ampersandTest() { + Pattern pattern = Pattern.compile("[&@]+"); + check(pattern, "@@@@&&&&", true); + + pattern = Pattern.compile("[@&]+"); + check(pattern, "@@@@&&&&", true); + + pattern = Pattern.compile("[@\\&]+"); + check(pattern, "@@@@&&&&", true); + + report("Ampersand"); + } + + private static void octalTest() throws Exception { + Pattern pattern = Pattern.compile("\\u0007"); + Matcher matcher = pattern.matcher("\u0007"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\07"); + matcher = pattern.matcher("\u0007"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\007"); + matcher = pattern.matcher("\u0007"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\0007"); + matcher = pattern.matcher("\u0007"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\040"); + matcher = pattern.matcher("\u0020"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\0403"); + matcher = pattern.matcher("\u00203"); + if (!matcher.matches()) + failCount++; + pattern = Pattern.compile("\\0103"); + matcher = pattern.matcher("\u0043"); + if (!matcher.matches()) + failCount++; + + report("Octal"); + } + + private static void longPatternTest() throws Exception { + try { + Pattern pattern = Pattern.compile( + "a 32-character-long pattern xxxx"); + pattern = Pattern.compile("a 33-character-long pattern xxxxx"); + pattern = Pattern.compile("a thirty four character long regex"); + StringBuffer patternToBe = new StringBuffer(101); + for (int i=0; i<100; i++) + patternToBe.append((char)(97 + i%26)); + pattern = Pattern.compile(patternToBe.toString()); + } catch (PatternSyntaxException e) { + failCount++; + } + + // Supplementary character test + try { + Pattern pattern = Pattern.compile( + toSupplementaries("a 32-character-long pattern xxxx")); + pattern = Pattern.compile(toSupplementaries("a 33-character-long pattern xxxxx")); + pattern = Pattern.compile(toSupplementaries("a thirty four character long regex")); + StringBuffer patternToBe = new StringBuffer(101*2); + for (int i=0; i<100; i++) + patternToBe.append(Character.toChars(Character.MIN_SUPPLEMENTARY_CODE_POINT + + 97 + i%26)); + pattern = Pattern.compile(patternToBe.toString()); + } catch (PatternSyntaxException e) { + failCount++; + } + report("LongPattern"); + } + + private static void group0Test() throws Exception { + Pattern pattern = Pattern.compile("(tes)ting"); + Matcher matcher = pattern.matcher("testing"); + check(matcher, "testing"); + + matcher.reset("testing"); + if (matcher.lookingAt()) { + if (!matcher.group(0).equals("testing")) + failCount++; + } else { + failCount++; + } + + matcher.reset("testing"); + if (matcher.matches()) { + if (!matcher.group(0).equals("testing")) + failCount++; + } else { + failCount++; + } + + pattern = Pattern.compile("(tes)ting"); + matcher = pattern.matcher("testing"); + if (matcher.lookingAt()) { + if (!matcher.group(0).equals("testing")) + failCount++; + } else { + failCount++; + } + + pattern = Pattern.compile("^(tes)ting"); + matcher = pattern.matcher("testing"); + if (matcher.matches()) { + if (!matcher.group(0).equals("testing")) + failCount++; + } else { + failCount++; + } + + // Supplementary character test + pattern = Pattern.compile(toSupplementaries("(tes)ting")); + matcher = pattern.matcher(toSupplementaries("testing")); + check(matcher, toSupplementaries("testing")); + + matcher.reset(toSupplementaries("testing")); + if (matcher.lookingAt()) { + if (!matcher.group(0).equals(toSupplementaries("testing"))) + failCount++; + } else { + failCount++; + } + + matcher.reset(toSupplementaries("testing")); + if (matcher.matches()) { + if (!matcher.group(0).equals(toSupplementaries("testing"))) + failCount++; + } else { + failCount++; + } + + pattern = Pattern.compile(toSupplementaries("(tes)ting")); + matcher = pattern.matcher(toSupplementaries("testing")); + if (matcher.lookingAt()) { + if (!matcher.group(0).equals(toSupplementaries("testing"))) + failCount++; + } else { + failCount++; + } + + pattern = Pattern.compile(toSupplementaries("^(tes)ting")); + matcher = pattern.matcher(toSupplementaries("testing")); + if (matcher.matches()) { + if (!matcher.group(0).equals(toSupplementaries("testing"))) + failCount++; + } else { + failCount++; + } + + report("Group0"); + } + + private static void findIntTest() throws Exception { + Pattern p = Pattern.compile("blah"); + Matcher m = p.matcher("zzzzblahzzzzzblah"); + boolean result = m.find(2); + if (!result) + failCount++; + + p = Pattern.compile("$"); + m = p.matcher("1234567890"); + result = m.find(10); + if (!result) + failCount++; + try { + result = m.find(11); + failCount++; + } catch (IndexOutOfBoundsException e) { + // correct result + } + + // Supplementary character test + p = Pattern.compile(toSupplementaries("blah")); + m = p.matcher(toSupplementaries("zzzzblahzzzzzblah")); + result = m.find(2); + if (!result) + failCount++; + + report("FindInt"); + } + + private static void emptyPatternTest() throws Exception { + Pattern p = Pattern.compile(""); + Matcher m = p.matcher("foo"); + + // Should find empty pattern at beginning of input + boolean result = m.find(); + if (result != true) + failCount++; + if (m.start() != 0) + failCount++; + + // Should not match entire input if input is not empty + m.reset(); + result = m.matches(); + if (result == true) + failCount++; + + try { + m.start(0); + failCount++; + } catch (IllegalStateException e) { + // Correct result + } + + // Should match entire input if input is empty + m.reset(""); + result = m.matches(); + if (result != true) + failCount++; + + result = Pattern.matches("", ""); + if (result != true) + failCount++; + + result = Pattern.matches("", "foo"); + if (result == true) + failCount++; + report("EmptyPattern"); + } + + private static void charClassTest() throws Exception { + Pattern pattern = Pattern.compile("blah[ab]]blech"); + check(pattern, "blahb]blech", true); + + pattern = Pattern.compile("[abc[def]]"); + check(pattern, "b", true); + + // Supplementary character tests + pattern = Pattern.compile(toSupplementaries("blah[ab]]blech")); + check(pattern, toSupplementaries("blahb]blech"), true); + + pattern = Pattern.compile(toSupplementaries("[abc[def]]")); + check(pattern, toSupplementaries("b"), true); + + try { + // u00ff when UNICODE_CASE + pattern = Pattern.compile("[ab\u00ffcd]", + Pattern.CASE_INSENSITIVE| + Pattern.UNICODE_CASE); + check(pattern, "ab\u00ffcd", true); + check(pattern, "Ab\u0178Cd", true); + + // u00b5 when UNICODE_CASE + pattern = Pattern.compile("[ab\u00b5cd]", + Pattern.CASE_INSENSITIVE| + Pattern.UNICODE_CASE); + check(pattern, "ab\u00b5cd", true); + check(pattern, "Ab\u039cCd", true); + } catch (Exception e) { failCount++; } + + /* Special cases + (1)LatinSmallLetterLongS u+017f + (2)LatinSmallLetterDotlessI u+0131 + (3)LatineCapitalLetterIWithDotAbove u+0130 + (4)KelvinSign u+212a + (5)AngstromSign u+212b + */ + int flags = Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE; + pattern = Pattern.compile("[sik\u00c5]+", flags); + if (!pattern.matcher("\u017f\u0130\u0131\u212a\u212b").matches()) + failCount++; + + report("CharClass"); + } + + private static void caretTest() throws Exception { + Pattern pattern = Pattern.compile("\\w*"); + Matcher matcher = pattern.matcher("a#bc#def##g"); + check(matcher, "a"); + check(matcher, ""); + check(matcher, "bc"); + check(matcher, ""); + check(matcher, "def"); + check(matcher, ""); + check(matcher, ""); + check(matcher, "g"); + check(matcher, ""); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("^\\w*"); + matcher = pattern.matcher("a#bc#def##g"); + check(matcher, "a"); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("\\w"); + matcher = pattern.matcher("abc##x"); + check(matcher, "a"); + check(matcher, "b"); + check(matcher, "c"); + check(matcher, "x"); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("^\\w"); + matcher = pattern.matcher("abc##x"); + check(matcher, "a"); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("\\A\\p{Alpha}{3}"); + matcher = pattern.matcher("abcdef-ghi\njklmno"); + check(matcher, "abc"); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("^\\p{Alpha}{3}", Pattern.MULTILINE); + matcher = pattern.matcher("abcdef-ghi\njklmno"); + check(matcher, "abc"); + check(matcher, "jkl"); + if (matcher.find()) + failCount++; + + pattern = Pattern.compile("^", Pattern.MULTILINE); + matcher = pattern.matcher("this is some text"); + String result = matcher.replaceAll("X"); + if (!result.equals("Xthis is some text")) + failCount++; + + pattern = Pattern.compile("^"); + matcher = pattern.matcher("this is some text"); + result = matcher.replaceAll("X"); + if (!result.equals("Xthis is some text")) + failCount++; + + pattern = Pattern.compile("^", Pattern.MULTILINE | Pattern.UNIX_LINES); + matcher = pattern.matcher("this is some text\n"); + result = matcher.replaceAll("X"); + if (!result.equals("Xthis is some text\n")) + failCount++; + + report("Caret"); + } + + private static void groupCaptureTest() throws Exception { + // Independent group + Pattern pattern = Pattern.compile("x+(?>y+)z+"); + Matcher matcher = pattern.matcher("xxxyyyzzz"); + matcher.find(); + try { + String blah = matcher.group(1); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Good result + } + // Pure group + pattern = Pattern.compile("x+(?:y+)z+"); + matcher = pattern.matcher("xxxyyyzzz"); + matcher.find(); + try { + String blah = matcher.group(1); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Good result + } + + // Supplementary character tests + // Independent group + pattern = Pattern.compile(toSupplementaries("x+(?>y+)z+")); + matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); + matcher.find(); + try { + String blah = matcher.group(1); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Good result + } + // Pure group + pattern = Pattern.compile(toSupplementaries("x+(?:y+)z+")); + matcher = pattern.matcher(toSupplementaries("xxxyyyzzz")); + matcher.find(); + try { + String blah = matcher.group(1); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Good result + } + + report("GroupCapture"); + } + + private static void backRefTest() throws Exception { + Pattern pattern = Pattern.compile("(a*)bc\\1"); + check(pattern, "zzzaabcazzz", true); + + pattern = Pattern.compile("(a*)bc\\1"); + check(pattern, "zzzaabcaazzz", true); + + pattern = Pattern.compile("(abc)(def)\\1"); + check(pattern, "abcdefabc", true); + + pattern = Pattern.compile("(abc)(def)\\3"); + check(pattern, "abcdefabc", false); + + try { + for (int i = 1; i < 10; i++) { + // Make sure backref 1-9 are always accepted + pattern = Pattern.compile("abcdef\\" + i); + // and fail to match if the target group does not exit + check(pattern, "abcdef", false); + } + } catch(PatternSyntaxException e) { + failCount++; + } + + pattern = Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\\11"); + check(pattern, "abcdefghija", false); + check(pattern, "abcdefghija1", true); + + pattern = Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11"); + check(pattern, "abcdefghijkk", true); + + pattern = Pattern.compile("(a)bcdefghij\\11"); + check(pattern, "abcdefghija1", true); + + // Supplementary character tests + pattern = Pattern.compile(toSupplementaries("(a*)bc\\1")); + check(pattern, toSupplementaries("zzzaabcazzz"), true); + + pattern = Pattern.compile(toSupplementaries("(a*)bc\\1")); + check(pattern, toSupplementaries("zzzaabcaazzz"), true); + + pattern = Pattern.compile(toSupplementaries("(abc)(def)\\1")); + check(pattern, toSupplementaries("abcdefabc"), true); + + pattern = Pattern.compile(toSupplementaries("(abc)(def)\\3")); + check(pattern, toSupplementaries("abcdefabc"), false); + + pattern = Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\\11")); + check(pattern, toSupplementaries("abcdefghija"), false); + check(pattern, toSupplementaries("abcdefghija1"), true); + + pattern = Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\\11")); + check(pattern, toSupplementaries("abcdefghijkk"), true); + + report("BackRef"); + } + + /** + * Unicode Technical Report #18, section 2.6 End of Line + * There is no empty line to be matched in the sequence \u000D\u000A + * but there is an empty line in the sequence \u000A\u000D. + */ + private static void anchorTest() throws Exception { + Pattern p = Pattern.compile("^.*$", Pattern.MULTILINE); + Matcher m = p.matcher("blah1\r\nblah2"); + m.find(); + m.find(); + if (!m.group().equals("blah2")) + failCount++; + + m.reset("blah1\n\rblah2"); + m.find(); + m.find(); + m.find(); + if (!m.group().equals("blah2")) + failCount++; + + // Test behavior of $ with \r\n at end of input + p = Pattern.compile(".+$"); + m = p.matcher("blah1\r\n"); + if (!m.find()) + failCount++; + if (!m.group().equals("blah1")) + failCount++; + if (m.find()) + failCount++; + + // Test behavior of $ with \r\n at end of input in multiline + p = Pattern.compile(".+$", Pattern.MULTILINE); + m = p.matcher("blah1\r\n"); + if (!m.find()) + failCount++; + if (m.find()) + failCount++; + + // Test for $ recognition of \u0085 for bug 4527731 + p = Pattern.compile(".+$", Pattern.MULTILINE); + m = p.matcher("blah1\u0085"); + if (!m.find()) + failCount++; + + // Supplementary character test + p = Pattern.compile("^.*$", Pattern.MULTILINE); + m = p.matcher(toSupplementaries("blah1\r\nblah2")); + m.find(); + m.find(); + if (!m.group().equals(toSupplementaries("blah2"))) + failCount++; + + m.reset(toSupplementaries("blah1\n\rblah2")); + m.find(); + m.find(); + m.find(); + if (!m.group().equals(toSupplementaries("blah2"))) + failCount++; + + // Test behavior of $ with \r\n at end of input + p = Pattern.compile(".+$"); + m = p.matcher(toSupplementaries("blah1\r\n")); + if (!m.find()) + failCount++; + if (!m.group().equals(toSupplementaries("blah1"))) + failCount++; + if (m.find()) + failCount++; + + // Test behavior of $ with \r\n at end of input in multiline + p = Pattern.compile(".+$", Pattern.MULTILINE); + m = p.matcher(toSupplementaries("blah1\r\n")); + if (!m.find()) + failCount++; + if (m.find()) + failCount++; + + // Test for $ recognition of \u0085 for bug 4527731 + p = Pattern.compile(".+$", Pattern.MULTILINE); + m = p.matcher(toSupplementaries("blah1\u0085")); + if (!m.find()) + failCount++; + + report("Anchors"); + } + + /** + * A basic sanity test of Matcher.lookingAt(). + */ + private static void lookingAtTest() throws Exception { + Pattern p = Pattern.compile("(ab)(c*)"); + Matcher m = p.matcher("abccczzzabcczzzabccc"); + + if (!m.lookingAt()) + failCount++; + + if (!m.group().equals(m.group(0))) + failCount++; + + m = p.matcher("zzzabccczzzabcczzzabccczzz"); + if (m.lookingAt()) + failCount++; + + // Supplementary character test + p = Pattern.compile(toSupplementaries("(ab)(c*)")); + m = p.matcher(toSupplementaries("abccczzzabcczzzabccc")); + + if (!m.lookingAt()) + failCount++; + + if (!m.group().equals(m.group(0))) + failCount++; + + m = p.matcher(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + if (m.lookingAt()) + failCount++; + + report("Looking At"); + } + + /** + * A basic sanity test of Matcher.matches(). + */ + private static void matchesTest() throws Exception { + // matches() + Pattern p = Pattern.compile("ulb(c*)"); + Matcher m = p.matcher("ulbcccccc"); + if (!m.matches()) + failCount++; + + // find() but not matches() + m.reset("zzzulbcccccc"); + if (m.matches()) + failCount++; + + // lookingAt() but not matches() + m.reset("ulbccccccdef"); + if (m.matches()) + failCount++; + + // matches() + p = Pattern.compile("a|ad"); + m = p.matcher("ad"); + if (!m.matches()) + failCount++; + + // Supplementary character test + // matches() + p = Pattern.compile(toSupplementaries("ulb(c*)")); + m = p.matcher(toSupplementaries("ulbcccccc")); + if (!m.matches()) + failCount++; + + // find() but not matches() + m.reset(toSupplementaries("zzzulbcccccc")); + if (m.matches()) + failCount++; + + // lookingAt() but not matches() + m.reset(toSupplementaries("ulbccccccdef")); + if (m.matches()) + failCount++; + + // matches() + p = Pattern.compile(toSupplementaries("a|ad")); + m = p.matcher(toSupplementaries("ad")); + if (!m.matches()) + failCount++; + + report("Matches"); + } + + /** + * A basic sanity test of Pattern.matches(). + */ + private static void patternMatchesTest() throws Exception { + // matches() + if (!Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbcccccc"))) + failCount++; + + // find() but not matches() + if (Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("zzzulbcccccc"))) + failCount++; + + // lookingAt() but not matches() + if (Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbccccccdef"))) + failCount++; + + // Supplementary character test + // matches() + if (!Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbcccccc"))) + failCount++; + + // find() but not matches() + if (Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("zzzulbcccccc"))) + failCount++; + + // lookingAt() but not matches() + if (Pattern.matches(toSupplementaries("ulb(c*)"), + toSupplementaries("ulbccccccdef"))) + failCount++; + + report("Pattern Matches"); + } + + /** + * Canonical equivalence testing. Tests the ability of the engine + * to match sequences that are not explicitly specified in the + * pattern when they are considered equivalent by the Unicode Standard. + */ + private static void ceTest() throws Exception { + // Decomposed char outside char classes + Pattern p = Pattern.compile("testa\u030a", Pattern.CANON_EQ); + Matcher m = p.matcher("test\u00e5"); + if (!m.matches()) + failCount++; + + m.reset("testa\u030a"); + if (!m.matches()) + failCount++; + + // Composed char outside char classes + p = Pattern.compile("test\u00e5", Pattern.CANON_EQ); + m = p.matcher("test\u00e5"); + if (!m.matches()) + failCount++; + + m.reset("testa\u030a"); + if (!m.find()) + failCount++; + + // Decomposed char inside a char class + p = Pattern.compile("test[abca\u030a]", Pattern.CANON_EQ); + m = p.matcher("test\u00e5"); + if (!m.find()) + failCount++; + + m.reset("testa\u030a"); + if (!m.find()) + failCount++; + + // Composed char inside a char class + p = Pattern.compile("test[abc\u00e5def\u00e0]", Pattern.CANON_EQ); + m = p.matcher("test\u00e5"); + if (!m.find()) + failCount++; + + m.reset("testa\u0300"); + if (!m.find()) + failCount++; + + m.reset("testa\u030a"); + if (!m.find()) + failCount++; + + // Marks that cannot legally change order and be equivalent + p = Pattern.compile("testa\u0308\u0300", Pattern.CANON_EQ); + check(p, "testa\u0308\u0300", true); + check(p, "testa\u0300\u0308", false); + + // Marks that can legally change order and be equivalent + p = Pattern.compile("testa\u0308\u0323", Pattern.CANON_EQ); + check(p, "testa\u0308\u0323", true); + check(p, "testa\u0323\u0308", true); + + // Test all equivalences of the sequence a\u0308\u0323\u0300 + p = Pattern.compile("testa\u0308\u0323\u0300", Pattern.CANON_EQ); + check(p, "testa\u0308\u0323\u0300", true); + check(p, "testa\u0323\u0308\u0300", true); + check(p, "testa\u0308\u0300\u0323", true); + check(p, "test\u00e4\u0323\u0300", true); + check(p, "test\u00e4\u0300\u0323", true); + + /* + * The following canonical equivalence tests don't work. Bug id: 4916384. + * + // Decomposed hangul (jamos) + p = Pattern.compile("\u1100\u1161", Pattern.CANON_EQ); + m = p.matcher("\u1100\u1161"); + if (!m.matches()) + failCount++; + + m.reset("\uac00"); + if (!m.matches()) + failCount++; + + // Composed hangul + p = Pattern.compile("\uac00", Pattern.CANON_EQ); + m = p.matcher("\u1100\u1161"); + if (!m.matches()) + failCount++; + + m.reset("\uac00"); + if (!m.matches()) + failCount++; + + // Decomposed supplementary outside char classes + p = Pattern.compile("test\ud834\uddbc\ud834\udd6f", Pattern.CANON_EQ); + m = p.matcher("test\ud834\uddc0"); + if (!m.matches()) + failCount++; + + m.reset("test\ud834\uddbc\ud834\udd6f"); + if (!m.matches()) + failCount++; + + // Composed supplementary outside char classes + p = Pattern.compile("test\ud834\uddc0", Pattern.CANON_EQ); + m.reset("test\ud834\uddbc\ud834\udd6f"); + if (!m.matches()) + failCount++; + + m = p.matcher("test\ud834\uddc0"); + if (!m.matches()) + failCount++; + + */ + + report("Canonical Equivalence"); + } + + /** + * A basic sanity test of Matcher.replaceAll(). + */ + private static void globalSubstitute() throws Exception { + // Global substitution with a literal + Pattern p = Pattern.compile("(ab)(c*)"); + Matcher m = p.matcher("abccczzzabcczzzabccc"); + if (!m.replaceAll("test").equals("testzzztestzzztest")) + failCount++; + + m.reset("zzzabccczzzabcczzzabccczzz"); + if (!m.replaceAll("test").equals("zzztestzzztestzzztestzzz")) + failCount++; + + // Global substitution with groups + m.reset("zzzabccczzzabcczzzabccczzz"); + String result = m.replaceAll("$1"); + if (!result.equals("zzzabzzzabzzzabzzz")) + failCount++; + + // Supplementary character test + // Global substitution with a literal + p = Pattern.compile(toSupplementaries("(ab)(c*)")); + m = p.matcher(toSupplementaries("abccczzzabcczzzabccc")); + if (!m.replaceAll(toSupplementaries("test")). + equals(toSupplementaries("testzzztestzzztest"))) + failCount++; + + m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + if (!m.replaceAll(toSupplementaries("test")). + equals(toSupplementaries("zzztestzzztestzzztestzzz"))) + failCount++; + + // Global substitution with groups + m.reset(toSupplementaries("zzzabccczzzabcczzzabccczzz")); + result = m.replaceAll("$1"); + if (!result.equals(toSupplementaries("zzzabzzzabzzzabzzz"))) + failCount++; + + report("Global Substitution"); + } + + /** + * Tests the usage of Matcher.appendReplacement() with literal + * and group substitutions. + */ + private static void stringbufferSubstitute() throws Exception { + // SB substitution with literal + String blah = "zzzblahzzz"; + Pattern p = Pattern.compile("blah"); + Matcher m = p.matcher(blah); + StringBuffer result = new StringBuffer(); + try { + m.appendReplacement(result, "blech"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "blech"); + if (!result.toString().equals("zzzblech")) + failCount++; + + m.appendTail(result); + if (!result.toString().equals("zzzblechzzz")) + failCount++; + + // SB substitution with groups + blah = "zzzabcdzzz"; + p = Pattern.compile("(ab)(cd)*"); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, "$1"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "$1"); + if (!result.toString().equals("zzzab")) + failCount++; + + m.appendTail(result); + if (!result.toString().equals("zzzabzzz")) + failCount++; + + // SB substitution with 3 groups + blah = "zzzabcdcdefzzz"; + p = Pattern.compile("(ab)(cd)*(ef)"); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, "$1w$2w$3"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "$1w$2w$3"); + if (!result.toString().equals("zzzabwcdwef")) + failCount++; + + m.appendTail(result); + if (!result.toString().equals("zzzabwcdwefzzz")) + failCount++; + + // SB substitution with groups and three matches + // skipping middle match + blah = "zzzabcdzzzabcddzzzabcdzzz"; + p = Pattern.compile("(ab)(cd*)"); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, "$1"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "$1"); + if (!result.toString().equals("zzzab")) + failCount++; + + m.find(); + m.find(); + m.appendReplacement(result, "$2"); + if (!result.toString().equals("zzzabzzzabcddzzzcd")) + failCount++; + + m.appendTail(result); + if (!result.toString().equals("zzzabzzzabcddzzzcdzzz")) + failCount++; + + // Check to make sure escaped $ is ignored + blah = "zzzabcdcdefzzz"; + p = Pattern.compile("(ab)(cd)*(ef)"); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, "$1w\\$2w$3"); + if (!result.toString().equals("zzzabw$2wef")) + failCount++; + + m.appendTail(result); + if (!result.toString().equals("zzzabw$2wefzzz")) + failCount++; + + // Check to make sure a reference to nonexistent group causes error + blah = "zzzabcdcdefzzz"; + p = Pattern.compile("(ab)(cd)*(ef)"); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + try { + m.appendReplacement(result, "$1w$5w$3"); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Correct result + } + + // Check double digit group references + blah = "zzz123456789101112zzz"; + p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, "$1w$11w$3"); + if (!result.toString().equals("zzz1w11w3")) + failCount++; + + // Check to make sure it backs off $15 to $1 if only three groups + blah = "zzzabcdcdefzzz"; + p = Pattern.compile("(ab)(cd)*(ef)"); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, "$1w$15w$3"); + if (!result.toString().equals("zzzabwab5wef")) + failCount++; + + + // Supplementary character test + // SB substitution with literal + blah = toSupplementaries("zzzblahzzz"); + p = Pattern.compile(toSupplementaries("blah")); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, toSupplementaries("blech")); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, toSupplementaries("blech")); + if (!result.toString().equals(toSupplementaries("zzzblech"))) + failCount++; + + m.appendTail(result); + if (!result.toString().equals(toSupplementaries("zzzblechzzz"))) + failCount++; + + // SB substitution with groups + blah = toSupplementaries("zzzabcdzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd)*")); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, "$1"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "$1"); + if (!result.toString().equals(toSupplementaries("zzzab"))) + failCount++; + + m.appendTail(result); + if (!result.toString().equals(toSupplementaries("zzzabzzz"))) + failCount++; + + // SB substitution with 3 groups + blah = toSupplementaries("zzzabcdcdefzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, toSupplementaries("$1w$2w$3")); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, toSupplementaries("$1w$2w$3")); + if (!result.toString().equals(toSupplementaries("zzzabwcdwef"))) + failCount++; + + m.appendTail(result); + if (!result.toString().equals(toSupplementaries("zzzabwcdwefzzz"))) + failCount++; + + // SB substitution with groups and three matches + // skipping middle match + blah = toSupplementaries("zzzabcdzzzabcddzzzabcdzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd*)")); + m = p.matcher(blah); + result = new StringBuffer(); + try { + m.appendReplacement(result, "$1"); + failCount++; + } catch (IllegalStateException e) { + } + m.find(); + m.appendReplacement(result, "$1"); + if (!result.toString().equals(toSupplementaries("zzzab"))) + failCount++; + + m.find(); + m.find(); + m.appendReplacement(result, "$2"); + if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcd"))) + failCount++; + + m.appendTail(result); + if (!result.toString().equals(toSupplementaries("zzzabzzzabcddzzzcdzzz"))) + failCount++; + + // Check to make sure escaped $ is ignored + blah = toSupplementaries("zzzabcdcdefzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, toSupplementaries("$1w\\$2w$3")); + if (!result.toString().equals(toSupplementaries("zzzabw$2wef"))) + failCount++; + + m.appendTail(result); + if (!result.toString().equals(toSupplementaries("zzzabw$2wefzzz"))) + failCount++; + + // Check to make sure a reference to nonexistent group causes error + blah = toSupplementaries("zzzabcdcdefzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + try { + m.appendReplacement(result, toSupplementaries("$1w$5w$3")); + failCount++; + } catch (IndexOutOfBoundsException ioobe) { + // Correct result + } + + // Check double digit group references + blah = toSupplementaries("zzz123456789101112zzz"); + p = Pattern.compile("(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)"); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, toSupplementaries("$1w$11w$3")); + if (!result.toString().equals(toSupplementaries("zzz1w11w3"))) + failCount++; + + // Check to make sure it backs off $15 to $1 if only three groups + blah = toSupplementaries("zzzabcdcdefzzz"); + p = Pattern.compile(toSupplementaries("(ab)(cd)*(ef)")); + m = p.matcher(blah); + result = new StringBuffer(); + m.find(); + m.appendReplacement(result, toSupplementaries("$1w$15w$3")); + if (!result.toString().equals(toSupplementaries("zzzabwab5wef"))) + failCount++; + + // Check nothing has been appended into the output buffer if + // the replacement string triggers IllegalArgumentException. + p = Pattern.compile("(abc)"); + m = p.matcher("abcd"); + result = new StringBuffer(); + m.find(); + try { + m.appendReplacement(result, ("xyz$g")); + failCount++; + } catch (IllegalArgumentException iae) { + if (result.length() != 0) + failCount++; + } + + report("SB Substitution"); + } + + /* + * 5 groups of characters are created to make a substitution string. + * A base string will be created including random lead chars, the + * substitution string, and random trailing chars. + * A pattern containing the 5 groups is searched for and replaced with: + * random group + random string + random group. + * The results are checked for correctness. + */ + private static void substitutionBasher() { + for (int runs = 0; runs<1000; runs++) { + // Create a base string to work in + int leadingChars = generator.nextInt(10); + StringBuffer baseBuffer = new StringBuffer(100); + String leadingString = getRandomAlphaString(leadingChars); + baseBuffer.append(leadingString); + + // Create 5 groups of random number of random chars + // Create the string to substitute + // Create the pattern string to search for + StringBuffer bufferToSub = new StringBuffer(25); + StringBuffer bufferToPat = new StringBuffer(50); + String[] groups = new String[5]; + for(int i=0; i<5; i++) { + int aGroupSize = generator.nextInt(5)+1; + groups[i] = getRandomAlphaString(aGroupSize); + bufferToSub.append(groups[i]); + bufferToPat.append('('); + bufferToPat.append(groups[i]); + bufferToPat.append(')'); + } + String stringToSub = bufferToSub.toString(); + String pattern = bufferToPat.toString(); + + // Place sub string into working string at random index + baseBuffer.append(stringToSub); + + // Append random chars to end + int trailingChars = generator.nextInt(10); + String trailingString = getRandomAlphaString(trailingChars); + baseBuffer.append(trailingString); + String baseString = baseBuffer.toString(); + + // Create test pattern and matcher + Pattern p = Pattern.compile(pattern); + Matcher m = p.matcher(baseString); + + // Reject candidate if pattern happens to start early + m.find(); + if (m.start() < leadingChars) + continue; + + // Reject candidate if more than one match + if (m.find()) + continue; + + // Construct a replacement string with : + // random group + random string + random group + StringBuffer bufferToRep = new StringBuffer(); + int groupIndex1 = generator.nextInt(5); + bufferToRep.append("$" + (groupIndex1 + 1)); + String randomMidString = getRandomAlphaString(5); + bufferToRep.append(randomMidString); + int groupIndex2 = generator.nextInt(5); + bufferToRep.append("$" + (groupIndex2 + 1)); + String replacement = bufferToRep.toString(); + + // Do the replacement + String result = m.replaceAll(replacement); + + // Construct expected result + StringBuffer bufferToRes = new StringBuffer(); + bufferToRes.append(leadingString); + bufferToRes.append(groups[groupIndex1]); + bufferToRes.append(randomMidString); + bufferToRes.append(groups[groupIndex2]); + bufferToRes.append(trailingString); + String expectedResult = bufferToRes.toString(); + + // Check results + if (!result.equals(expectedResult)) + failCount++; + } + + report("Substitution Basher"); + } + + /** + * Checks the handling of some escape sequences that the Pattern + * class should process instead of the java compiler. These are + * not in the file because the escapes should be be processed + * by the Pattern class when the regex is compiled. + */ + private static void escapes() throws Exception { + Pattern p = Pattern.compile("\\043"); + Matcher m = p.matcher("#"); + if (!m.find()) + failCount++; + + p = Pattern.compile("\\x23"); + m = p.matcher("#"); + if (!m.find()) + failCount++; + + p = Pattern.compile("\\u0023"); + m = p.matcher("#"); + if (!m.find()) + failCount++; + + report("Escape sequences"); + } + + /** + * Checks the handling of blank input situations. These + * tests are incompatible with my test file format. + */ + private static void blankInput() throws Exception { + Pattern p = Pattern.compile("abc", Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(""); + if (m.find()) + failCount++; + + p = Pattern.compile("a*", Pattern.CASE_INSENSITIVE); + m = p.matcher(""); + if (!m.find()) + failCount++; + + p = Pattern.compile("abc"); + m = p.matcher(""); + if (m.find()) + failCount++; + + p = Pattern.compile("a*"); + m = p.matcher(""); + if (!m.find()) + failCount++; + + report("Blank input"); + } + + /** + * Tests the Boyer-Moore pattern matching of a character sequence + * on randomly generated patterns. + */ + private static void bm() throws Exception { + doBnM('a'); + report("Boyer Moore (ASCII)"); + + doBnM(Character.MIN_SUPPLEMENTARY_CODE_POINT - 10); + report("Boyer Moore (Supplementary)"); + } + + private static void doBnM(int baseCharacter) throws Exception { + int achar=0; + + for (int i=0; i<100; i++) { + // Create a short pattern to search for + int patternLength = generator.nextInt(7) + 4; + StringBuffer patternBuffer = new StringBuffer(patternLength); + for (int x=0; xy+)z+"), + "xxxyyyzzz", + "gname", + "yyy"); + + //backref + Pattern pattern = Pattern.compile("(a*)bc\\1"); + check(pattern, "zzzaabcazzz", true); // found "abca" + + check(Pattern.compile("(?a*)bc\\k"), + "zzzaabcaazzz", true); + + check(Pattern.compile("(?abc)(def)\\k"), + "abcdefabc", true); + + check(Pattern.compile("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(?k)\\k"), + "abcdefghijkk", true); + + // Supplementary character tests + check(Pattern.compile("(?" + toSupplementaries("a*)bc") + "\\k"), + toSupplementaries("zzzaabcazzz"), true); + + check(Pattern.compile("(?" + toSupplementaries("a*)bc") + "\\k"), + toSupplementaries("zzzaabcaazzz"), true); + + check(Pattern.compile("(?" + toSupplementaries("abc)(def)") + "\\k"), + toSupplementaries("abcdefabc"), true); + + check(Pattern.compile(toSupplementaries("(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)") + + "(?" + + toSupplementaries("k)") + "\\k"), + toSupplementaries("abcdefghijkk"), true); + + check(Pattern.compile("x+(?y+)z+\\k"), + "xxxyyyzzzyyy", + "gname", + "yyy"); + + //replaceFirst/All + checkReplaceFirst("(?ab)(c*)", + "abccczzzabcczzzabccc", + "$", + "abzzzabcczzzabccc"); + + checkReplaceAll("(?ab)(c*)", + "abccczzzabcczzzabccc", + "$", + "abzzzabzzzab"); + + + checkReplaceFirst("(?ab)(c*)", + "zzzabccczzzabcczzzabccczzz", + "$", + "zzzabzzzabcczzzabccczzz"); + + checkReplaceAll("(?ab)(c*)", + "zzzabccczzzabcczzzabccczzz", + "$", + "zzzabzzzabzzzabzzz"); + + checkReplaceFirst("(?ab)(?c*)", + "zzzabccczzzabcczzzabccczzz", + "$", + "zzzccczzzabcczzzabccczzz"); + + checkReplaceAll("(?ab)(?c*)", + "zzzabccczzzabcczzzabccczzz", + "$", + "zzzccczzzcczzzccczzz"); + + //toSupplementaries("(ab)(c*)")); + checkReplaceFirst("(?" + toSupplementaries("ab") + + ")(?" + toSupplementaries("c") + "*)", + toSupplementaries("abccczzzabcczzzabccc"), + "$", + toSupplementaries("abzzzabcczzzabccc")); + + + checkReplaceAll("(?" + toSupplementaries("ab") + + ")(?" + toSupplementaries("c") + "*)", + toSupplementaries("abccczzzabcczzzabccc"), + "$", + toSupplementaries("abzzzabzzzab")); + + checkReplaceFirst("(?" + toSupplementaries("ab") + + ")(?" + toSupplementaries("c") + "*)", + toSupplementaries("abccczzzabcczzzabccc"), + "$", + toSupplementaries("ccczzzabcczzzabccc")); + + + checkReplaceAll("(?" + toSupplementaries("ab") + + ")(?" + toSupplementaries("c") + "*)", + toSupplementaries("abccczzzabcczzzabccc"), + "$", + toSupplementaries("ccczzzcczzzccc")); + + checkReplaceFirst("(?Dog)AndCat", + "zzzDogAndCatzzzDogAndCatzzz", + "$", + "zzzDogzzzDogAndCatzzz"); + + + checkReplaceAll("(?Dog)AndCat", + "zzzDogAndCatzzzDogAndCatzzz", + "$", + "zzzDogzzzDogzzz"); + + // backref in Matcher & String + if (!"abcdefghij".replaceFirst("cd(?ef)gh", "$").equals("abefij") || + !"abbbcbdbefgh".replaceAll("(?[a-e])b", "$").equals("abcdefgh")) + failCount++; + + // negative + checkExpectedFail("(?abc)(def)"); + checkExpectedFail("(?abc)(def)"); + checkExpectedFail("(?abc)(def)\\k"); + checkExpectedFail("(?abc)(?def)\\k"); + checkExpectedFail(Pattern.compile("(?abc)(def)").matcher("abcdef"), + "gnameX"); + checkExpectedFail(Pattern.compile("(?abc)(def)").matcher("abcdef"), + null); + report("NamedGroupCapture"); + } +} diff --git a/jdk/test/java/util/regex/SupplementaryTestCases.txt b/jdk/test/java/util/regex/SupplementaryTestCases.txt new file mode 100644 index 00000000000..2f05d4fed46 --- /dev/null +++ b/jdk/test/java/util/regex/SupplementaryTestCases.txt @@ -0,0 +1,1434 @@ +// +// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// +// -------------------------------------------------------- +// This file contains test cases with supplementary characters for regular expressions. +// A test case consists of three lines: +// The first line is a pattern used in the test +// The second line is the input to search for the pattern in +// The third line is a concatentation of the match, the number of groups, +// and the contents of the first four subexpressions. +// Empty lines and lines beginning with comment slashes are ignored. + +// Test unsetting of backed off groups +^(\ud800\udc61)?\ud800\udc61 +\ud800\udc61 +true \ud800\udc61 1 + +^(\ud800\udc61\ud800)?\ud800\udc61\ud800 +\ud800\udc61\ud800 +true \ud800\udc61\ud800 1 + +^(\ud800\udc61\ud800\udc61(\ud800\udc62\ud800\udc62)?)+$ +\ud800\udc61\ud800\udc61\ud800\udc62\ud800\udc62\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61\ud800\udc62\ud800\udc62\ud800\udc61\ud800\udc61 2 \ud800\udc61\ud800\udc61 \ud800\udc62\ud800\udc62 + +^(\ud800\udc61\ud800\udc61\ud800(\ud800\udc62\ud800\udc62\ud800)?)+$ +\ud800\udc61\ud800\udc61\ud800\ud800\udc62\ud800\udc62\ud800\ud800\udc61\ud800\udc61\ud800 +true \ud800\udc61\ud800\udc61\ud800\ud800\udc62\ud800\udc62\ud800\ud800\udc61\ud800\udc61\ud800 2 \ud800\udc61\ud800\udc61\ud800 \ud800\udc62\ud800\udc62\ud800 + +((\ud800\udc61|\ud800\udc62)?\ud800\udc62)+ +\ud800\udc62 +true \ud800\udc62 2 \ud800\udc62 + +((\ud800|\ud800\udc62)?\ud800\udc62)+ +\ud800\udc62 +true \ud800\udc62 2 \ud800\udc62 + +(\ud800\udc61\ud800\udc61\ud800\udc61)?\ud800\udc61\ud800\udc61\ud800\udc61 +\ud800\udc61\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61\ud800\udc61 1 + +(\ud800\udc61\ud800\udc61\ud800\ud800\udc61)?\ud800\udc61\ud800\udc61\ud800\ud800\udc61 +\ud800\udc61\ud800\udc61\ud800\ud800\udc61 +true \ud800\udc61\ud800\udc61\ud800\ud800\udc61 1 + +^(\ud800\udc61\ud800(\ud800\udc62\ud800)?)+$ +\ud800\udc61\ud800\ud800\udc62\ud800\ud800\udc61\ud800 +true \ud800\udc61\ud800\ud800\udc62\ud800\ud800\udc61\ud800 2 \ud800\udc61\ud800 \ud800\udc62\ud800 + +^(\ud800\udc61(\ud800\udc62)?)+$ +\ud800\udc61\ud800\udc62\ud800\udc61 +true \ud800\udc61\ud800\udc62\ud800\udc61 2 \ud800\udc61 \ud800\udc62 + +^(\ud800\udc61\ud800(\ud800\udc62\ud800)?)+$ +\ud800\udc61\ud800\ud800\udc62\ud800\ud800\udc61\ud800 +true \ud800\udc61\ud800\ud800\udc62\ud800\ud800\udc61\ud800 2 \ud800\udc61\ud800 \ud800\udc62\ud800 + +^(\ud800\udc61(\ud800\udc62(\ud800\udc63)?)?)?\ud800\udc61\ud800\udc62\ud800\udc63 +\ud800\udc61\ud800\udc62\ud800\udc63 +true \ud800\udc61\ud800\udc62\ud800\udc63 3 + +^(\ud800\udc61\ud800(\ud800\udc62(\ud800\udc63)?)?)?\ud800\udc61\ud800\ud800\udc62\ud800\udc63 +\ud800\udc61\ud800\ud800\udc62\ud800\udc63 +true \ud800\udc61\ud800\ud800\udc62\ud800\udc63 3 + +^(\ud800\udc61(\ud800\udc02(\ud800\udc63))).* +\ud800\udc61\ud800\udc02\ud800\udc63 +true \ud800\udc61\ud800\udc02\ud800\udc63 3 \ud800\udc61\ud800\udc02\ud800\udc63 \ud800\udc02\ud800\udc63 \ud800\udc63 + +^(\ud800\udc61(\ud800(\ud800\udc63))).* +\ud800\udc61\ud800\ud800\udc63 +true \ud800\udc61\ud800\ud800\udc63 3 \ud800\udc61\ud800\ud800\udc63 \ud800\ud800\udc63 \ud800\udc63 + +// Patterns including no surrogates +(.)([^a])xyz +\ud801\ud800\udc00xyz +true \ud801\ud800\udc00xyz 2 \ud801 \ud800\udc00 + +[^a-z].. +\ud801\ud800\udc00xyz +true \ud801\ud800\udc00x 0 + +.$ +\ud801\ud800\udc00 +true \ud800\udc00 0 + +.$ +\ud801\udc01\ud800\udc00 +true \ud800\udc00 0 + +.$ +\ud801\udc01\ud800\udc00\udcff +true \udcff 0 + +[^x-\uffff][^y-\uffff] +\ud800\udc00pqr +true \ud800\udc00p 0 + +[^x-\uffff]+ +\ud800\udc00pqrx +true \ud800\udc00pqr 0 + +/// The following test cases fail due to use of Start rather than +/// StartS. Disabled for now. +///[a-\uffff] +///\ud800\udc00x +///true x 0 +/// +///[a-\uffff] +///\ud800\udc00 +///false 0 + +// use of x modifier +\ud800\udc61bc(?x)bl\ud800\udc61h +\ud800\udc61bcbl\ud800\udc61h +true \ud800\udc61bcbl\ud800\udc61h 0 + +\ud800\udc61bc(?x) bl\ud800\udc61h +\ud800\udc61bcbl\ud800\udc61h +true \ud800\udc61bcbl\ud800\udc61h 0 + +\ud800\udc61bc(?x) bl\ud800\udc61h blech +\ud800\udc61bcbl\ud800\udc61hblech +true \ud800\udc61bcbl\ud800\udc61hblech 0 + +\ud800\udc61bc(?x) bl\ud800\udc61h # ignore comment +\ud800\udc61bcbl\ud800\udc61h +true \ud800\udc61bcbl\ud800\udc61h 0 + +// Simple alternation +\ud800\udc61|\ud800\udc62 +\ud800\udc61 +true \ud800\udc61 0 + +\ud800\udc61|\ud800\udc62|\ud800 +\ud800\udc61 +true \ud800\udc61 0 + +\ud800\udc61|\ud800 +\ud800\udc62 +false 0 + +\ud800\udc62|\ud800 +\ud800 +true \ud800 0 + +\ud800\udc61|\ud802\udc02 +z +false 0 + +\ud800\udc61|\ud802\udc02 +\ud802\udc02 +true \ud802\udc02 0 + +\ud800\udc61|\ud802\udc02|\ud803\udc03\ud804\udc04 +\ud803\udc03\ud804\udc04 +true \ud803\udc03\ud804\udc04 0 + +\ud800\udc61|\ud800\udc61d +\ud800\udc61d +true \ud800\udc61 0 + +z(\ud800\udc61|\ud800\udc61c)\ud802\udc02 +z\ud800\udc61c\ud802\udc02 +true z\ud800\udc61c\ud802\udc02 1 \ud800\udc61c + +z(\ud800\udc61|\ud800\udc61c|\udc61c)\ud802\udc02 +z\udc61c\ud802\udc02 +true z\udc61c\ud802\udc02 1 \udc61c + +// Simple codepoint class +[\ud800\udc61\ud802\udc02c]+ +\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 +true \ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 0 + +[\ud800\udc61\ud802\udc02c]+ +\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 +true \ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 0 + +[\ud800\udc61\ud802\udc02c\ud800]+ +\ud800\udc61\ud802\udc02\ud800\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 +true \ud800\udc61\ud802\udc02\ud800\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 0 + +[\ud800\udc61bc]+ +d\ud800\udc62fg +false 0 + +[\ud800\udc61bc]+[\ud804\udc04ef]+[\ud807\udc07hi]+ +zzz\ud800\udc61\ud800\udc61\ud804\udc04\ud804\udc04\ud807\udc07\ud807\udc07zzz +true \ud800\udc61\ud800\udc61\ud804\udc04\ud804\udc04\ud807\udc07\ud807\udc07 0 + +// Range codepoint class +[\ud801\udc01-\ud807\udc07]+ +\ud8ff\udcff\ud8ff\udcff\ud8ff\udcff\ud807\udc07\ud807\udc07\ud807\udc07 +true \ud807\udc07\ud807\udc07\ud807\udc07 0 + +[\ud801\udc01-\ud807\udc07]+ +mmm +false 0 + +[\ud800\udc61-]+ +z\ud800\udc61-9z +true \ud800\udc61- 0 + +// Negated char class +[^\ud800\udc61\ud802\udc02c]+ +\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02\ud800\udc61\ud802\udc02 +false 0 + +[^\ud800\udc61\ud802\udc02\ud803\udc03]+ +\ud800\udc61\ud800\udc61\ud800\udc61\ud802\udc02\ud802\udc02\ud802\udc02\ud803\udc03\ud803\udc03\ud803\udc03\ud804\udc04efg +true \ud804\udc04efg 0 + +[^\ud800\udc61\ud802\udc02\ud803\udc03\ud800]+ +\ud800\udc61\ud800\udc61\ud800\udc61\ud802\udc02\ud802\udc02\ud802\udc02\ud803\udc03\ud803\udc03\ud803\udc03\ud804\udc04efg +true \ud804\udc04efg 0 + +// Making sure a ^ not in first position matches literal ^ +[\ud801\udc01\ud802\udc02\ud803\udc03^\ud802\udc02] +\ud802\udc02 +true \ud802\udc02 0 + +[\ud801\udc01\ud802\udc02\ud803\udc03^\ud802\udc02] +^ +true ^ 0 + +// Class union and intersection +[\ud801\udc01\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]] +\ud802\udc02 +true \ud802\udc02 0 + +[\ud800\udc61\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]] +\ud805\udc05 +true \ud805\udc05 0 + +[\ud801\udc01-\ud804\udc04[0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud801\udc01 +true \ud801\udc01 0 + +[\ud801\udc01-\ud804\udc04[0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud80c\udc0c +true \ud80c\udc0c 0 + +[\ud801\udc01-\ud804\udc04[0-9][\ud80b\udc0b-\ud80d\udc0d]] +4 +true 4 0 + +[\ud801\udc01-\ud804\udc04[0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud805\udc05 +false 0 + +[\ud801\udc01-\ud804\udc04[0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud816\udc16 +false 0 + +[[\ud801\udc01-\ud804\udc04][0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud802\udc02 +true \ud802\udc02 0 + +[[\ud801\udc01-\ud804\udc04][0-9][\ud80b\udc0b-\ud80d\udc0d]] +\ud81a\udc1a +false 0 + +[\ud801\udc01-\ud803\udc03[\ud804\udc04-\ud806\udc06[\ud807\udc07-\ud809\udc09]]] +\ud801\udc01 +true \ud801\udc01 0 + +[\ud801\udc01-\ud803\udc03[\ud804\udc04-\ud806\udc06[\ud807\udc07-\ud809\udc09]]] +\ud805\udc05 +true \ud805\udc05 0 + +[\ud801\udc01-\ud803\udc03[\ud804\udc04-\ud806\udc06[\ud807\udc07-\ud809\udc09]]] +\ud808\udc08 +true \ud808\udc08 0 + +[\ud801\udc01-\ud803\udc03[\ud804\udc04-\ud806\udc06[\ud807\udc07-\ud809\udc09]]] +\ud80d\udc0d +false 0 + +[\ud801\udc01-\ud803\udc03[\ud804\udc04-\ud806\udc06[\ud807\udc07-\ud809\udc09]]\ud80d\udc0d] +\ud80d\udc0d +true \ud80d\udc0d 0 + +[\ud801\udc01\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]\ud807\udc07\ud808\udc08\ud809\udc09] +\ud801\udc01 +true \ud801\udc01 0 + +[\ud800\udc61\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]\ud807\udc07\ud808\udc08\ud809\udc09] +\ud804\udc04 +true \ud804\udc04 0 + +[\ud800\udc61\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]\ud807\udc07\ud808\udc08\ud809\udc09] +\ud808\udc08 +true \ud808\udc08 0 + +[\ud800\udc61\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]\ud807\udc07\ud808\udc08\ud809\udc09] +\ud816\udc16 +false 0 + +[\ud801\udc01-\ud803\udc03&&[\ud804\udc04-\ud806\udc06]] +\ud801\udc01 +false 0 + +[\ud801\udc01-\ud803\udc03&&[\ud804\udc04-\ud806\udc06]] +\ud805\udc05 +false 0 + +[\ud801\udc01-\ud803\udc03&&[\ud804\udc04-\ud806\udc06]] +\ud81a\udc1a +false 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud804\udc04-\ud806\udc06]] +\ud801\udc01 +false 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud804\udc04-\ud806\udc06]] +\ud805\udc05 +false 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud804\udc04-\ud806\udc06]] +\ud81a\udc1a +false 0 + +[\ud801\udc01-\ud803\udc03&&\ud804\udc04-\ud806\udc06] +\ud801\udc01 +false 0 + +[\ud801\udc01-\ud80d\udc0d&&\ud80d\udc0d-\ud81a\udc1a] +\ud80d\udc0d +true \ud80d\udc0d 0 + +[\ud801\udc01-\ud80d\udc0d&&\ud80d\udc0d-\ud81a\udc1a&&\ud801\udc01-\ud803\udc03] +\ud80d\udc0d +false 0 + +[\ud801\udc01-\ud80d\udc0d&&\ud80d\udc0d-\ud81a\udc1a&&\ud801\udc01-\ud81a\udc1a] +\ud80d\udc0d +true \ud80d\udc0d 0 + +[[\ud801\udc01-\ud80d\udc0d]&&[\ud80d\udc0d-\ud81a\udc1a]] +\ud801\udc01 +false 0 + +[[\ud801\udc01-\ud80d\udc0d]&&[\ud80d\udc0d-\ud81a\udc1a]] +\ud80d\udc0d +true \ud80d\udc0d 0 + +[[\ud801\udc01-\ud80d\udc0d]&&[\ud80d\udc0d-\ud81a\udc1a]] +\ud81a\udc1a +false 0 + +[[\ud801\udc01-\ud80d\udc0d]&&[^\ud801\udc01-\ud803\udc03]] +\ud801\udc01 +false 0 + +[[\ud801\udc01-\ud80d\udc0d]&&[^\ud801\udc01-\ud803\udc03]] +\ud804\udc04 +true \ud804\udc04 0 + +[\ud801\udc01-\ud80d\udc0d&&[^\ud801\udc01-\ud803\udc03]] +\ud801\udc01 +false 0 + +[\ud801\udc01-\ud80d\udc0d&&[^\ud801\udc01-\ud803\udc03]] +\ud804\udc04 +true \ud804\udc04 0 + +[\ud801\udc01-\ud803\udc03\ud804\udc04-\ud806\udc06&&[\ud804\udc04-\ud806\udc06]] +\ud801\udc01 +false 0 + +[\ud801\udc01-\ud803\udc03\ud804\udc04-\ud806\udc06&&[\ud804\udc04-\ud806\udc06]] +\ud805\udc05 +true \ud805\udc05 0 + +[[\ud801\udc01-\ud803\udc03]&&\ud804\udc04-\ud806\udc06\ud801\udc01-\ud803\udc03] +\ud801\udc01 +true \ud801\udc01 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud804\udc04-\ud806\udc06][\ud801\udc01-\ud803\udc03]] +\ud801\udc01 +true \ud801\udc01 0 + +[[\ud801\udc01-\ud803\udc03][\ud804\udc04-\ud806\udc06]&&\ud801\udc01\ud802\udc02\ud803\udc03] +\ud801\udc01 +true \ud801\udc01 0 + +[[\ud801\udc01-\ud803\udc03][\ud804\udc04-\ud806\udc06]&&\ud801\udc01\ud802\udc02\ud803\udc03[\ud804\udc04\ud805\udc05\ud806\udc06]] +\ud805\udc05 +true \ud805\udc05 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud802\udc02-\ud804\udc04]&&[\ud803\udc03-\ud805\udc05]] +\ud801\udc01 +false 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud802\udc02-\ud804\udc04]&&[\ud803\udc03-\ud805\udc05]] +\ud803\udc03 +true \ud803\udc03 0 + +[[\ud801\udc01-\ud803\udc03]&&[\ud802\udc02-\ud804\udc04][\ud803\udc03-\ud805\udc05]&&[\ud815\udc15-\ud81a\udc1a]] +\ud803\udc03 +false 0 + +[\ud801\udc01\ud802\udc02\ud803\udc03[^\ud802\udc02\ud803\udc03\ud804\udc04]] +\ud801\udc01 +true \ud801\udc01 0 + +[\ud800\udc61\ud802\udc02\ud803\udc03[^\ud802\udc02\ud803\udc03\ud804\udc04]] +\ud804\udc04 +false 0 + +[\ud801\udc01-\ud803\udc03&&\ud801\udc01-\ud804\udc04&&\ud801\udc01-\ud805\udc05\ud807\udc07\ud808\udc08\ud809\udc09] +\ud802\udc02 +true \ud802\udc02 0 + +[\ud801\udc01-\ud803\udc03&&\ud801\udc01-\ud804\udc04&&\ud801\udc01-\ud805\udc05\ud807\udc07\ud808\udc08\ud809\udc09] +\ud807\udc07 +false 0 + +[[\ud801\udc01[\ud802\udc02]]&&[\ud802\udc02[\ud801\udc01]]] +\ud801\udc01 +true \ud801\udc01 0 + +// Unicode isn't supported in clazz() +[[\ud800\udc61]&&[b][c][\ud800\udc61]&&[^d]] +\ud800\udc61 +true \ud800\udc61 0 + +[[\ud800\udc61]&&[\ud802\udc02][\ud800][\ud800\udc61]&&[^\ud804\udc04]] +\ud800\udc61 +true \ud800\udc61 0 + +[[\ud800\udc61]&&[b][\ud800][\ud800\udc61]&&[^\ud804\udc04]] +\ud804\udc04 +false 0 + +[[\ud800\udc61]&&[b][c][\ud800\udc61]&&[^d]] +d +false 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]] +\ud800\udc01 +false 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]] +\ud800\udc03 +true \ud800\udc03 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]&&[\ud800\udc03]] +\ud800\udc03 +true \ud800\udc03 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]&&[\ud800\udc03]&&\ud800\udc03] +\ud800\udc03 +true \ud800\udc03 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]&&[\ud800\udc03]&&\ud800\udc03&&\ud800\udc03] +\ud800\udc03 +true \ud800\udc03 0 + +[[[\ud800\udc01-\ud800\udc04]&&[\ud800\udc03-\ud800\udc06]]&&[\ud800\udc03]&&\ud800\udc03&&[\ud800\udc03\ud800\udc04\ud800\udc05]] +\ud800\udc03 +true \ud800\udc03 0 + +[z[\ud800\udc61b\ud800\udc03&&b\ud800\udc03\ud800\udc04]] +\ud800\udc03 +true \ud800\udc03 0 + +[z[\ud800\udc61b\ud800\udc03&&b\ud800\udc03\ud800\udc04]&&[u-z]] +z +true z 0 + +[x[\ud800\udc61b\ud800\udc03&&b\ud800\udc03\ud800\udc04[z]]&&[u-z]] +z +false 0 + +[x[[wz]\ud800\udc61b\ud800\udc03&&b\ud800\udc03\ud800\udc04[z]]&&[u-z]] +z +true z 0 + +[[\ud800\udc61b\ud800\udc03]&&[\ud800\udc04\ud800\udc05f]\ud800\udc61b\ud800\udc03] +\ud800\udc61 +true \ud800\udc61 0 + +[[\ud800\udc61b\ud800\udc03]&&[\ud800\udc04\ud800\udc05f]xyz[\ud800\udc61b\ud800\udc03]] +\ud800\udc61 +true \ud800\udc61 0 + +\pL +\ud800\udc00 +true \ud800\udc00 0 + +\p{IsASCII} +\ud800\udc00 +false 0 + +\pLbc +\ud800\udc00bc +true \ud800\udc00bc 0 + +\ud800\udc61[r\p{InGreek}]c +\ud800\udc61\u0370c +true \ud800\udc61\u0370c 0 + +\ud800\udc61\p{InGreek} +\ud800\udc61\u0370 +true \ud800\udc61\u0370 0 + +\ud800\udc61\P{InGreek} +\ud800\udc61\u0370 +false 0 + +\ud800\udc61\P{InGreek} +\ud800\udc61b +true \ud800\udc61b 0 + +\ud800\udc61{^InGreek} +- +error + +\ud800\udc61\p{^InGreek} +- +error + +\ud800\udc61\P{^InGreek} +- +error + +\ud800\udc61\p{InGreek} +\ud800\udc61\u0370 +true \ud800\udc61\u0370 0 + +\ud800\udc61[\p{InGreek}]c +\ud800\udc61\u0370c +true \ud800\udc61\u0370c 0 + +\ud800\udc61[\P{InGreek}]c +\ud800\udc61\u0370c +false 0 + +\ud800\udc61[\P{InGreek}]c +\ud800\udc61bc +true \ud800\udc61bc 0 + +\ud800\udc61[{^InGreek}]c +\ud800\udc61nc +true \ud800\udc61nc 0 + +\ud800\udc61[{^InGreek}]c +\ud800\udc61zc +false 0 + +\ud800\udc61[\p{^InGreek}]c +- +error + +\ud800\udc61[\P{^InGreek}]c +- +error + +\ud800\udc61[\p{InGreek}] +\ud800\udc61\u0370 +true \ud800\udc61\u0370 0 + +\ud800\udc61[r\p{InGreek}]c +\ud800\udc61rc +true \ud800\udc61rc 0 + +\ud800\udc61[\p{InGreek}r]c +\ud800\udc61rc +true \ud800\udc61rc 0 + +\ud800\udc61[r\p{InGreek}]c +\ud800\udc61rc +true \ud800\udc61rc 0 + +\ud800\udc61[^\p{InGreek}]c +\ud800\udc61\u0370c +false 0 + +\ud800\udc61[^\P{InGreek}]c +\ud800\udc61\u0370c +true \ud800\udc61\u0370c 0 + +\ud800\udc61[\p{InGreek}&&[^\u0370]]c +\ud800\udc61\u0370c +false 0 + +// Test the dot metacharacter +\ud800\udc61.c.+ +\ud800\udc61#c%& +true \ud800\udc61#c%& 0 + +\ud800\udc61b. +\ud800\udc61b\n +false 0 + +(?s)\ud800\udc61b. +\ud800\udc61b\n +true \ud800\udc61b\n 0 + +\ud800\udc61[\p{L}&&[\P{InGreek}]]c +\ud800\udc61\u6000c +true \ud800\udc61\u6000c 0 + +\ud800\udc61[\p{L}&&[\P{InGreek}]]c +\ud800\udc61rc +true \ud800\udc61rc 0 + +\ud800\udc61[\p{L}&&[\P{InGreek}]]c +\ud800\udc61\u0370c +false 0 + +\ud800\udc61\p{InGreek}c +\ud800\udc61\u0370c +true \ud800\udc61\u0370c 0 + +\ud800\udc61\p{Sc} +\ud800\udc61$ +true \ud800\udc61$ 0 + +// Test \p{L} +\p{L} +\ud800\udf1e +true \ud800\udf1e 0 + +^a\p{L}z$ +a\ud800\udf1ez +true a\ud800\udf1ez 0 + +// Test \P{InDeseret} + +\ud800\udf00\p{L}{2,3}\P{L}*supp->\ud900\udc00<-\P{InDeseret} +\ud800\udf00\ud800\udf1e\ud800\udf1esupp->\ud900\udc00<-\ud901\udf00 +true \ud800\udf00\ud800\udf1e\ud800\udf1esupp->\ud900\udc00<-\ud901\udf00 0 + +\ud800\udf00\p{L}{2,3}\P{L}*supp->\ud900\udc00<-\P{InDeseret} +\ud800\udf00\ud800\udf1e\ud800\udf1e\ud901\udf00supp->\ud900\udc00<-\ud901\udf00 +true \ud800\udf00\ud800\udf1e\ud800\udf1e\ud901\udf00supp->\ud900\udc00<-\ud901\udf00 0 + +// Test \p{InDeseret} +\ud800\udf00\p{L}{2,3}\P{L}*supp->\ud900\udc00<-\p{InDeseret} +\ud800\udf00\ud800\udf1e\ud800\udf1e\ud901\udf00supp->\ud900\udc00<-\ud801\udc00 +true \ud800\udf00\ud800\udf1e\ud800\udf1e\ud901\udf00supp->\ud900\udc00<-\ud801\udc00 0 + +// Test the word char escape sequence +\ud800\udc61b\wc +\ud800\udc61bcc +true \ud800\udc61bcc 0 + +\ud800\udc61bc[\w] +\ud800\udc61bcd +true \ud800\udc61bcd 0 + +\ud800\udc61bc[\sdef]* +\ud800\udc61bc def +true \ud800\udc61bc def 0 + +\ud800\udc61bc[\sy-z]* +\ud800\udc61bc y z +true \ud800\udc61bc y z 0 + +\ud800\udc01bc[\ud800\udc01-\ud800\udc04\sm-p]* +\ud800\udc01bc\ud800\udc01\ud800\udc01 mn p +true \ud800\udc01bc\ud800\udc01\ud800\udc01 mn p 0 + +// Test the whitespace escape sequence +\ud800\udc61b\s\ud800\udc03 +\ud800\udc61b \ud800\udc03 +true \ud800\udc61b \ud800\udc03 0 + +\s\s\s +bl\ud800\udc61h err +false 0 + +\S\S\s +bl\ud800\udc61h err +true \ud800\udc61h 0 + +// Test the digit escape sequence +\ud800\udc61b\d\ud800\udc03 +\ud800\udc61b9\ud800\udc03 +true \ud800\udc61b9\ud800\udc03 0 + +\d\d\d +bl\ud800\udc61h45 +false 0 + +// Test the caret metacharacter +^\ud800\udc61bc +\ud800\udc61bcdef +true \ud800\udc61bc 0 + +^\ud800\udc61bc +bcd\ud800\udc61bc +false 0 + +// Greedy ? metacharacter +\ud800\udc61?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +\udc61?\ud800\udc02 +\ud800\udc61\udc61\udc61\ud800\udc02 +true \udc61\ud800\udc02 0 + +\ud800\udc61?\ud800\udc02 +\ud800\udc02 +true \ud800\udc02 0 + +\ud800?\ud800\udc02 +\ud800\udc02 +true \ud800\udc02 0 + +\ud800\udc61?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc03\ud800\udc03\ud800\udc03 +false 0 + +.?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +// Reluctant ? metacharacter +\ud800\udc61??\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +\ud800??\ud800\udc02 +\ud800\ud800\ud8001\ud800\ud800\udc02 +true \ud800\ud800\udc02 0 + +\ud800\udc61??\ud800\udc02 +\ud800\udc02 +true \ud800\udc02 0 + +\ud800??\ud800\udc02 +\ud800\udc02 +true \ud800\udc02 0 + +\ud800\udc61??\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61ccc +false 0 + +.??\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +// Possessive ? metacharacter +\ud800\udc61?+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +\ud800\udc61?+\ud800\udc02 +\ud800\udc02 +true \ud800\udc02 0 + +\ud800\udc61?+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61ccc +false 0 + +.?+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc02 0 + +// Greedy + metacharacter +\ud800\udc61+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 0 + +\udc61+\ud800\udc02 +\ud800\udc61\udc61\udc61\udc61\ud800\udc02 +true \udc61\udc61\udc61\ud800\udc02 0 + +\ud800\udc61+\ud800\udc02 +\ud800\udc02 +false 0 + +\ud800+\ud800\udc02 +\ud800\udc02 +false 0 + +\ud800\udc61+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61ccc +false 0 + +.+\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 0 + +.+\ud800\udc02 +\ud800\udc61\udc61\udc61\udc61\ud800\udc02 +true \ud800\udc61\udc61\udc61\udc61\ud800\udc02 0 + +// Reluctant + metacharacter +\ud800\udc61+?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 0 + +\udc61+?\ud800\udc02 +\udc61\udc61\udc61\udc61\ud800\udc02 +true \udc61\udc61\udc61\udc61\ud800\udc02 0 + +\ud800\udc61+?\ud800\udc02 +\ud800\udc02 +false 0 + +\ud800+?\ud800\udc02 +\ud800\udc02 +false 0 + +\ud800\udc61+?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61ccc +false 0 + +.+?\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 0 + +// Possessive + metacharacter +\ud800\udc61++\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 0 + +\ud800\udc61++\ud800\udc02 +\ud800\udc02 +false 0 + +\ud800\udc61++\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61ccc +false 0 + +.++\ud800\udc02 +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc02 +false 0 + +// Greedy Repetition +\ud800\udc61{2,3} +\ud800\udc61 +false 0 + +\ud800\udc61{2,3} +\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61 0 + +\ud800\udc61{2,3} +\ud800\udc61\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61\ud800\udc61 0 + +\ud800\udc61{2,3} +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61\ud800\udc61 0 + +\ud800\udc61{3,} +zzz\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61zzz +true \ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61 0 + +\ud800\udc61{3,} +zzz\ud800\udc61\ud800\udc61zzz +false 0 + +// Reluctant Repetition +\ud800\udc61{2,3}? +\ud800\udc61 +false 0 + +\ud800\udc61{2,3}? +\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61 0 + +\ud800\udc61{2,3}? +\ud800\udc61\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61 0 + +\ud800\udc61{2,3}? +\ud800\udc61\ud800\udc61\ud800\udc61\ud800\udc61 +true \ud800\udc61\ud800\udc61 0 + +// Zero width Positive lookahead +\ud800\udc61\ud802\udc02\ud803\udc03(?=\ud804\udc04) +zzz\ud800\udc61\ud802\udc02\ud803\udc03\ud804\udc04 +true \ud800\udc61\ud802\udc02\ud803\udc03 0 + +\ud800\udc61\ud802\udc02\ud803\udc03(?=\ud804\udc04) +zzz\ud800\udc61\ud802\udc02\ud803\udc03e\ud804\udc04 +false 0 + +\ud800\udc61\ud802\udc02\ud803\udc03(?=\udcff\ud804\udc04) +zzz\ud800\udc61\ud802\udc02\ud803\udc03\udcff\ud804\udc04 +true \ud800\udc61\ud802\udc02\ud803\udc03 0 + +\ud800\udc61\ud802\udc02\ud803\udc03(?=\udcff\ud804\udc04) +zzz\ud800\udc61\ud802\udc02\ud803\udc03\ud8ff\udcff\ud804\udc04 +false 0 + +// Zero width Negative lookahead +\ud800\udc61\ud802\udc02\ud803\udc03(?!\ud804\udc04) +zz\ud800\udc61\ud802\udc02\ud803\udc03\ud804\udc04 +false 0 + +a\ud802\udc02\ud803\udc03(?!\ud804\udc04) +zza\ud802\udc02\ud803\udc03\udc04\ud804\udc04 +true a\ud802\udc02\ud803\udc03 0 + +\ud800\udc61\ud802\udc02\ud803\udc03(?!\ud804\udc04\ud8ff) +zz\ud800\udc61\ud802\udc02\ud803\udc03\ud804\udc04\ud8ffX +false 0 + +a\ud802\udc02\ud803\udc03(?!\ud804\udc04\ud8ff) +zza\ud802\udc02\ud803\udc03e\ud804\udc04\ud8ff\udcff +true a\ud802\udc02\ud803\udc03 0 + +// Zero width Positive lookbehind +(?<=\ud801\udc01\ud802\udc02)\ud803\udc03 +\ud801\udc01\ud802\udc02\ud803\udc03 +true \ud803\udc03 0 + +// Zero width Negative lookbehind +(?3 +// So that the BM optimization is part of test +\Q***\E\ud801\udc01\ud802\udc02\ud800\udc03 +***\ud801\udc01\ud802\udc02\ud800\udc03 +true ***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\ud802\udc02l\Q***\E\ud801\udc01\ud802\udc02\ud800\udc03 +\ud802\udc02l***\ud801\udc01\ud802\udc02\ud800\udc03 +true \ud802\udc02l***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\Q***\ud801\udc01\ud802\udc02\ud800\udc03 +***\ud801\udc01\ud802\udc02\ud800\udc03 +true ***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\ud802\udc02l\ud801\udc01h\Q***\E\ud801\udc01\ud802\udc02\ud800\udc03 +\ud802\udc02l\ud801\udc01h***\ud801\udc01\ud802\udc02\ud800\udc03 +true \ud802\udc02l\ud801\udc01h***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\Q***\ud801\udc01\ud802\udc02\ud800\udc03 +***\ud801\udc01\ud802\udc02\ud800\udc03 +true ***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\Q*\ud801\udc01\ud802\udc02 +*\ud801\udc01\ud802\udc02 +true *\ud801\udc01\ud802\udc02 0 + +\ud802\udc02l\ud801\udc01h\Q***\ud801\udc01\ud802\udc02\ud800\udc03 +\ud802\udc02l\ud801\udc01h***\ud801\udc01\ud802\udc02\ud800\udc03 +true \ud802\udc02l\ud801\udc01h***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +\ud802\udc02l\ud801\udc01\Q***\ud801\udc01\ud802\udc02\ud800\udc03 +\ud802\udc02l\ud801\udc01***\ud801\udc01\ud802\udc02\ud800\udc03 +true \ud802\udc02l\ud801\udc01***\ud801\udc01\ud802\udc02\ud800\udc03 0 + +//Test cases below copied from i18n QE's RegexSupplementaryTests.txt +\uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 +\uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 +true \uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 0 + +\uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 +\u1000\uD801\uDFF1\uDB00\uDC00 +false 0 + +\uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 +\uD800\uDFFF\uFFFF\uDB00\uDC00 +false 0 + +\uD800\uDFFF\uD801\uDFF1\uDB00\uDC00 +\uD800\uDFFF\uD801\uDFF1\uFFFF +false 0 + +\u1000.\uFFFF +\u1000\uD800\uDFFF\uFFFF +true \u1000\uD800\uDFFF\uFFFF 0 + +//======= +// Ranges +//======= +[a-\uD800\uDFFF] +\uDFFF +true \uDFFF 0 + +[a-\uD800\uDFFF] +\uD800 +true \uD800 0 + +[a-\uD800\uDFFF] +\uD800\uDFFF +true \uD800\uDFFF 0 + +[\uD800\uDC00-\uDBFF\uDFFF] +\uDBFF +false 0 + +[\uD800\uDC00-\uDBFF\uDFFF] +\uDC00 +false 0 + +[\uD800-\uDFFF] +\uD800\uDFFF +false 0 + +[\uD800-\uDFFF] +\uDFFF\uD800 +true \uDFFF 0 + +foo[^\uD800-\uDFFF] +foo\uD800\uDFFF +true foo\uD800\uDFFF 0 + +foo[^\uD800-\uDFFF] +foo\uDFFF\uD800 +false 0 + +//fo\uD800[\uDC00-\uDFFF] + +//================== +// Character Classes +//================== +// Simple class +[ab\uD800\uDFFFcd]at +\uD800at +false 0 + +[ab\uD800\uDFFFcd]at +\uD800\uDFFFat +true \uD800\uDFFFat 0 + +// Negation +[^\uD800\uDFFFcd]at +\uD800at +true \uD800at 0 + +[^\uD800\uDFFFcd]at +\uDFFFat +true \uDFFFat 0 + +// Inclusive range +[\u0000-\uD800\uDFFF-\uFFFF] +\uD800\uDFFF +true \uD800\uDFFF 0 + +// Unions +[\u0000-\uD800[\uDFFF-\uFFFF]] +\uD800\uDFFF +false 0 + + +// Intersection +[\u0000-\uFFFF&&[\uD800\uDFFF]] +\uD800\uDFFF +false 0 + +[\u0000-\uFFFF&&[\uD800\uDFFF]] +\uD800 +false 0 + +[\u0000-\uFFFF&&[\uDFFF\uD800]] +\uD800 +true \uD800 0 + +[\u0000-\uFFFF&&[\uDFFF\uD800\uDC00]] +\uDC00 +false 0 + +[\u0000-\uDFFF&&[\uD800-\uFFFF]] +\uD800\uDFFF +false 0 + +[\u0000-\uDFFF&&[\uD800-\uFFFF]] +\uDFFF\uD800 +true \uDFFF 0 + +// Subtraction +[\u0000-\uD800\uDFFF&&[^\uD800\uDC00]] +\uD800 +true \uD800 0 + +[\u0000-\uD800\uDFFF&&[^\uD800\uDC00]] +\uDC00 +true \uDC00 0 + +[\u0000-\uD800\uDFFF&&[^\uD800\uDC00]] +\uD800\uDFFF +true \uD800\uDFFF 0 + +[\u0000-\uD800\uDFFF&&[^\uD800\uDBFF\uDC00]] +\uD800 +false 0 + +[\u0000-\uD800\uDFFF&&[^\uDC00\uD800\uDBFF]] +\uD800\uDC00 +true \uD800\uDC00 0 + +// Quantifiers +a\uD800\uDFFF? +a\uD800 +true a 0 + +a\uD800\uDFFF? +a\uDFFF +true a 0 + +a\uD800\uDFFF? +a\uD800\uDFFF +true a\uD800\uDFFF 0 + +a\uDFFF\uD800? +a\uDFFF +true a\uDFFF 0 + +a\uDFFF\uD800? +a\uD800 +false 0 + +\uD800\uDFFF\uDC00? +\uD800 +false 0 + +\uD800\uDFFF\uDC00? +\uD800\uDFFF +true \uD800\uDFFF 0 + +a\uD800\uDFFF?? +a\uDFFF +true a 0 + +a\uD800\uDFFF* +a +true a 0 + +a\uD800\uDFFF* +a\uD800 +true a 0 + +\uD800\uDFFF* +\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +\uD800\uDFFF* +\uD800\uDFFF\uDFFF\uDFFF\uDFFF +true \uD800\uDFFF 0 + +\uD800*\uDFFF +\uD800\uDFFF +false 0 + +a\uD800\uDFFF* +a\uD800 +true a 0 + +\uDFFF\uD800* +\uDFFF +true \uDFFF 0 + +\uDFFF\uD800* +\uDFFF\uD800\uD800\uD800 +true \uDFFF\uD800\uD800\uD800 0 + +\uD800\uDFFF+ +\uD800\uDFFF\uDFFF\uDFFF +true \uD800\uDFFF 0 + +\uD800\uDFFF+ +\uD800 +false 0 + +\uD800\uDFFF+ +\uD800\uDFFF +true \uD800\uDFFF 0 + +\uD800\uDFFF+ +\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +\uDFFF\uD800+ +\uDFFF\uD800\uDFFF\uD800 +false 0 + +\uD800+\uDFFF +\uD800\uDFFF +false 0 + +\uD800+\uDFFF +\uD800 +false 0 + +\uDFFF+\uD800 +\uD800 +false 0 + +\uDFFF+\uD800 +\uDFFF\uD800 +true \uDFFF\uD800 0 + +\uD800\uDFFF{3} +\uD800\uDFFF\uDFFF\uDFFF +false 0 + +\uD800\uDFFF{3} +\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +\uDFFF\uD800{3} +\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800 +false 0 + +\uDFFF\uD800{3} +\uDFFF\uD800\uD800\uD800 +true \uDFFF\uD800\uD800\uD800 0 + +\uD800\uDFFF{2,} +\uD800\uDFFF +false 0 + +\uD800\uDFFF{2,} +\uD800\uDFFF\uDFFF +false 0 + +\uD800\uDFFF{2,} +\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF 0 + +\uDFFF\uD800{2,} +\uDFFF\uD800\uDFFF\uD800 +false 0 + +\uDFFF\uD800{2,} +\uDFFF\uD800\uD800\uD800 +true \uDFFF\uD800\uD800\uD800 0 + +\uD800\uDFFF{3,4} +\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +\uD800\uDFFF{3,4} +\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF\uD800 +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +\uD800\uDFFF{3,4} +\uD800\uDFFF\uD800\uD800\uDFFF\uD800\uDFFF +false 0 + +\uDFFF\uD800{3,5} +\uDFFF\uD800\uD800\uD800\uD800\uD800\uD800\uD800 +true \uDFFF\uD800\uD800\uD800\uD800\uD800 0 + +\uD800\uDFFF{3,5} +\uD800\uDFFF\uDFFF\uDFFF +false 0 + +\uD800\uDFFF{3,5} +\uD800\uDFFF\uD800\uD800\uDFFF\uD800\uDFFF\uD800\uDFFF +true \uD800\uDFFF\uD800\uDFFF\uD800\uDFFF 0 + +// Groupings +(\uD800(\uDFFF)) +\uD800\uDFFF +false 2 + +(\uD800(\uDC00)(\uDFFF)) +\uD800\uDC00\uDFFF +false 3 + +((\uD800)(\uDFFF)) +\uD800\uDFFF +false 3 + +(\uD800(\uDFFF)\uDFFF) +\uD800\uDFFF +false 2 + +(\uDFFF(\uD800)(\uDBFF)) +\uDFFF\uD800\uDBFF +true \uDFFF\uD800\uDBFF 3 \uDFFF\uD800\uDBFF \uD800 \uDBFF + +(\uDFFF(\uD800)(\uDC00)) +\uDFFF\uD800\uDC00 +false 3 + +(\uDFFF\uD800(\uDC00\uDBFF)) +\uDFFF\uD800\uDC00\uDBFF +false 2 + +(\uD800\uDFFF(\uDBFF)(\uDC00)) +\uD800\uDFFF\uDBFF\uDC00 +false 3 + +(\uD800\uDFFF(\uDBFF\uDC00)) +\uD800\uDFFF\uDBFF\uDC00 +true \uD800\uDFFF\uDBFF\uDC00 2 \uD800\uDFFF\uDBFF\uDC00 \uDBFF\uDC00 diff --git a/jdk/test/java/util/regex/TestCases.txt b/jdk/test/java/util/regex/TestCases.txt new file mode 100644 index 00000000000..fd41df33f76 --- /dev/null +++ b/jdk/test/java/util/regex/TestCases.txt @@ -0,0 +1,1092 @@ +// +// Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// +// +// This file contains test cases for regular expressions. +// A test case consists of three lines: +// The first line is a pattern used in the test +// The second line is the input to search for the pattern in +// The third line is a concatentation of the match, the number of groups, +// and the contents of the first four subexpressions. +// Empty lines and lines beginning with comment slashes are ignored. +// +// Test unsetting of backed off groups +^(a)?a +a +true a 1 + +^(aa(bb)?)+$ +aabbaa +true aabbaa 2 aa bb + +((a|b)?b)+ +b +true b 2 b + +(aaa)?aaa +aaa +true aaa 1 + +^(a(b)?)+$ +aba +true aba 2 a b + +^(a(b(c)?)?)?abc +abc +true abc 3 + +^(a(b(c))).* +abc +true abc 3 abc bc c + +// use of x modifier +abc(?x)blah +abcblah +true abcblah 0 + +abc(?x) blah +abcblah +true abcblah 0 + +abc(?x) blah blech +abcblahblech +true abcblahblech 0 + +abc(?x) blah # ignore comment +abcblah +true abcblah 0 + +// Simple alternation +a|b +a +true a 0 + +a|b +z +false 0 + +a|b +b +true b 0 + +a|b|cd +cd +true cd 0 + +a|ad +ad +true a 0 + +z(a|ac)b +zacb +true zacb 1 ac + +// Simple char class +[abc]+ +ababab +true ababab 0 + +[abc]+ +defg +false 0 + +[abc]+[def]+[ghi]+ +zzzaaddggzzz +true aaddgg 0 + +// Range char class +[a-g]+ +zzzggg +true ggg 0 + +[a-g]+ +mmm +false 0 + +[a-]+ +za-9z +true a- 0 + +[a-\\u4444]+ +za-9z +true za 0 + +// Negated char class +[^abc]+ +ababab +false 0 + +[^abc]+ +aaabbbcccdefg +true defg 0 + +// Making sure a ^ not in first position matches literal ^ +[abc^b] +b +true b 0 + +[abc^b] +^ +true ^ 0 + +// Class union and intersection +[abc[def]] +b +true b 0 + +[abc[def]] +e +true e 0 + +[a-d[0-9][m-p]] +a +true a 0 + +[a-d[0-9][m-p]] +o +true o 0 + +[a-d[0-9][m-p]] +4 +true 4 0 + +[a-d[0-9][m-p]] +e +false 0 + +[a-d[0-9][m-p]] +u +false 0 + +[[a-d][0-9][m-p]] +b +true b 0 + +[[a-d][0-9][m-p]] +z +false 0 + +[a-c[d-f[g-i]]] +a +true a 0 + +[a-c[d-f[g-i]]] +e +true e 0 + +[a-c[d-f[g-i]]] +h +true h 0 + +[a-c[d-f[g-i]]] +m +false 0 + +[a-c[d-f[g-i]]m] +m +true m 0 + +[abc[def]ghi] +a +true a 0 + +[abc[def]ghi] +d +true d 0 + +[abc[def]ghi] +h +true h 0 + +[abc[def]ghi] +w +false 0 + +[a-c&&[d-f]] +a +false 0 + +[a-c&&[d-f]] +e +false 0 + +[a-c&&[d-f]] +z +false 0 + +[[a-c]&&[d-f]] +a +false 0 + +[[a-c]&&[d-f]] +e +false 0 + +[[a-c]&&[d-f]] +z +false 0 + +[a-c&&d-f] +a +false 0 + +[a-m&&m-z] +m +true m 0 + +[a-m&&m-z&&a-c] +m +false 0 + +[a-m&&m-z&&a-z] +m +true m 0 + +[[a-m]&&[m-z]] +a +false 0 + +[[a-m]&&[m-z]] +m +true m 0 + +[[a-m]&&[m-z]] +z +false 0 + +[[a-m]&&[^a-c]] +a +false 0 + +[[a-m]&&[^a-c]] +d +true d 0 + +[a-m&&[^a-c]] +a +false 0 + +[a-m&&[^a-c]] +d +true d 0 + +[a-cd-f&&[d-f]] +a +false 0 + +[a-cd-f&&[d-f]] +e +true e 0 + +[[a-c]&&d-fa-c] +a +true a 0 + +[[a-c]&&[d-f][a-c]] +a +true a 0 + +[[a-c][d-f]&&abc] +a +true a 0 + +[[a-c][d-f]&&abc[def]] +e +true e 0 + +[[a-c]&&[b-d]&&[c-e]] +a +false 0 + +[[a-c]&&[b-d]&&[c-e]] +c +true c 0 + +[[a-c]&&[b-d][c-e]&&[u-z]] +c +false 0 + +[abc[^bcd]] +a +true a 0 + +[abc[^bcd]] +d +false 0 + +[a-c&&a-d&&a-eghi] +b +true b 0 + +[a-c&&a-d&&a-eghi] +g +false 0 + +[[a[b]]&&[b[a]]] +a +true a 0 + +[[a]&&[b][c][a]&&[^d]] +a +true a 0 + +[[a]&&[b][c][a]&&[^d]] +d +false 0 + +[[[a-d]&&[c-f]]] +a +false 0 + +[[[a-d]&&[c-f]]] +c +true c 0 + +[[[a-d]&&[c-f]]&&[c]] +c +true c 0 + +[[[a-d]&&[c-f]]&&[c]&&c] +c +true c 0 + +[[[a-d]&&[c-f]]&&[c]&&c&&c] +c +true c 0 + +[[[a-d]&&[c-f]]&&[c]&&c&&[cde]] +c +true c 0 + +[z[abc&&bcd]] +c +true c 0 + +[z[abc&&bcd]&&[u-z]] +z +true z 0 + +[x[abc&&bcd[z]]&&[u-z]] +z +false 0 + +[x[[wz]abc&&bcd[z]]&&[u-z]] +z +true z 0 + +[[abc]&&[def]abc] +a +true a 0 + +[[abc]&&[def]xyz[abc]] +a +true a 0 + +\pL +a +true a 0 + +\pL +7 +false 0 + +\p{L} +a +true a 0 + +\p{LC} +a +true a 0 + +\p{LC} +A +true A 0 + +\p{IsL} +a +true a 0 + +\p{IsLC} +a +true a 0 + +\p{IsLC} +A +true A 0 + +\p{IsLC} +9 +false 0 + +\P{IsLC} +9 +true 9 0 + +// Guillemet left is initial quote punctuation +\p{Pi} +\u00ab +true \u00ab 0 + +\P{Pi} +\u00ac +true \u00ac 0 + +// Guillemet right is final quote punctuation +\p{IsPf} +\u00bb +true \u00bb 0 + +\p{P} +\u00bb +true \u00bb 0 + +\p{P}+ +\u00bb +true \u00bb 0 + +\P{IsPf} +\u00bc +true \u00bc 0 + +\P{IsP} +\u00bc +true \u00bc 0 + +\p{L1} +\u00bc +true \u00bc 0 + +\p{L1}+ +\u00bc +true \u00bc 0 + +\p{L1} +\u02bc +false 0 + +\p{ASCII} +a +true a 0 + +\p{IsASCII} +a +true a 0 + +\p{IsASCII} +\u0370 +false 0 + +\pLbc +abc +true abc 0 + +a[r\p{InGreek}]c +a\u0370c +true a\u0370c 0 + +a\p{InGreek} +a\u0370 +true a\u0370 0 + +a\P{InGreek} +a\u0370 +false 0 + +a\P{InGreek} +ab +true ab 0 + +a{^InGreek} +- +error + +a\p{^InGreek} +- +error + +a\P{^InGreek} +- +error + +a\p{InGreek} +a\u0370 +true a\u0370 0 + +a[\p{InGreek}]c +a\u0370c +true a\u0370c 0 + +a[\P{InGreek}]c +a\u0370c +false 0 + +a[\P{InGreek}]c +abc +true abc 0 + +a[{^InGreek}]c +anc +true anc 0 + +a[{^InGreek}]c +azc +false 0 + +a[\p{^InGreek}]c +- +error + +a[\P{^InGreek}]c +- +error + +a[\p{InGreek}] +a\u0370 +true a\u0370 0 + +a[r\p{InGreek}]c +arc +true arc 0 + +a[\p{InGreek}r]c +arc +true arc 0 + +a[r\p{InGreek}]c +arc +true arc 0 + +a[^\p{InGreek}]c +a\u0370c +false 0 + +a[^\P{InGreek}]c +a\u0370c +true a\u0370c 0 + +a[\p{InGreek}&&[^\u0370]]c +a\u0370c +false 0 + +// Test the dot metacharacter +a.c.+ +a#c%& +true a#c%& 0 + +ab. +ab\n +false 0 + +(?s)ab. +ab\n +true ab\n 0 + +a[\p{L}&&[\P{InGreek}]]c +a\u6000c +true a\u6000c 0 + +a[\p{L}&&[\P{InGreek}]]c +arc +true arc 0 + +a[\p{L}&&[\P{InGreek}]]c +a\u0370c +false 0 + +a\p{InGreek}c +a\u0370c +true a\u0370c 0 + +a\p{Sc} +a$ +true a$ 0 + +// Test the word char escape sequence +ab\wc +abcc +true abcc 0 + +\W\w\W +#r# +true #r# 0 + +\W\w\W +rrrr#ggg +false 0 + +abc[\w] +abcd +true abcd 0 + +abc[\sdef]* +abc def +true abc def 0 + +abc[\sy-z]* +abc y z +true abc y z 0 + +abc[a-d\sm-p]* +abcaa mn p +true abcaa mn p 0 + +// Test the whitespace escape sequence +ab\sc +ab c +true ab c 0 + +\s\s\s +blah err +false 0 + +\S\S\s +blah err +true ah 0 + +// Test the digit escape sequence +ab\dc +ab9c +true ab9c 0 + +\d\d\d +blah45 +false 0 + +// Test the caret metacharacter +^abc +abcdef +true abc 0 + +^abc +bcdabc +false 0 + +// Greedy ? metacharacter +a?b +aaaab +true ab 0 + +a?b +b +true b 0 + +a?b +aaaccc +false 0 + +.?b +aaaab +true ab 0 + +// Reluctant ? metacharacter +a??b +aaaab +true ab 0 + +a??b +b +true b 0 + +a??b +aaaccc +false 0 + +.??b +aaaab +true ab 0 + +// Possessive ? metacharacter +a?+b +aaaab +true ab 0 + +a?+b +b +true b 0 + +a?+b +aaaccc +false 0 + +.?+b +aaaab +true ab 0 + +// Greedy + metacharacter +a+b +aaaab +true aaaab 0 + +a+b +b +false 0 + +a+b +aaaccc +false 0 + +.+b +aaaab +true aaaab 0 + +// Reluctant + metacharacter +a+?b +aaaab +true aaaab 0 + +a+?b +b +false 0 + +a+?b +aaaccc +false 0 + +.+?b +aaaab +true aaaab 0 + +// Possessive + metacharacter +a++b +aaaab +true aaaab 0 + +a++b +b +false 0 + +a++b +aaaccc +false 0 + +.++b +aaaab +false 0 + +// Greedy Repetition +a{2,3} +a +false 0 + +a{2,3} +aa +true aa 0 + +a{2,3} +aaa +true aaa 0 + +a{2,3} +aaaa +true aaa 0 + +a{3,} +zzzaaaazzz +true aaaa 0 + +a{3,} +zzzaazzz +false 0 + +// Reluctant Repetition +a{2,3}? +a +false 0 + +a{2,3}? +aa +true aa 0 + +a{2,3}? +aaa +true aa 0 + +a{2,3}? +aaaa +true aa 0 + +// Zero width Positive lookahead +abc(?=d) +zzzabcd +true abc 0 + +abc(?=d) +zzzabced +false 0 + +// Zero width Negative lookahead +abc(?!d) +zzabcd +false 0 + +abc(?!d) +zzabced +true abc 0 + +// Zero width Positive lookbehind +\w(?<=a) +###abc### +true a 0 + +\w(?<=a) +###ert### +false 0 + +// Zero width Negative lookbehind +(?3 +// So that the BM optimization is part of test +\Q***\Eabc +***abc +true ***abc 0 + +bl\Q***\Eabc +bl***abc +true bl***abc 0 + +\Q***abc +***abc +true ***abc 0 + +blah\Q***\Eabc +blah***abc +true blah***abc 0 + +\Q***abc +***abc +true ***abc 0 + +\Q*ab +*ab +true *ab 0 + +blah\Q***abc +blah***abc +true blah***abc 0 + +bla\Q***abc +bla***abc +true bla***abc 0 + +// Escapes in char classes +[ab\Qdef\E] +d +true d 0 + +[ab\Q[\E] +[ +true [ 0 + +[\Q]\E] +] +true ] 0 + +[\Q\\E] +\ +true \ 0 + +[\Q(\E] +( +true ( 0 + +[\n-#] +! +true ! 0 + +[\n-#] +- +false 0 + +[\w-#] +! +false 0 + +[\w-#] +a +true a 0 + +[\w-#] +- +true - 0 + +[\w-#] +# +true # 0 + +[\043]+ +blahblah#blech +true # 0 + +[\042-\044]+ +blahblah#blech +true # 0 + +[\u1234-\u1236] +blahblah\u1235blech +true \u1235 0 + +[^\043]* +blahblah#blech +true blahblah 0 + +(|f)?+ +foo +true 1 diff --git a/jdk/test/java/util/zip/ZipFile/LargeZipFile.java b/jdk/test/java/util/zip/ZipFile/LargeZipFile.java new file mode 100644 index 00000000000..e4f986ef210 --- /dev/null +++ b/jdk/test/java/util/zip/ZipFile/LargeZipFile.java @@ -0,0 +1,138 @@ +import java.io.*; +import java.nio.*; +import java.util.*; +import java.util.zip.*; + +public class LargeZipFile { + // If true, don't delete large ZIP file created for test. + static final boolean debug = System.getProperty("debug") != null; + + static final int DATA_LEN = 1024 * 1024; + static final int DATA_SIZE = 8; + + static long fileSize = 3L * 1024L * 1024L * 1024L; // 3GB + + static boolean userFile = false; + + static byte[] data; + static File largeFile; + static String lastEntryName; + + /* args can be empty, in which case check a 3 GB file which is created for + * this test (and then deleted). Or it can be a number, in which case + * that designates the size of the file that's created for this test (and + * then deleted). Or it can be the name of a file to use for the test, in + * which case it is *not* deleted. Note that in this last case, the data + * comparison might fail. + */ + static void realMain (String[] args) throws Throwable { + if (args.length > 0) { + try { + fileSize = Long.parseLong(args[0]); + System.out.println("Testing with file of size " + fileSize); + } catch (NumberFormatException ex) { + largeFile = new File(args[0]); + if (!largeFile.exists()) { + throw new Exception("Specified file " + args[0] + " does not exist"); + } + userFile = true; + System.out.println("Testing with user-provided file " + largeFile); + } + } + File testDir = null; + if (largeFile == null) { + testDir = new File(System.getProperty("test.scratch", "."), + "LargeZip"); + if (testDir.exists()) { + if (!testDir.delete()) { + throw new Exception("Cannot delete already-existing test directory"); + } + } + check(!testDir.exists() && testDir.mkdirs()); + largeFile = new File(testDir, "largezip.zip"); + createLargeZip(); + } + + readLargeZip(); + + if (!userFile && !debug) { + check(largeFile.delete()); + check(testDir.delete()); + } + } + + static void createLargeZip() throws Throwable { + int iterations = DATA_LEN / DATA_SIZE; + ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (int i = 0; i < iterations; i++) { + bb.putDouble(0, Math.random()); + baos.write(bb.array(), 0, DATA_SIZE); + } + data = baos.toByteArray(); + + ZipOutputStream zos = new ZipOutputStream( + new BufferedOutputStream(new FileOutputStream(largeFile))); + long length = 0; + while (length < fileSize) { + ZipEntry ze = new ZipEntry("entry-" + length); + lastEntryName = ze.getName(); + zos.putNextEntry(ze); + zos.write(data, 0, data.length); + zos.closeEntry(); + length = largeFile.length(); + } + System.out.println("Last entry written is " + lastEntryName); + zos.close(); + } + + static void readLargeZip() throws Throwable { + ZipFile zipFile = new ZipFile(largeFile); + ZipEntry entry = null; + String entryName = null; + int count = 0; + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + entry = entries.nextElement(); + entryName = entry.getName(); + count++; + } + System.out.println("Number of entries read: " + count); + System.out.println("Last entry read is " + entryName); + check(!entry.isDirectory()); + if (check(entryName.equals(lastEntryName))) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream is = zipFile.getInputStream(entry); + byte buf[] = new byte[4096]; + int len; + while ((len = is.read(buf)) >= 0) { + baos.write(buf, 0, len); + } + baos.close(); + is.close(); + check(Arrays.equals(data, baos.toByteArray())); + } + try { + zipFile.close(); + } catch (IOException ioe) {/* what can you do */ } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void pass(String msg) {System.out.println(msg); passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void unexpected(Throwable t, String msg) { + System.out.println(msg); failed++; t.printStackTrace();} + static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} + diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/GetFormat.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/GetFormat.java new file mode 100644 index 00000000000..5dbfbce300b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/GetFormat.java @@ -0,0 +1,41 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatConverter getFormat method */ + +import javax.sound.sampled.*; +import com.sun.media.sound.*; + +public class GetFormat { + + public static void main(String[] args) throws Exception { + AudioFormat frm = new AudioFormat(8000, 16, 1, true, false); + AudioFloatConverter conv = AudioFloatConverter.getConverter(frm); + if(!conv.getFormat().matches(frm)) + throw new RuntimeException("Incorrect audio format returned."); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/ToFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/ToFloatArray.java new file mode 100644 index 00000000000..c76097c0925 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/ToFloatArray.java @@ -0,0 +1,160 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatConverter toFloatArray method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ToFloatArray { + + public static void main(String[] args) throws Exception { + float[] testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + + // Check conversion using PCM_FLOAT + for (int big = 0; big < 2; big+=1) + for (int bits = 32; bits <= 64; bits+=32) { + AudioFormat frm = new AudioFormat( + AudioFloatConverter.PCM_FLOAT, + 44100, bits, 1, bits/8, + 44100, big==1); + byte[] buff = new byte[testarray.length * frm.getFrameSize()]; + float[] testarray2 = new float[testarray.length]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(frm); + conv.toByteArray(testarray, buff); + conv.toFloatArray(buff, testarray2); + for (int i = 0; i < testarray2.length; i++) { + if(Math.abs(testarray[i] - testarray2[i]) > 0.05) + throw new RuntimeException("Conversion failed for " + frm +" , arrays not equal enough!\n"); + } + } + + // Check conversion from float2byte and byte2float. + for (int big = 0; big < 2; big+=1) + for (int signed = 0; signed < 2; signed+=1) + for (int bits = 6; bits <= 40; bits+=2) { + AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1); + byte[] buff = new byte[testarray.length * frm.getFrameSize()]; + float[] testarray2 = new float[testarray.length]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(frm); + conv.toByteArray(testarray, buff); + conv.toFloatArray(buff, testarray2); + for (int i = 0; i < testarray2.length; i++) { + if(Math.abs(testarray[i] - testarray2[i]) > 0.05) + throw new RuntimeException("Conversion failed for " + frm +" , arrays not equal enough!\n"); + } + } + + // Check big/little + for (int big = 0; big < 2; big+=1) + for (int signed = 0; signed < 2; signed+=1) + for (int bits = 6; bits <= 40; bits+=2) { + AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1); + byte[] buff = new byte[testarray.length * frm.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(frm); + conv.toByteArray(testarray, buff); + byte[] buff2 = new byte[testarray.length * frm.getFrameSize()]; + int fs = frm.getFrameSize(); + for (int i = 0; i < buff2.length; i+=fs) { + for (int j = 0; j < fs; j++) { + buff2[i+(fs-j-1)] = buff[i+j]; + } + } + float[] testarray2 = new float[testarray.length]; + AudioFormat frm2 = new AudioFormat(44100, bits, 1, signed==1, big==0); + AudioFloatConverter.getConverter(frm2).toFloatArray(buff2, testarray2); + for (int i = 0; i < testarray2.length; i++) { + if(Math.abs(testarray[i] - testarray2[i]) > 0.05) + { + throw new RuntimeException("Conversion failed for " + frm +" to " + frm2 + " , arrays not equal enough!\n"); + } + } + } + + // Check signed/unsigned + for (int big = 0; big < 2; big+=1) + for (int signed = 0; signed < 2; signed+=1) + for (int bits = 6; bits <= 40; bits+=2) { + AudioFormat frm = new AudioFormat(44100, bits, 1, signed==1, big==1); + byte[] b = new byte[testarray.length * frm.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(frm); + conv.toByteArray(testarray, b); + int fs = frm.getFrameSize(); + if(big==1) + { + for(int i=0; i < b.length; i+= fs ) + b[i] = (b[i] >= 0) ? (byte)(0x80 | b[i]) : (byte)(0x7F & b[i]); + } + else + { + for(int i=(0+fs-1); i < b.length; i+= fs ) + b[i] = (b[i] >= 0) ? (byte)(0x80 | b[i]) : (byte)(0x7F & b[i]); + } + float[] testarray2 = new float[testarray.length]; + AudioFormat frm2 = new AudioFormat(44100, bits, 1, signed==0, big==1); + AudioFloatConverter.getConverter(frm2).toFloatArray(b, testarray2); + for (int i = 0; i < testarray2.length; i++) { + if(Math.abs(testarray[i] - testarray2[i]) > 0.05) + { + throw new RuntimeException("Conversion failed for " + frm +" to " + frm2 + " , arrays not equal enough!\n"); + } + } + } + + // Check if conversion 32->24, 24->16, 16->8 result in same float data + AudioFormat frm = new AudioFormat(44100, 40, 1, true, true); + byte[] b = new byte[testarray.length * frm.getFrameSize()]; + AudioFloatConverter.getConverter(frm).toByteArray(testarray, b); + for (int bits = 6; bits <= 40; bits+=2) { + AudioFormat frm2 = new AudioFormat(44100, bits, 1, true, true); + byte[] b2 = new byte[testarray.length * frm2.getFrameSize()]; + int fs1 = frm.getFrameSize(); + int fs2 = frm2.getFrameSize(); + int ii = 0; + for (int i = 0; i < b.length; i+=fs1) + for (int j = 0; j < fs2; j++) + b2[ii++] = b[i+j]; + float[] testarray2 = new float[testarray.length]; + AudioFloatConverter.getConverter(frm2).toFloatArray(b2, testarray2); + for (int i = 0; i < testarray2.length; i++) { + if(Math.abs(testarray[i] - testarray2[i]) > 0.05) + { + throw new RuntimeException("Conversion failed for " + frm +" to " + frm2 + " , arrays not equal enough!\n"); + } + } + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Available.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Available.java new file mode 100644 index 00000000000..49e51ede2ee --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Available.java @@ -0,0 +1,81 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream available method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Available { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float[] buff = new float[512]; + if(stream.available() != 1024) + throw new RuntimeException("stream.available return incorrect value."); + stream.read(buff); + if(stream.available() != 512) + throw new RuntimeException("stream.available return incorrect value."); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Close.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Close.java new file mode 100644 index 00000000000..76de1f91246 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Close.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream close method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Close { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + getStream1().close(); + getStream2().close(); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFormat.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFormat.java new file mode 100644 index 00000000000..b161ecb93e5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFormat.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream getFormat method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetFormat { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + if(!getStream1().getFormat().matches(format)) + throw new RuntimeException("Incorrect audio format returned."); + if(!getStream2().getFormat().matches(format)) + throw new RuntimeException("Incorrect audio format returned."); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFrameLength.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFrameLength.java new file mode 100644 index 00000000000..530896ae5e5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/GetFrameLength.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream getFrameLength method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetFrameLength { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + if(getStream1().getFrameLength() != 1024L) + throw new RuntimeException("Incorrect frame length returned."); + if(getStream2().getFrameLength() != 1024L) + throw new RuntimeException("Incorrect frame length returned."); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/MarkSupported.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/MarkSupported.java new file mode 100644 index 00000000000..6120494419a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/MarkSupported.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream markSupported method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class MarkSupported { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + if(!getStream1().markSupported()) + throw new RuntimeException("Mark not supported."); + if(!getStream2().markSupported()) + throw new RuntimeException("Mark not supported."); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Read.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Read.java new file mode 100644 index 00000000000..ab23fac2649 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Read.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream read method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Read { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float v = 0; + stream.skip(512); + v = stream.read(); + if(!(Math.abs(v - test_float_array[512]) < 0.0001)) + { + throw new RuntimeException("Read returned unexpected value."); + } + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArray.java new file mode 100644 index 00000000000..2fa1b481494 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArray.java @@ -0,0 +1,81 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream read(float[]) method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadFloatArray { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float[] buff = new float[1024]; + stream.read(buff); + for (int j = 0; j < buff.length; j++) + if(!(Math.abs(buff[j] - test_float_array[j]) < 0.0001)) + throw new RuntimeException("Incorrect data in buffer."); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArrayIntInt.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArrayIntInt.java new file mode 100644 index 00000000000..8393672739a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/ReadFloatArrayIntInt.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream read(float[], int, int) method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadFloatArrayIntInt { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float[] buff = new float[1024]; + stream.read(buff,0,512); + stream.read(buff,512,512); + for (int j = 0; j < buff.length; j++) + if(!(Math.abs(buff[j] - test_float_array[j]) < 0.0001)) + throw new RuntimeException("Incorrect data in buffer."); + + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Reset.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Reset.java new file mode 100644 index 00000000000..8553181639a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Reset.java @@ -0,0 +1,87 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream reset method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Reset { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float[] buff = new float[512]; + float[] buff2 = new float[512]; + stream.read(buff); + stream.mark(512); + stream.read(buff); + stream.reset(); + stream.read(buff2); + for (int j = 0; j < buff2.length; j++) + if(!(Math.abs(buff[j] - buff2[j]) < 0.0001)) + throw new RuntimeException("Incorrect data in buffer."); + + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Skip.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Skip.java new file mode 100644 index 00000000000..2388646a886 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatInputStream/Skip.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test AudioFloatInputStream skip method */ + +import java.io.*; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Skip { + + static float[] test_float_array; + static byte[] test_byte_array; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static AudioFloatInputStream getStream1() + { + return AudioFloatInputStream.getInputStream(format, test_byte_array, 0, test_byte_array.length); + } + + static AudioFloatInputStream getStream2() + { + AudioInputStream strm = new AudioInputStream(new ByteArrayInputStream(test_byte_array), format, 1024); + return AudioFloatInputStream.getInputStream(strm); + } + + static void setUp() throws Exception { + test_float_array = new float[1024]; + test_byte_array = new byte[1024*format.getFrameSize()]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + test_float_array[i] = (float)Math.sin(10*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + test_float_array[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + test_float_array[i] *= 0.3; + } + AudioFloatConverter.getConverter(format).toByteArray(test_float_array, test_byte_array); + } + + public static void main(String[] args) throws Exception { + setUp(); + + for (int i = 0; i < 2; i++) { + AudioFloatInputStream stream = null; + if(i == 0) stream = getStream1(); + if(i == 1) stream = getStream2(); + float[] buff = new float[512]; + stream.skip(512); + stream.read(buff); + for (int j = 0; j < buff.length; j++) + if(!(Math.abs(buff[j] - test_float_array[j+512]) < 0.0001)) + throw new RuntimeException("Incorrect data in buffer."); + + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankFile.java b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankFile.java new file mode 100644 index 00000000000..4b7b8e8975f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankFile.java @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test DLSSoundbankReader getSoundbank(File) method */ + +import java.io.File; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.DLSSoundbankReader; + +public class TestGetSoundbankFile { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.dls"); + Soundbank dls = new DLSSoundbankReader().getSoundbank(file); + assertTrue(dls.getInstruments().length == 1); + Patch patch = dls.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream.java b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream.java new file mode 100644 index 00000000000..f82d31cbfec --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test DLSSoundbankReader getSoundbank(InputStream) method */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.DLSSoundbankReader; + +public class TestGetSoundbankInputStream { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.dls"); + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + try + { + Soundbank dls = new DLSSoundbankReader().getSoundbank(bis); + assertTrue(dls.getInstruments().length == 1); + Patch patch = dls.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } + finally + { + bis.close(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream2.java b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream2.java new file mode 100644 index 00000000000..e0c393256c3 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankInputStream2.java @@ -0,0 +1,119 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test DLSSoundbankReader getSoundbank(InputStream) method using + very bad InputStream which can only read 1 byte at time */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.DLSSoundbankReader; + +public class TestGetSoundbankInputStream2 { + + private static class BadInputStream extends InputStream + { + + InputStream is; + + public BadInputStream(InputStream is) + { + this.is = is; + } + + public int read() throws IOException { + return is.read(); + } + + public int read(byte[] b, int off, int len) throws IOException { + if(len > 1) len = 1; + return is.read(b, off, len); + } + + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public long skip(long n) throws IOException { + if(n > 1) n = 1; + return is.skip(n); + } + + public int available() throws IOException { + int avail = is.available(); + if(avail > 1) avail = 1; + return avail; + } + + public void close() throws IOException { + is.close(); + } + + public synchronized void mark(int readlimit) { + is.mark(readlimit); + } + + public boolean markSupported() { + return is.markSupported(); + } + + public synchronized void reset() throws IOException { + is.reset(); + } + + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.dls"); + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + try + { + InputStream badis = new BadInputStream(bis); + Soundbank dls = new DLSSoundbankReader().getSoundbank(badis); + assertTrue(dls.getInstruments().length == 1); + Patch patch = dls.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } + finally + { + bis.close(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankUrl.java b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankUrl.java new file mode 100644 index 00000000000..502b753e7c5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/TestGetSoundbankUrl.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test DLSSoundbankReader getSoundbank(File) method */ + +import java.io.File; +import java.net.URL; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.DLSSoundbankReader; + +public class TestGetSoundbankUrl { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.dls"); + URL url = file.toURI().toURL(); + Soundbank dls = new DLSSoundbankReader().getSoundbank(url); + assertTrue(dls.getInstruments().length == 1); + Patch patch = dls.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/ding.dls b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/ding.dls new file mode 100644 index 00000000000..278f5f14ba4 Binary files /dev/null and b/jdk/test/javax/sound/midi/Gervill/DLSSoundbankReader/ding.dls differ diff --git a/jdk/test/javax/sound/midi/Gervill/EmergencySoundbank/TestCreateSoundbank.java b/jdk/test/javax/sound/midi/Gervill/EmergencySoundbank/TestCreateSoundbank.java new file mode 100644 index 00000000000..bf3ec3394f4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/EmergencySoundbank/TestCreateSoundbank.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test EmergencySoundbank createSoundbank() method */ + +import java.io.File; + +import javax.sound.midi.Instrument; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.EmergencySoundbank; +import com.sun.media.sound.ModelInstrument; +import com.sun.media.sound.ModelPatch; + +public class TestCreateSoundbank { + + public static void main(String[] args) throws Exception { + + Soundbank soundbank = EmergencySoundbank.createSoundbank(); + for (int i = 0; i < 128; i++) { + Patch patch = new ModelPatch(0, i, false); + ModelInstrument ins = (ModelInstrument)soundbank.getInstrument(patch); + if(ins == null) + throw new Exception("Instrument " + i + " is missing!"); + if(ins.getPerformers().length == 0) + throw new Exception("Instrument " + i + " doesn't have any performers!"); + } + Patch patch = new ModelPatch(0, 0, true); + ModelInstrument ins = (ModelInstrument)soundbank.getInstrument(patch); + if(ins == null) + throw new Exception("Drumkit instrument is missing!"); + if(ins.getPerformers().length == 0) + throw new Exception("Drumkit instrument doesn't have any performers!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetInputStream.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetInputStream.java new file mode 100644 index 00000000000..0a70adbaaef --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetInputStream.java @@ -0,0 +1,91 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer getInputStream method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetInputStream { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 2; i++) { + ModelByteBuffer buff; + if(i == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + + byte[] b = new byte[test_byte_array.length]; + buff.getInputStream().read(b); + for (int j = 0; j < b.length; j++) + if(b[i] != test_byte_array[i]) + throw new RuntimeException("Byte array compare fails!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetRoot.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetRoot.java new file mode 100644 index 00000000000..56a07869ad2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/GetRoot.java @@ -0,0 +1,82 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer getRoot method */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetRoot { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file); + ModelByteBuffer buff2 = buff.subbuffer(10, 10); + ModelByteBuffer buff3 = buff2.subbuffer(2, 2); + if(buff != buff3.getRoot()) + throw new RuntimeException("ModelByteBuffer doesn't return correct root!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Load.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Load.java new file mode 100644 index 00000000000..ce3ee25dc1a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Load.java @@ -0,0 +1,89 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer load method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file); + + buff.load(); + if(buff.array() == null) + throw new RuntimeException("buf is null!"); + if(buff.array().length != test_byte_array.length) + throw new RuntimeException("buff.array().length length is incorrect!"); + byte[] b = buff.array(); + for (int i = 0; i < b.length; i++) + if(test_byte_array[i] != b[i]) + throw new RuntimeException("buff.array() incorrect!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/LoadAll.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/LoadAll.java new file mode 100644 index 00000000000..a5f61edd15b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/LoadAll.java @@ -0,0 +1,93 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer loadAll method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class LoadAll { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file); + List col = new ArrayList(); + col.add(buff); + ModelByteBuffer.loadAll(col); + if(buff.array() == null) + throw new RuntimeException("buf is null!"); + if(buff.array().length != test_byte_array.length) + throw new RuntimeException("buff.array().length length is incorrect!"); + byte[] b = buff.array(); + for (int i = 0; i < b.length; i++) + if(test_byte_array[i] != b[i]) + throw new RuntimeException("buff.array() incorrect!"); + + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArray.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArray.java new file mode 100644 index 00000000000..d9f3940ba95 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArray.java @@ -0,0 +1,84 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer(byte[]) constructor */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferByteArray { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_byte_array); + if(buff.array() != test_byte_array) + throw new RuntimeException("buff.bytearray incorrect!"); + if(buff.capacity() != test_byte_array.length) + throw new RuntimeException("buff.capacity() incorrect!"); + if(buff.arrayOffset() != 0) + throw new RuntimeException("buff.arrayOffset not 0!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArrayIntInt.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArrayIntInt.java new file mode 100644 index 00000000000..e7b71e6b5ef --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferByteArrayIntInt.java @@ -0,0 +1,86 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer(byte[],int,int) constructor */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferByteArrayIntInt { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_byte_array,10,20); + if(buff.array() != test_byte_array) + throw new RuntimeException("buff.array() incorrect!"); + if(buff.capacity() != 20) + throw new RuntimeException("buff.capacity() not 20!"); + if(buff.arrayOffset() != 10) + throw new RuntimeException("buff.arrayOffset() not 10!"); + if(buff.getFile() != null) + throw new RuntimeException("buff.getFile() not null!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFile.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFile.java new file mode 100644 index 00000000000..677860cf06b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFile.java @@ -0,0 +1,88 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer(File) constructor */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferFile { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file); + if(buff.array() != null) + throw new RuntimeException("buff.array() not null!"); + if(buff.capacity() != test_file.length()) + throw new RuntimeException("buff.capacity() incorrect!"); + if(buff.arrayOffset() != 0) + throw new RuntimeException("buff.arrayOffset() not 0!"); + if(buff.getFile() != test_file) + throw new RuntimeException("buff.getFile() incorrect!"); + if(buff.getFilePointer() != 0) + throw new RuntimeException("buff.getFilePointer() not 0!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFileLongLong.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFileLongLong.java new file mode 100644 index 00000000000..100fb77232c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/NewModelByteBufferFileLongLong.java @@ -0,0 +1,88 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer(File,long,long) constructor */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferFileLongLong { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file,10,20); + if(buff.array() != null) + throw new RuntimeException("buff.array() not null!"); + if(buff.capacity() != 20) + throw new RuntimeException("buff.capacity() not 20!"); + if(buff.arrayOffset() != 0) + throw new RuntimeException("buff.arrayOffset() not 0!"); + if(buff.getFile() != test_file) + throw new RuntimeException("buff.getFile incorrect!"); + if(buff.getFilePointer() != 10) + throw new RuntimeException("buff.getFilePointer not 10!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Available.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Available.java new file mode 100644 index 00000000000..0543d74e915 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Available.java @@ -0,0 +1,107 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream available() method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Available { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + int ret = is.available(); + if(ret != capacity) + throw new RuntimeException("is.available() return unexpected value!"); + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Close.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Close.java new file mode 100644 index 00000000000..2b84ae0105b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Close.java @@ -0,0 +1,104 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream close method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Close { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkReset.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkReset.java new file mode 100644 index 00000000000..2755912a4a1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkReset.java @@ -0,0 +1,129 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream mark and reset methods */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class MarkReset { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + is.mark(1000); + int ret = is.available(); + int a = is.read(); + is.skip(75); + is.reset(); + if(is.available() != ret) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret)+") !"); + int b = is.read(); + if(a != b) + throw new RuntimeException( + "is doesn't return same value after reset (" + + a + "!="+b+") !"); + + is.skip(15); + ret = is.available(); + is.mark(1000); + is.reset(); + if(is.available() != ret) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret)+") !"); + + + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkSupported.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkSupported.java new file mode 100644 index 00000000000..5662cfff404 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/MarkSupported.java @@ -0,0 +1,106 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream markSupported() method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class MarkSupported { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + if(!is.markSupported()) + throw new RuntimeException("InputStream doesn't support mark/reset!"); + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Read.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Read.java new file mode 100644 index 00000000000..20502c77bf2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Read.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream read() method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Read { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + byte[] b = new byte[100]; + int ret = is.available(); + int n = is.read(); + if(n == -1) + throw new RuntimeException("is.read shouldn't return -1!"); + if(is.available() != ret - 1) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - 1)+") !"); + is.skip(5000); + if(is.read() != -1) + throw new RuntimeException( + "is.read() doesn't return -1!"); + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByte.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByte.java new file mode 100644 index 00000000000..aa08ca707b1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByte.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream read(byte[]) method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadByte { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + byte[] b = new byte[100]; + int ret = is.available(); + int n = is.read(b); + if(n == -1) + throw new RuntimeException("is.read shouldn't return -1!"); + if(is.available() != ret - n) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - n)+") !"); + is.skip(5000); + if(is.read(b) != -1) + throw new RuntimeException( + "is.read() doesn't return -1!"); + + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByteIntInt.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByteIntInt.java new file mode 100644 index 00000000000..6917de297b5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/ReadByteIntInt.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream read(byte[], int, int) method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadByteIntInt { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + byte[] b = new byte[100]; + int ret = is.available(); + int n = is.read(b, 7, 50); + if(n == -1) + throw new RuntimeException("is.read shouldn't return -1!"); + if(is.available() != ret - n) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - n)+") !"); + is.skip(5000); + if(is.read(b, 7, 50) != -1) + throw new RuntimeException( + "is.read() doesn't return -1!"); + + } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Skip.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Skip.java new file mode 100644 index 00000000000..6d943da3016 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/RandomFileInputStream/Skip.java @@ -0,0 +1,131 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer.RandomFileInputStream skip(long) method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Skip { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 8; i++) { + ModelByteBuffer buff; + if(i % 2 == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + if((i / 2) == 1) + buff.subbuffer(5); + if((i / 2) == 2) + buff.subbuffer(5,500); + if((i / 2) == 3) + buff.subbuffer(5,600,true); + + long capacity = buff.capacity(); + InputStream is = buff.getInputStream(); + try + { + int ret = is.available(); + long n = is.skip(75); + if(n == -1) + throw new RuntimeException("is.read shouldn't return -1!"); + if(is.available() != ret - n) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - n)+") !"); + + ret = is.available(); + n = is.skip(-100); + if(n != 0) + throw new RuntimeException("is.skip(-100) shouldn't skip values!"); + if(is.available() != ret - n) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - n)+") !"); + + ret = is.available(); + n = is.skip(5000); + if(is.available() != ret - n) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(ret - n)+") !"); + if(is.available() != 0) + throw new RuntimeException( + "is.available() returns incorrect value (" + + is.available() + "!="+(0)+") !"); } + finally + { + is.close(); + } + if(buff.capacity() != capacity) + throw new RuntimeException("Capacity variable should not change!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLong.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLong.java new file mode 100644 index 00000000000..83c0240a42e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLong.java @@ -0,0 +1,92 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer subbuffer(long) method */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SubbufferLong { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 2; i++) { + ModelByteBuffer buff; + if(i == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + + ModelByteBuffer buff2 = buff.subbuffer(10); + if(buff2.getFilePointer() != buff.getFilePointer()) + throw new RuntimeException("buff2.getFilePointer() incorreect!"); + if(buff2.arrayOffset() != 10) + throw new RuntimeException("buff2.arrayOffset() not 10!"); + if(buff2.capacity() != buff.capacity()-10) + throw new RuntimeException("buff2.capacity() not correct!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLong.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLong.java new file mode 100644 index 00000000000..70b22e91dc7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLong.java @@ -0,0 +1,92 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer subbuffer(long,long) method */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SubbufferLongLong { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 2; i++) { + ModelByteBuffer buff; + if(i == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + + ModelByteBuffer buff2 = buff.subbuffer(10,21); + if(buff2.getFilePointer() != buff.getFilePointer()) + throw new RuntimeException("buff2.getFilePointer() incorrect!"); + if(buff2.arrayOffset() != 10) + throw new RuntimeException("buff2.arrayOffset() not 10!"); + if(buff2.capacity() != 11) + throw new RuntimeException("buff2.capacity() not 11!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLongBoolean.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLongBoolean.java new file mode 100644 index 00000000000..d5907789c60 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/SubbufferLongLongBoolean.java @@ -0,0 +1,98 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer subbuffer(long,long,boolean) method */ + +import java.io.File; +import java.io.FileOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SubbufferLongLongBoolean { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 2; i++) { + ModelByteBuffer buff; + if(i == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + + ModelByteBuffer buff2 = buff.subbuffer(10,21,true); + if(buff2.getRoot() != buff2); + if(buff2.capacity() != 11); + if(i == 0) + { + if(buff2.getFilePointer() != buff.getFilePointer()+10) + throw new RuntimeException("buff2.getFilePointer() incorrect!"); + } + else + { + if(buff2.arrayOffset() != 10) + throw new RuntimeException("buff2.arrayOffset() not 10!"); + } + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Unload.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Unload.java new file mode 100644 index 00000000000..577210855a9 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/Unload.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer unload method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Unload { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + ModelByteBuffer buff = new ModelByteBuffer(test_file); + buff.load(); + buff.unload(); + if(buff.array() != null) + throw new RuntimeException("buff.array() not null!"); + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/WriteTo.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/WriteTo.java new file mode 100644 index 00000000000..804c48b6eb7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBuffer/WriteTo.java @@ -0,0 +1,92 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBuffer writeTo method */ + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class WriteTo { + + static float[] testarray; + static byte[] test_byte_array; + static File test_file; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + test_file = File.createTempFile("test", ".raw"); + FileOutputStream fos = new FileOutputStream(test_file); + fos.write(test_byte_array); + } + + static void tearDown() throws Exception { + if(!test_file.delete()) + test_file.deleteOnExit(); + } + + public static void main(String[] args) throws Exception { + try + { + setUp(); + + for (int i = 0; i < 2; i++) { + ModelByteBuffer buff; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if(i == 0) + buff = new ModelByteBuffer(test_file); + else + buff = new ModelByteBuffer(test_byte_array); + buff.writeTo(baos); + byte[] b = baos.toByteArray(); + for (int j = 0; j < b.length; j++) + if(b[i] != test_byte_array[i]) + throw new RuntimeException("baos.toByteArray() incorrect!"); + } + } + finally + { + tearDown(); + } + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetAttenuation.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetAttenuation.java new file mode 100644 index 00000000000..ff2c4cddd5b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetAttenuation.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable getAttenuation method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetAttenuation { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + wavetable.setAttenuation(10f); + if(wavetable.getAttenuation() != 10f) + throw new RuntimeException("wavetable.getAttenuation() not 10!"); + wavetable.setAttenuation(20f); + if(wavetable.getAttenuation() != 20f) + throw new RuntimeException("wavetable.getAttenuation() not 20!"); + + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetChannels.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetChannels.java new file mode 100644 index 00000000000..56673d9831e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetChannels.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable getChannels method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetChannels { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + AudioFormat format1 = new AudioFormat(44100, 16, 1, true, false); + AudioFormat format2 = new AudioFormat(44100, 16, 2, true, false); + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format1,10f); + if(wavetable.getChannels() != 1) + throw new RuntimeException("wavetable.getChannels() not 1!"); + wavetable = new ModelByteBufferWavetable(buffer,format2,10f); + if(wavetable.getChannels() != 2) + throw new RuntimeException("wavetable.getChannels() not 2!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopLength.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopLength.java new file mode 100644 index 00000000000..fcfd6dbfd91 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopLength.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable getLoopLength method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetLoopLength { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + wavetable.setLoopLength(10f); + if(wavetable.getLoopLength() != 10f) + throw new RuntimeException("wavetable.getLoopLength() not 10!"); + wavetable.setLoopLength(20f); + if(wavetable.getLoopLength() != 20f) + throw new RuntimeException("wavetable.getLoopLength() not 20!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopStart.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopStart.java new file mode 100644 index 00000000000..b2adb34d1c1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetLoopStart.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable getLoopStart method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetLoopStart { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + wavetable.setLoopStart(10f); + if(wavetable.getLoopStart() != 10f) + throw new RuntimeException("wavetable.getLoopStart() not 10!"); + wavetable.setLoopStart(20f); + if(wavetable.getLoopStart() != 20f) + throw new RuntimeException("wavetable.getLoopStart() not 20!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetPitchCorrection.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetPitchCorrection.java new file mode 100644 index 00000000000..8343283d069 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/GetPitchCorrection.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable getPitchCorrect method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetPitchCorrection { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + wavetable.setPitchcorrection(10f); + if(wavetable.getPitchcorrection() != 10f) + throw new RuntimeException("wavetable.getPitchcorrection() not 10!"); + wavetable.setPitchcorrection(20f); + if(wavetable.getPitchcorrection() != 20f) + throw new RuntimeException("wavetable.getPitchcorrection() not 20!"); + + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBuffer.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBuffer.java new file mode 100644 index 00000000000..c3d6ab1b030 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBuffer.java @@ -0,0 +1,94 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable(ModelByteBuffer) method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferWavetableModelByteBuffer { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer_wave); + if(wavetable.getBuffer() != buffer_wave) + throw new RuntimeException("wavetable.getBuffer() incorrect!"); + if(!wavetable.getFormat().matches(format)) + throw new RuntimeException("wavetable.getFormat() incorrect!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormat.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormat.java new file mode 100644 index 00000000000..6005f1f4969 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormat.java @@ -0,0 +1,94 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable(ModelByteBuffer, AudioFormat) method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferWavetableModelByteBufferAudioFormat { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + if(wavetable.getBuffer() != buffer) + throw new RuntimeException("wavetable.getBuffer() incorrect!"); + if(wavetable.getFormat() != format) + throw new RuntimeException("wavetable.getFormat() incorrect!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormatFloat.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormatFloat.java new file mode 100644 index 00000000000..c3073b62dba --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferAudioFormatFloat.java @@ -0,0 +1,94 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable(ModelByteBuffer, AudioFormat) method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferWavetableModelByteBufferAudioFormatFloat { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + if(wavetable.getBuffer() != buffer) + throw new RuntimeException("wavetable.getBuffer() incorrect!"); + if(!wavetable.getFormat().matches(format)) + throw new RuntimeException("wavetable.getFormat() incorrect!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferFloat.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferFloat.java new file mode 100644 index 00000000000..3ad0823c95a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/NewModelByteBufferWavetableModelByteBufferFloat.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable(ModelByteBuffer, AudioFormat, float) method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelByteBufferWavetableModelByteBufferFloat { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format,10f); + if(wavetable.getBuffer() != buffer) + throw new RuntimeException("wavetable.getBuffer() incorrect!"); + if(!wavetable.getFormat().matches(format)) + throw new RuntimeException("wavetable.getFormat() incorrect!"); + if(wavetable.getPitchcorrection() != 10f) + throw new RuntimeException("wavetable.getPitchcorrection() not 10!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Open.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Open.java new file mode 100644 index 00000000000..745cc1fa033 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Open.java @@ -0,0 +1,92 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable open method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Open { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + if(wavetable.open(44100) != null) + throw new RuntimeException("wavetable.open(44100) doesn't return null!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Set8BitExtensionBuffer.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Set8BitExtensionBuffer.java new file mode 100644 index 00000000000..24559f9f1e4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/Set8BitExtensionBuffer.java @@ -0,0 +1,119 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable set8BitExtensionBuffer method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Set8BitExtensionBuffer { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + static float compare(float[] a, float[] b) + { + float ac_error = 0; + int counter = 0; + for (int i = 0; i < a.length; i++) { + ac_error += Math.abs(a[i] - b[i]); + counter++; + } + return ac_error / ((float)counter); + + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer16_8,format,10f); + float[] f1 = new float[testarray.length]; + float[] f2 = new float[testarray.length]; + wavetable.openStream().read(f1); + wavetable.set8BitExtensionBuffer(buffer8); + if(wavetable.get8BitExtensionBuffer() != buffer8) + throw new RuntimeException("wavetable.get8BitExtensionBuffer() incorrect!"); + wavetable.openStream().read(f2); + // f2 should have more accurity than f1, + // about 256 times more, or 8 bits + float spec1 = compare(f1, testarray); + float spec2 = compare(f2, testarray); + if((spec1/spec2) <= 200) + throw new RuntimeException("(spec1/spec2) <= 200!"); + + + } + + + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/SetLoopType.java b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/SetLoopType.java new file mode 100644 index 00000000000..854815368bd --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/SetLoopType.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable SetLoopType method */ + +import java.io.ByteArrayOutputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetLoopType { + + static float[] testarray; + static byte[] test_byte_array; + static byte[] test_byte_array_8ext; + static AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false); + static ModelByteBuffer buffer; + static ModelByteBuffer buffer_wave; + static ModelByteBuffer buffer8; + static ModelByteBuffer buffer16_8; + static ModelByteBuffer buffer24; + + static void setUp() throws Exception { + testarray = new float[1024]; + for (int i = 0; i < 1024; i++) { + double ii = i / 1024.0; + ii = ii * ii; + testarray[i] = (float)Math.sin(10*ii*2*Math.PI); + testarray[i] += (float)Math.sin(1.731 + 2*ii*2*Math.PI); + testarray[i] += (float)Math.sin(0.231 + 6.3*ii*2*Math.PI); + testarray[i] *= 0.3; + } + test_byte_array = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format).toByteArray(testarray, test_byte_array); + buffer = new ModelByteBuffer(test_byte_array); + + byte[] test_byte_array2 = new byte[testarray.length*3]; + buffer24 = new ModelByteBuffer(test_byte_array2); + test_byte_array_8ext = new byte[testarray.length]; + byte[] test_byte_array_8_16 = new byte[testarray.length*2]; + AudioFloatConverter.getConverter(format24).toByteArray(testarray, test_byte_array2); + int ix = 0; + int x = 0; + for (int i = 0; i < test_byte_array_8ext.length; i++) { + test_byte_array_8ext[i] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + test_byte_array_8_16[x++] = test_byte_array2[ix++]; + } + buffer16_8 = new ModelByteBuffer(test_byte_array_8_16); + buffer8 = new ModelByteBuffer(test_byte_array_8ext); + + AudioInputStream ais = new AudioInputStream(buffer.getInputStream(), format, testarray.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos); + buffer_wave = new ModelByteBuffer(baos.toByteArray()); + } + + public static void main(String[] args) throws Exception { + + setUp(); + + ModelByteBufferWavetable wavetable = new ModelByteBufferWavetable(buffer,format); + wavetable.setLoopType(1); + if(wavetable.getLoopType() != 1) + throw new RuntimeException("wavetable.getLoopType() not 1!"); + wavetable.setLoopType(2); + if(wavetable.getLoopType() != 2) + throw new RuntimeException("wavetable.getLoopType() not 2!"); + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestination.java b/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestination.java new file mode 100644 index 00000000000..b46c156c212 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestination.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelDestination constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelDestination { + + public static void main(String[] args) throws Exception { + ModelDestination dest = new ModelDestination(); + if(dest.getIdentifier() != ModelDestination.DESTINATION_NONE) + throw new RuntimeException("dest.getIdentifier() is not equals ModelDestination.DESTINATION_NONE!"); + if(!(dest.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("dest.getTransform() is not instancoef ModelStandardTransform!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestinationModelIdentifier.java b/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestinationModelIdentifier.java new file mode 100644 index 00000000000..b64af94e8de --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelDestination/NewModelDestinationModelIdentifier.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelDestination(ModelIdentifier) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelDestinationModelIdentifier { + + public static void main(String[] args) throws Exception { + ModelDestination dest = new ModelDestination(ModelDestination.DESTINATION_EG1_ATTACK); + if(dest.getIdentifier() != ModelDestination.DESTINATION_EG1_ATTACK) + throw new RuntimeException("dest.getIdentifier() is not equals ModelDestination.DESTINATION_EG1_ATTACK!"); + if(!(dest.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("dest.getTransform() is not instancoef ModelStandardTransform!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetIdentifier.java b/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetIdentifier.java new file mode 100644 index 00000000000..64418fe271b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetIdentifier.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable setIdentifier(ModelIdentifier) method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetIdentifier { + + public static void main(String[] args) throws Exception { + ModelDestination dest = new ModelDestination(); + dest.setIdentifier(ModelDestination.DESTINATION_EG1_ATTACK); + if(dest.getIdentifier() != ModelDestination.DESTINATION_EG1_ATTACK) + throw new RuntimeException("dest.getIdentifier() is not equals ModelDestination.DESTINATION_EG1_ATTACK!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetTransform.java b/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetTransform.java new file mode 100644 index 00000000000..0b7e359b00e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelDestination/SetTransform.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelByteBufferWavetable setTransform(ModelTransform) method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetTransform{ + + public static void main(String[] args) throws Exception { + ModelDestination dest = new ModelDestination(); + ModelStandardTransform newtransform = new ModelStandardTransform(); + dest.setTransform(newtransform); + if(dest.getTransform() != newtransform) + throw new RuntimeException("dest.getTransform() is incorrect!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/EqualsObject.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/EqualsObject.java new file mode 100644 index 00000000000..b9235739beb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/EqualsObject.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier equals method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class EqualsObject { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a",1); + ModelIdentifier id2 = new ModelIdentifier("test","a",1); + ModelIdentifier id3 = new ModelIdentifier("test","a",2); + ModelIdentifier id4 = new ModelIdentifier("test","b",1); + ModelIdentifier id5 = new ModelIdentifier("hello","a",1); + if(!id.equals(id2)) + throw new RuntimeException("Compare failed!"); + if(id.equals(id3)) + throw new RuntimeException("Compare failed!"); + if(id.equals(id4)) + throw new RuntimeException("Compare failed!"); + if(id.equals(id5)) + throw new RuntimeException("Compare failed!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierString.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierString.java new file mode 100644 index 00000000000..d599a71de79 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierString.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier(String) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelIdentifierString { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test"); + if(!id.getObject().equals("test")) + throw new RuntimeException("id.getObject() doesn't return \"test\"!"); + if(id.getVariable() != null) + throw new RuntimeException("id.getVariable() doesn't return null!"); + if(id.getInstance() != 0) + throw new RuntimeException("id.getInstance() doesn't return 0!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringInt.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringInt.java new file mode 100644 index 00000000000..ecfee41c2ee --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringInt.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier(String, integer) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelIdentifierStringInt { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test",1); + if(!id.getObject().equals("test")) + throw new RuntimeException("id.getObject() doesn't return \"test\"!"); + if(id.getVariable() != null) + throw new RuntimeException("id.getVariable() doesn't return null!"); + if(id.getInstance() != 1) + throw new RuntimeException("id.getInstance() doesn't return 1!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringString.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringString.java new file mode 100644 index 00000000000..8b27369b88e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringString.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier(String,String) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelIdentifierStringString { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a"); + if(!id.getObject().equals("test")) + throw new RuntimeException("id.getObject() doesn't return \"test\"!"); + if(!id.getVariable().equals("a")) + throw new RuntimeException("id.getVariable() doesn't return \"a\"!"); + if(id.getInstance() != 0) + throw new RuntimeException("id.getInstance() doesn't return 0!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java new file mode 100644 index 00000000000..923ff12fe00 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier(String,String,int) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelIdentifierStringStringInt { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a",1);; + if(!id.getObject().equals("test")) + throw new RuntimeException("id.getObject() doesn't return \"test\"!"); + if(!id.getVariable().equals("a")) + throw new RuntimeException("id.getVariable() doesn't return \"a\"!"); + if(id.getInstance() != 1) + throw new RuntimeException("id.getInstance() doesn't return 1!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetInstance.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetInstance.java new file mode 100644 index 00000000000..92cf70a4823 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetInstance.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier setInstance method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetInstance { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a",1); + id.setInstance(2); + if(id.getInstance() != 2) + throw new RuntimeException("id.getInstance() doesn't return 2!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetObject.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetObject.java new file mode 100644 index 00000000000..d9f9b076629 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetObject.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier setObject method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetObject { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a",1); + id.setObject("hello"); + if(!id.getObject().equals("hello")) + throw new RuntimeException("id.getObject() does't return \"hello\"!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetVariable.java b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetVariable.java new file mode 100644 index 00000000000..82b2f5c22e7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelIdentifier/SetVariable.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelIdentifier setVariable method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetVariable { + + public static void main(String[] args) throws Exception { + ModelIdentifier id = new ModelIdentifier("test","a",1); + id.setVariable("b"); + if(!id.getVariable().equals("b")) + throw new RuntimeException("id.getVariable() does't return \"b\"!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/GetOscillators.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/GetOscillators.java new file mode 100644 index 00000000000..c148580f85c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/GetOscillators.java @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer getOscillators method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetOscillators { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + if(performer.getOscillators() == null) + throw new RuntimeException("performer.getOscillators() returned null!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetConnectionBlocks.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetConnectionBlocks.java new file mode 100644 index 00000000000..4d26e6bebc5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetConnectionBlocks.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setConnectionBlocks method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetConnectionBlocks { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + List newlist = new ArrayList(); + performer.setConnectionBlocks(newlist); + if(performer.getConnectionBlocks() != newlist) + throw new RuntimeException("performer.getConnectionBlocks() returned incorrect data!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetDefaultConnectionsEnabled.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetDefaultConnectionsEnabled.java new file mode 100644 index 00000000000..9b44f95a998 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetDefaultConnectionsEnabled.java @@ -0,0 +1,49 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setDefaultConnectionsEnabled method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetDefaultConnectionsEnabled { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setDefaultConnectionsEnabled(true); + if(performer.isDefaultConnectionsEnabled() != true) + throw new RuntimeException("performer.isAddDefaultConnectionsEnabled() didn't return true!"); + performer.setDefaultConnectionsEnabled(false); + if(performer.isDefaultConnectionsEnabled() != false) + throw new RuntimeException("performer.isAddDefaultConnectionsEnabled() didn't return false!"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetExclusiveClass.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetExclusiveClass.java new file mode 100644 index 00000000000..fb1053fa755 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetExclusiveClass.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setExclusiveClass method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetExclusiveClass { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setExclusiveClass(10); + if(performer.getExclusiveClass() != 10) + throw new RuntimeException("performer.getExclusiveClass() didn't return 10!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyFrom.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyFrom.java new file mode 100644 index 00000000000..27b9b314c68 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyFrom.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setKeyFrom method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetKeyFrom { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setKeyFrom(10); + if(performer.getKeyFrom() != 10) + throw new RuntimeException("performer.getKeyFrom() didn't return 10!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyTo.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyTo.java new file mode 100644 index 00000000000..e23e13235ac --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetKeyTo.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setKeyTo method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetKeyTo { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setKeyTo(10); + if(performer.getKeyTo() != 10) + throw new RuntimeException("performer.getKeyTo() didn't return 10!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetName.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetName.java new file mode 100644 index 00000000000..9c6fb129672 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetName.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setName method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetName { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setName("hello"); + if(!performer.getName().equals("hello")) + throw new RuntimeException("performer.getName() didn't return \"hello\"!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetSelfNonExclusive.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetSelfNonExclusive.java new file mode 100644 index 00000000000..86f5ea006b4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetSelfNonExclusive.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setSelfNonExclusive method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetSelfNonExclusive { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setSelfNonExclusive(true); + if(performer.isSelfNonExclusive() != true) + throw new RuntimeException("performer.isSelfNonExclusive() didn't return true!"); + performer.setSelfNonExclusive(false); + if(performer.isSelfNonExclusive() != false) + throw new RuntimeException("performer.isSelfNonExclusive() didn't return false!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelFrom.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelFrom.java new file mode 100644 index 00000000000..bdc4176d0ca --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelFrom.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setVelFrom method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetVelFrom { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setVelFrom(10); + if(performer.getVelFrom() != 10) + throw new RuntimeException("performer.getVelFrom() didn't return 10!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelTo.java b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelTo.java new file mode 100644 index 00000000000..cbba49007f4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelPerformer/SetVelTo.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelPerformer setVelTo method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetVelTo { + + public static void main(String[] args) throws Exception { + ModelPerformer performer = new ModelPerformer(); + performer.setVelTo(10); + if(performer.getVelTo() != 10) + throw new RuntimeException("performer.getVelTo() didn't return 10!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSource.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSource.java new file mode 100644 index 00000000000..e2766c30fed --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSource.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource() constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSource { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(); + if(src.getIdentifier() != ModelSource.SOURCE_NONE) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NONE!"); + if(!(src.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("src.getTransform() doesn't return object which is instance of ModelStandardTransform!"); + + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifier.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifier.java new file mode 100644 index 00000000000..00ae37699ab --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifier.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource(ModelIdentifier) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSourceModelIdentifier { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(ModelSource.SOURCE_NOTEON_KEYNUMBER); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + if(!(src.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("src.getTransform() doesn't return object which is instance of ModelStandardTransform!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBoolean.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBoolean.java new file mode 100644 index 00000000000..397718b2820 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBoolean.java @@ -0,0 +1,49 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource(ModelIdentifier,boolean) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSourceModelIdentifierBoolean { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(ModelSource.SOURCE_NOTEON_KEYNUMBER,ModelStandardTransform.DIRECTION_MAX2MIN); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + if(!(src.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("src.getTransform() doesn't return object which is instance of ModelStandardTransform!"); + ModelStandardTransform trans = (ModelStandardTransform)src.getTransform(); + if(trans.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("trans.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBoolean.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBoolean.java new file mode 100644 index 00000000000..1d8776a67be --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBoolean.java @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource(ModelIdentifier,boolean,boolean) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSourceModelIdentifierBooleanBoolean { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(ModelSource.SOURCE_NOTEON_KEYNUMBER,ModelStandardTransform.DIRECTION_MAX2MIN,ModelStandardTransform.POLARITY_BIPOLAR); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + if(!(src.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("src.getTransform() doesn't return object which is instance of ModelStandardTransform!"); + ModelStandardTransform trans = (ModelStandardTransform)src.getTransform(); + if(trans.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("trans.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + if(trans.getPolarity() != ModelStandardTransform.POLARITY_BIPOLAR) + throw new RuntimeException("trans.getPolarity() doesn't return ModelStandardTransform.POLARITY_BIPOLAR!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBooleanInt.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBooleanInt.java new file mode 100644 index 00000000000..fe66b1bccf9 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierBooleanBooleanInt.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource(ModelIdentifier,boolean,boolean,int) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSourceModelIdentifierBooleanBooleanInt { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(ModelSource.SOURCE_NOTEON_KEYNUMBER, + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_CONCAVE); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + if(!(src.getTransform() instanceof ModelStandardTransform)) + throw new RuntimeException("src.getTransform() doesn't return object which is instance of ModelStandardTransform!"); + ModelStandardTransform trans = (ModelStandardTransform)src.getTransform(); + if(trans.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("trans.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + if(trans.getPolarity() != ModelStandardTransform.POLARITY_BIPOLAR) + throw new RuntimeException("trans.getPolarity() doesn't return ModelStandardTransform.POLARITY_BIPOLAR!"); + if(trans.getTransform() != ModelStandardTransform.TRANSFORM_CONCAVE) + throw new RuntimeException("trans.getTransform() doesn't return ModelStandardTransform.TRANSFORM_CONCAVE!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierModelTransform.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierModelTransform.java new file mode 100644 index 00000000000..42c880ebb61 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/NewModelSourceModelIdentifierModelTransform.java @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource(ModelIdentifier,ModelTransform) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelSourceModelIdentifierModelTransform { + + public static void main(String[] args) throws Exception { + ModelStandardTransform trans = new ModelStandardTransform(); + ModelSource src = new ModelSource(ModelSource.SOURCE_NOTEON_KEYNUMBER, trans); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + if(src.getTransform() != trans) + throw new RuntimeException("src.getTransform() doesn't return trans!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/SetIdentifier.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/SetIdentifier.java new file mode 100644 index 00000000000..793231577eb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/SetIdentifier.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource setIdentifier method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetIdentifier { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(); + src.setIdentifier(ModelSource.SOURCE_NOTEON_KEYNUMBER); + if(src.getIdentifier() != ModelSource.SOURCE_NOTEON_KEYNUMBER) + throw new RuntimeException("src.getIdentifier() doesn't return ModelSource.SOURCE_NOTEON_KEYNUMBER!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelSource/SetTransform.java b/jdk/test/javax/sound/midi/Gervill/ModelSource/SetTransform.java new file mode 100644 index 00000000000..b36b4382e79 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelSource/SetTransform.java @@ -0,0 +1,46 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelSource setTransform method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetTransform { + + public static void main(String[] args) throws Exception { + ModelSource src = new ModelSource(); + ModelStandardTransform trans = new ModelStandardTransform(); + src.setTransform(trans); + if(src.getTransform() != trans) + throw new RuntimeException("src.getTransform() doesn't return trans!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransform.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransform.java new file mode 100644 index 00000000000..04fa862f1ee --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransform.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelStandardTransform { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + if(transform.getDirection() != ModelStandardTransform.DIRECTION_MIN2MAX) + throw new RuntimeException("transform.getDirection() doesn't return ModelStandardTransform.DIRECTION_MIN2MAX!"); + if(transform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) + throw new RuntimeException("transform.getPolarity() doesn't return ModelStandardTransform.POLARITY_UNIPOLAR!"); + if(transform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) + throw new RuntimeException("transform.getTransform() doesn't return ModelStandardTransform.TRANSFORM_LINEAR!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBoolean.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBoolean.java new file mode 100644 index 00000000000..6d6362944be --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBoolean.java @@ -0,0 +1,48 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform(boolean) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelStandardTransformBoolean { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(ModelStandardTransform.DIRECTION_MAX2MIN); + if(transform.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("transform.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + if(transform.getPolarity() != ModelStandardTransform.POLARITY_UNIPOLAR) + throw new RuntimeException("transform.getPolarity() doesn't return ModelStandardTransform.POLARITY_UNIPOLAR!"); + if(transform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) + throw new RuntimeException("transform.getTransform() doesn't return ModelStandardTransform.TRANSFORM_LINEAR!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBoolean.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBoolean.java new file mode 100644 index 00000000000..b3656a3cc3c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBoolean.java @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform(boolean,boolean) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelStandardTransformBooleanBoolean { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform( + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_BIPOLAR); + if(transform.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("transform.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + if(transform.getPolarity() != ModelStandardTransform.POLARITY_BIPOLAR) + throw new RuntimeException("transform.getPolarity() doesn't return ModelStandardTransform.POLARITY_BIPOLAR!"); + if(transform.getTransform() != ModelStandardTransform.TRANSFORM_LINEAR) + throw new RuntimeException("transform.getTransform() doesn't return ModelStandardTransform.TRANSFORM_LINEAR!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBooleanInt.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBooleanInt.java new file mode 100644 index 00000000000..06593ea9bf5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/NewModelStandardTransformBooleanBooleanInt.java @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform(boolean,boolean,int) constructor */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewModelStandardTransformBooleanBooleanInt { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform( + ModelStandardTransform.DIRECTION_MAX2MIN, + ModelStandardTransform.POLARITY_BIPOLAR, + ModelStandardTransform.TRANSFORM_CONVEX); + if(transform.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("transform.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + if(transform.getPolarity() != ModelStandardTransform.POLARITY_BIPOLAR) + throw new RuntimeException("transform.getPolarity() doesn't return ModelStandardTransform.POLARITY_BIPOLAR!"); + if(transform.getTransform() != ModelStandardTransform.TRANSFORM_CONVEX) + throw new RuntimeException("transform.getTransform() doesn't return ModelStandardTransform.TRANSFORM_CONVEX!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetDirection.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetDirection.java new file mode 100644 index 00000000000..b0941296dcb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetDirection.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform setDirection method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetDirection { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + if(transform.getDirection() != ModelStandardTransform.DIRECTION_MAX2MIN) + throw new RuntimeException("transform.getDirection() doesn't return ModelStandardTransform.DIRECTION_MAX2MIN!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetPolarity.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetPolarity.java new file mode 100644 index 00000000000..804e8b60820 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetPolarity.java @@ -0,0 +1,45 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform setPolarity method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetPolarity { + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(transform.getPolarity() != ModelStandardTransform.POLARITY_BIPOLAR) + throw new RuntimeException("transform.getPolarity() doesn't return ModelStandardTransform.POLARITY_BIPOLAR!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetTransform.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetTransform.java new file mode 100644 index 00000000000..8cfe08fbdbf --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/SetTransform.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform setTransform method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetTransform { + + + private static boolean checkLinearity(ModelStandardTransform transform) + { + double lastx = 0; + for (int p = 0; p < 2; p++) + for (int d = 0; d < 2; d++) + for (double i = 0; i < 1.0; i+=0.001) { + if(p == 0) + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(d == 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + double x = transform.transform(i); + if(i == 0) + lastx = x; + else + { + if(lastx - x > 0.2) return false; + lastx = x; + } + } + return true; + } + + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX); + if(transform.getTransform() != ModelStandardTransform.TRANSFORM_CONVEX) + throw new RuntimeException("transform.getTransform() doesn't return ModelStandardTransform.TRANSFORM_CONVEX!"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformAbsolute.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformAbsolute.java new file mode 100644 index 00000000000..a2f690dcc5c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformAbsolute.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform transform method */ + +import com.sun.media.sound.ModelStandardTransform; + +public class TransformAbsolute { + + private static boolean checkLinearity(ModelStandardTransform transform) + { + double lastx = 0; + for (int p = 0; p < 2; p++) + for (int d = 0; d < 2; d++) + for (double i = 0; i < 1.0; i+=0.001) { + if(p == 0) + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(d == 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + double x = transform.transform(i); + if(i == 0) + lastx = x; + else + { + if(lastx - x > 0.2) return false; + lastx = x; + } + } + return true; + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + + } + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_ABSOLUTE); + assertTrue(Math.abs(transform.transform(0.2f) - 0.2f) < 0.0001f); + assertTrue(Math.abs(transform.transform(-0.8f) - 0.8f) < 0.0001f); + assertTrue(checkLinearity(transform)); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConcave.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConcave.java new file mode 100644 index 00000000000..448658df19b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConcave.java @@ -0,0 +1,98 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform transform method */ + +import com.sun.media.sound.ModelStandardTransform; + +public class TransformConcave { + + private static boolean checkLinearity(ModelStandardTransform transform) + { + double lastx = 0; + for (int p = 0; p < 2; p++) + for (int d = 0; d < 2; d++) + for (double i = 0; i < 1.0; i+=0.001) { + if(p == 0) + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(d == 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + double x = transform.transform(i); + if(i == 0) + lastx = x; + else + { + if(lastx - x > 0.2) return false; + lastx = x; + } + } + return true; + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_CONCAVE); + assertTrue(checkLinearity(transform)); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.0f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.5f) < 0.5f); + assertTrue(Math.abs(transform.transform(1.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(1.0f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.5f) < 0.5f); + assertTrue(Math.abs(transform.transform(0.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.0f) + 1.0f) < 0.0001f); + assertTrue(transform.transform(0.25f) > -0.5f); + assertTrue(Math.abs(transform.transform(0.5f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.75f) < 0.5f); + assertTrue(Math.abs(transform.transform(1.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(1.0f) + 1.0f) < 0.0001f); + assertTrue(transform.transform(0.75f) > -0.5f); + assertTrue(Math.abs(transform.transform(0.50f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.25f) < 0.5f); + assertTrue(Math.abs(transform.transform(0.0f) - 1.0f) < 0.0001f); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConvex.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConvex.java new file mode 100644 index 00000000000..fc8ec5e2a63 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformConvex.java @@ -0,0 +1,98 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform transform method */ + +import com.sun.media.sound.ModelStandardTransform; + +public class TransformConvex { + + private static boolean checkLinearity(ModelStandardTransform transform) + { + double lastx = 0; + for (int p = 0; p < 2; p++) + for (int d = 0; d < 2; d++) + for (double i = 0; i < 1.0; i+=0.001) { + if(p == 0) + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(d == 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + double x = transform.transform(i); + if(i == 0) + lastx = x; + else + { + if(lastx - x > 0.2) return false; + lastx = x; + } + } + return true; + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_CONVEX); + assertTrue(checkLinearity(transform)); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.0f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.5f) > 0.5f); + assertTrue(Math.abs(transform.transform(1.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(1.0f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.5f) > 0.5f); + assertTrue(Math.abs(transform.transform(0.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.0f) + 1.0f) < 0.0001f); + assertTrue(transform.transform(0.25f) < -0.5f); + assertTrue(Math.abs(transform.transform(0.5f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.75f) > 0.5f); + assertTrue(Math.abs(transform.transform(1.0f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(1.0f) + 1.0f) < 0.0001f); + assertTrue(transform.transform(0.75f) < -0.5f); + assertTrue(Math.abs(transform.transform(0.50f) - 0.0f) < 0.0001f); + assertTrue(transform.transform(0.25f) > 0.5f); + assertTrue(Math.abs(transform.transform(0.0f) - 1.0f) < 0.0001f); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformLinear.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformLinear.java new file mode 100644 index 00000000000..1e575178684 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformLinear.java @@ -0,0 +1,90 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform transform method */ + +import com.sun.media.sound.ModelStandardTransform; + +public class TransformLinear { + + private static boolean checkLinearity(ModelStandardTransform transform) + { + double lastx = 0; + for (int p = 0; p < 2; p++) + for (int d = 0; d < 2; d++) + for (double i = 0; i < 1.0; i+=0.001) { + if(p == 0) + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + else + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + if(d == 0) + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + else + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + double x = transform.transform(i); + if(i == 0) + lastx = x; + else + { + if(lastx - x > 0.2) return false; + lastx = x; + } + } + return true; + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_LINEAR); + assertTrue(checkLinearity(transform)); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - 0.2f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - 0.8f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - 0.8f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - 0.2f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - (-0.6f)) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - (0.6f)) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - (0.6f)) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - (-0.6f)) < 0.0001f); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformSwitch.java b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformSwitch.java new file mode 100644 index 00000000000..21ba674e817 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/ModelStandardTransform/TransformSwitch.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test ModelStandardTransform transform method */ + +import com.sun.media.sound.ModelStandardTransform; + +public class TransformSwitch { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + ModelStandardTransform transform = new ModelStandardTransform(); + transform.setTransform(ModelStandardTransform.TRANSFORM_SWITCH); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - 0.0f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_UNIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - 1.0f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - 0.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MIN2MAX); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) + 1.0f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) - 1.0f) < 0.0001f); + + transform.setDirection(ModelStandardTransform.DIRECTION_MAX2MIN); + transform.setPolarity(ModelStandardTransform.POLARITY_BIPOLAR); + assertTrue(Math.abs(transform.transform(0.2f) - 1.0f) < 0.0001f); + assertTrue(Math.abs(transform.transform(0.8f) + 1.0f) < 0.0001f); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Available.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Available.java new file mode 100644 index 00000000000..6e7aa1f8d32 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Available.java @@ -0,0 +1,78 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader available method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Available { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeByte(10); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + RIFFReader readchunk = reader.nextChunk(); + int avail = readchunk.available(); + readchunk.readByte(); + assertEquals(avail - 1,readchunk.available()); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Close.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Close.java new file mode 100644 index 00000000000..5f1192d8bf1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Close.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader close method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Close { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + reader.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetFilePointer.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetFilePointer.java new file mode 100644 index 00000000000..7a04e6fe611 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetFilePointer.java @@ -0,0 +1,78 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader getFilePointer method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetFilePointer { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeByte(10); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + RIFFReader readchunk = reader.nextChunk(); + long p = readchunk.getFilePointer(); + readchunk.readByte(); + assertEquals(p+1,readchunk.getFilePointer()); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetSize.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetSize.java new file mode 100644 index 00000000000..e35eecd851d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/GetSize.java @@ -0,0 +1,77 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader getSize method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetSize { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeByte(10); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getSize(), (long)readchunk.available()); + readchunk.readByte(); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/HasNextChunk.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/HasNextChunk.java new file mode 100644 index 00000000000..b6137e51530 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/HasNextChunk.java @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader hasNextChunk method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class HasNextChunk { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean a) throws Exception + { + if(!a) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeByte(10); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertTrue(reader.hasNextChunk()); + RIFFReader readchunk = reader.nextChunk(); + readchunk.readByte(); + readchunk.close(); + assertTrue(!reader.hasNextChunk()); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Read.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Read.java new file mode 100644 index 00000000000..a4b0a07acf7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Read.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader read method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Read { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.write((byte)33); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(readchunk.read(), 33); + fis.close(); + reader = null; + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByte.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByte.java new file mode 100644 index 00000000000..7ee23c5fb6a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByte.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader read(byte) method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadByte { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeByte((byte)33); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals((int)reader.readByte(), 33); + fis.close(); + reader = null; + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByteArrayIntInt.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByteArrayIntInt.java new file mode 100644 index 00000000000..78e480a197b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadByteArrayIntInt.java @@ -0,0 +1,81 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader read(byte[], int, int) method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadByteArrayIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.write(new byte[] {1,2,3}); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(readchunk.read(), 1); + assertEquals(readchunk.read(), 2); + assertEquals(readchunk.read(), 3); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadInt.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadInt.java new file mode 100644 index 00000000000..5408a761ec8 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadInt.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readInt method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeInt(133); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readInt(), 133); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadLong.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadLong.java new file mode 100644 index 00000000000..290a22407e1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadLong.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readLong method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadLong { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeLong(133L); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readLong(), 133L); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadShort.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadShort.java new file mode 100644 index 00000000000..2b316d584e1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadShort.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readShort method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadShort { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeShort((short)133); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readShort(), (short)133); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadString.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadString.java new file mode 100644 index 00000000000..7985b1b3620 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadString.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readString method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadString { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeString("HELLO",5); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readString(5), "HELLO"); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedByte.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedByte.java new file mode 100644 index 00000000000..594862dc459 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedByte.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readUnsignedByte method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadUnsignedByte { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeUnsignedByte(77); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readUnsignedByte(), 77); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedInt.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedInt.java new file mode 100644 index 00000000000..d0e2847fa5f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedInt.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readUnsignedInt method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadUnsignedInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeUnsignedInt(55377); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readUnsignedInt(), 55377L); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedShort.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedShort.java new file mode 100644 index 00000000000..a61a0cb01f3 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/ReadUnsignedShort.java @@ -0,0 +1,79 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader readUnsignedShort method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ReadUnsignedShort { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.writeUnsignedShort(377); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(reader.readUnsignedShort(), 377); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Skip.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Skip.java new file mode 100644 index 00000000000..d3408c994fa --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/Skip.java @@ -0,0 +1,78 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffReader skip method */ + +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Skip { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + writer = new RIFFWriter(tempfile, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.write((byte)33); + chunk.write((byte)44); + writer.close(); + writer = null; + FileInputStream fis = new FileInputStream(tempfile); + reader = new RIFFReader(fis); + RIFFReader readchunk = reader.nextChunk(); + reader.skip(1); + assertEquals(readchunk.read(), 44); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/WriteOutputStream.java b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/WriteOutputStream.java new file mode 100644 index 00000000000..a7f5d23113f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/RiffReaderWriter/WriteOutputStream.java @@ -0,0 +1,81 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test RiffWriter(OutputStream) constructor */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class WriteOutputStream { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + RIFFWriter writer = null; + RIFFReader reader = null; + File tempfile = File.createTempFile("test",".riff"); + try + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + writer = new RIFFWriter(baos, "TEST"); + RIFFWriter chunk = writer.writeChunk("TSCH"); + chunk.write((byte)33); + writer.close(); + writer = null; + ByteArrayInputStream fis = new ByteArrayInputStream(baos.toByteArray()); + reader = new RIFFReader(fis); + assertEquals(reader.getFormat(), "RIFF"); + assertEquals(reader.getType(), "TEST"); + RIFFReader readchunk = reader.nextChunk(); + assertEquals(readchunk.getFormat(), "TSCH"); + assertEquals(readchunk.read(), 33); + fis.close(); + reader = null; + + + } + finally + { + if(writer != null) + writer.close(); + if(reader != null) + reader.close(); + + if(tempfile.exists()) + if(!tempfile.delete()) + tempfile.deleteOnExit(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankFile.java b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankFile.java new file mode 100644 index 00000000000..f526d6ef672 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankFile.java @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SF2SoundbankReader getSoundbank(File) method */ + +import java.io.File; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.SF2SoundbankReader; + +public class TestGetSoundbankFile { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.sf2"); + Soundbank sf2 = new SF2SoundbankReader().getSoundbank(file); + assertTrue(sf2.getInstruments().length == 1); + Patch patch = sf2.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream.java b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream.java new file mode 100644 index 00000000000..446b6f2dd8f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SF2SoundbankReader getSoundbank(InputStream) method */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.SF2SoundbankReader; + +public class TestGetSoundbankInputStream { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.sf2"); + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + try + { + Soundbank sf2 = new SF2SoundbankReader().getSoundbank(bis); + assertTrue(sf2.getInstruments().length == 1); + Patch patch = sf2.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } + finally + { + bis.close(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream2.java b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream2.java new file mode 100644 index 00000000000..a914a6446ed --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankInputStream2.java @@ -0,0 +1,119 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SF2SoundbankReader getSoundbank(InputStream) method using + very bad InputStream which can only read 1 byte at time */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.SF2SoundbankReader; + +public class TestGetSoundbankInputStream2 { + + private static class BadInputStream extends InputStream + { + + InputStream is; + + public BadInputStream(InputStream is) + { + this.is = is; + } + + public int read() throws IOException { + return is.read(); + } + + public int read(byte[] b, int off, int len) throws IOException { + if(len > 1) len = 1; + return is.read(b, off, len); + } + + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public long skip(long n) throws IOException { + if(n > 1) n = 1; + return is.skip(n); + } + + public int available() throws IOException { + int avail = is.available(); + if(avail > 1) avail = 1; + return avail; + } + + public void close() throws IOException { + is.close(); + } + + public synchronized void mark(int readlimit) { + is.mark(readlimit); + } + + public boolean markSupported() { + return is.markSupported(); + } + + public synchronized void reset() throws IOException { + is.reset(); + } + + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.sf2"); + FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + try + { + InputStream badis = new BadInputStream(bis); + Soundbank sf2 = new SF2SoundbankReader().getSoundbank(badis); + assertTrue(sf2.getInstruments().length == 1); + Patch patch = sf2.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } + finally + { + bis.close(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankUrl.java b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankUrl.java new file mode 100644 index 00000000000..16e39399bf4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/TestGetSoundbankUrl.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SF2SoundbankReader getSoundbank(File) method */ + +import java.io.File; +import java.net.URL; + +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; + +import com.sun.media.sound.SF2SoundbankReader; + +public class TestGetSoundbankUrl { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + File file = new File(System.getProperty("test.src", "."), "ding.sf2"); + URL url = file.toURI().toURL(); + Soundbank sf2 = new SF2SoundbankReader().getSoundbank(url); + assertTrue(sf2.getInstruments().length == 1); + Patch patch = sf2.getInstruments()[0].getPatch(); + assertTrue(patch.getProgram() == 0); + assertTrue(patch.getBank() == 0); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/ding.sf2 b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/ding.sf2 new file mode 100644 index 00000000000..86327f056a4 Binary files /dev/null and b/jdk/test/javax/sound/midi/Gervill/SF2SoundbankReader/ding.sf2 differ diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrument.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrument.java new file mode 100644 index 00000000000..f598461e4d1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrument.java @@ -0,0 +1,86 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelInstrument) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + SimpleInstrument subins = new SimpleInstrument(); + subins.add(performers[0]); + instrument.add(subins); + instrument.add(performers[1]); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntInt.java new file mode 100644 index 00000000000..682d68be4e6 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntInt.java @@ -0,0 +1,91 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelInstrument,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelInstrumentIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + SimpleInstrument subins = new SimpleInstrument(); + subins.add(performers[0]); + instrument.add(subins, 18, 40); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntInt.java new file mode 100644 index 00000000000..93fae266fda --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntInt.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelInstrument,int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelInstrumentIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + SimpleInstrument subins = new SimpleInstrument(); + subins.add(performers[0]); + instrument.add(subins,18,40,20,75); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntIntInt.java new file mode 100644 index 00000000000..9417fdd4047 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelInstrumentIntIntIntIntInt.java @@ -0,0 +1,97 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelInstrument,int,int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelInstrumentIntIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + SimpleInstrument subins = new SimpleInstrument(); + subins.add(performers[0]); + instrument.add(subins,18,40,20,75,12); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(12, performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformer.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformer.java new file mode 100644 index 00000000000..42f4645aa42 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformer.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformer { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers[0]); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArray.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArray.java new file mode 100644 index 00000000000..93d7d5dd662 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArray.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer[]) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerArray { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntInt.java new file mode 100644 index 00000000000..c01c84923ea --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntInt.java @@ -0,0 +1,89 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer[],int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerArrayIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers,18,40); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntInt.java new file mode 100644 index 00000000000..acbecc5ab57 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntInt.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer[],int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerArrayIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers,18,40,20,75); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntIntInt.java new file mode 100644 index 00000000000..f74cc7b7fbb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerArrayIntIntIntIntInt.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer[],int,int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerArrayIntIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers,18,40,20,75,12); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(12, performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntInt.java new file mode 100644 index 00000000000..6ba9a611782 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntInt.java @@ -0,0 +1,89 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers[0],18,40); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntInt.java new file mode 100644 index 00000000000..a8f35587319 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntInt.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer,int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers[0],18,40,20,75); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(performers[i].getExclusiveClass(), performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntIntInt.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntIntInt.java new file mode 100644 index 00000000000..2651a382f7f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/AddModelPerformerIntIntIntIntInt.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument add(ModelPerformer,int,int,int,int,int) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddModelPerformerIntIntIntIntInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers[0],18,40,20,75,12); + ModelPerformer[] performers2 = instrument.getPerformers(); + for (int i = 0; i < performers2.length; i++) { + assertEquals(performers[i].getConnectionBlocks(), performers2[i].getConnectionBlocks()); + assertEquals(12, performers2[i].getExclusiveClass()); + if(performers[i].getKeyFrom() < 18) + assertEquals(18, performers2[i].getKeyFrom()); + else + assertEquals(performers[i].getKeyFrom(), performers2[i].getKeyFrom()); + if(performers[i].getKeyTo() > 40) + assertEquals(40, performers2[i].getKeyTo()); + else + assertEquals(performers[i].getKeyTo(), performers2[i].getKeyTo()); + if(performers[i].getVelFrom() < 20) + assertEquals(20, performers2[i].getVelFrom()); + else + assertEquals(performers[i].getVelFrom(), performers2[i].getVelFrom()); + if(performers[i].getVelTo() > 75) + assertEquals(75, performers2[i].getVelTo()); + else + assertEquals(performers[i].getVelTo(), performers2[i].getVelTo()); + assertEquals(performers[i].getOscillators(), performers2[i].getOscillators()); + assertEquals(performers[i].isSelfNonExclusive(), performers2[i].isSelfNonExclusive()); + assertEquals(performers[i].isDefaultConnectionsEnabled(), performers2[i].isDefaultConnectionsEnabled()); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/Clear.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/Clear.java new file mode 100644 index 00000000000..30210155764 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/Clear.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument clear method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Clear { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.add(performers[0]); + instrument.clear(); + assertEquals(instrument.getPerformers().length, 0); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetName.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetName.java new file mode 100644 index 00000000000..721ec22543f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetName.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument setName(String) method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetName { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + instrument.setName("hello"); + assertEquals(instrument.getName(), "hello"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetPatch.java b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetPatch.java new file mode 100644 index 00000000000..6ddf1406cba --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleInstrument/SetPatch.java @@ -0,0 +1,75 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleInstrument setPatch(Patch) method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetPatch { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + + SimpleInstrument instrument = new SimpleInstrument(); + + ModelPerformer[] performers = new ModelPerformer[2]; + + performers[0] = new ModelPerformer(); + performers[0].setExclusiveClass(1); + performers[0].setKeyFrom(36); + performers[0].setKeyTo(48); + performers[0].setVelFrom(16); + performers[0].setVelTo(80); + performers[0].setSelfNonExclusive(true); + performers[0].setDefaultConnectionsEnabled(false); + performers[0].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[0].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + performers[1] = new ModelPerformer(); + performers[1].setExclusiveClass(0); + performers[1].setKeyFrom(12); + performers[1].setKeyTo(24); + performers[1].setVelFrom(20); + performers[1].setVelTo(90); + performers[1].setSelfNonExclusive(false); + performers[0].setDefaultConnectionsEnabled(true); + performers[1].getConnectionBlocks().add(new ModelConnectionBlock()); + performers[1].getOscillators().add(new ModelByteBufferWavetable(new ModelByteBuffer(new byte[] {1,2,3}))); + + Patch patch = new Patch(0,36); + instrument.setPatch(patch); + assertEquals(instrument.getPatch().getProgram(), patch.getProgram()); + assertEquals(instrument.getPatch().getBank(), patch.getBank()); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddInstrument.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddInstrument.java new file mode 100644 index 00000000000..e980d931445 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddInstrument.java @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank addInstrument method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(3,7)); + soundbank.addInstrument(ins); + assertEquals(soundbank.getInstruments().length, 1); + assertEquals(soundbank.getInstruments()[0], ins); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddResource.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddResource.java new file mode 100644 index 00000000000..5af64ff20ec --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/AddResource.java @@ -0,0 +1,52 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank addResource method */ + +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AddResource { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + SoundbankResource res = new SoundbankResource(soundbank, "test", null) { + public Object getData() { + return null; + }}; + soundbank.addResource(res); + assertEquals(soundbank.getResources().length, 1); + assertEquals(soundbank.getResources()[0], res); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/GetInstrument.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/GetInstrument.java new file mode 100644 index 00000000000..2aeda8ccad9 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/GetInstrument.java @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank getInstrument method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(3,7)); + soundbank.addInstrument(ins); + assertEquals(soundbank.getInstrument(new Patch(3,7)), ins); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/RemoveInstrument.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/RemoveInstrument.java new file mode 100644 index 00000000000..b90a065b5cf --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/RemoveInstrument.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank removeInstrument method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class RemoveInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean a) throws Exception + { + if(!a) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(3,7)); + soundbank.addInstrument(ins); + soundbank.removeInstrument(ins); + assertEquals(soundbank.getInstruments().length, 0); + assertTrue(soundbank.getInstrument(new Patch(3,7)) == null); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetDescription.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetDescription.java new file mode 100644 index 00000000000..0f20ea11010 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetDescription.java @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank setDescription method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetDescription { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + soundbank.setDescription("hello"); + assertEquals(soundbank.getDescription(), "hello"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetName.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetName.java new file mode 100644 index 00000000000..712749e12f3 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetName.java @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank setName method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetName { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + soundbank.setName("hello"); + assertEquals(soundbank.getName(), "hello"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVendor.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVendor.java new file mode 100644 index 00000000000..78cb57d26ce --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVendor.java @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank setVendor method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetVendor { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + soundbank.setVendor("hello"); + assertEquals(soundbank.getVendor(), "hello"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVersion.java b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVersion.java new file mode 100644 index 00000000000..24be16fbf4f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SimpleSoundbank/SetVersion.java @@ -0,0 +1,47 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SimpleSoundbank setVersion method */ + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SetVersion { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + public static void main(String[] args) throws Exception { + SimpleSoundbank soundbank = new SimpleSoundbank(); + soundbank.setVersion("hello"); + assertEquals(soundbank.getVersion(), "hello"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Array.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Array.java new file mode 100644 index 00000000000..c400d645d95 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Array.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioBuffer array method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Array { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioFormat frm = new AudioFormat(8000, 8, 1, true, false); + SoftAudioBuffer buff = new SoftAudioBuffer(377, frm); + float[] ar = buff.array(); + assertEquals(ar.length, 377); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Clear.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Clear.java new file mode 100644 index 00000000000..c26518487e0 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Clear.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioBuffer clear method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Clear { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioFormat frm = new AudioFormat(8000, 8, 1, true, false); + SoftAudioBuffer buff = new SoftAudioBuffer(377, frm); + buff.array(); + assertTrue(!buff.isSilent()); + buff.clear(); + assertTrue(buff.isSilent()); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Get.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Get.java new file mode 100644 index 00000000000..4658f7d12a0 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/Get.java @@ -0,0 +1,68 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioBuffer get method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Get { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioFormat frm = new AudioFormat(8000, 16, 1, true, false); + SoftAudioBuffer buff = new SoftAudioBuffer(100, frm); + float[] ar = buff.array(); + for (int i = 0; i < ar.length; i++) { + if(i % 2 == 0) + ar[i] = 1; + if(i % 2 == 0) + ar[i] = -0.5f; + } + + byte[] bbuff = new byte[ar.length*frm.getFrameSize()]; + buff.get(bbuff, 0); + float[] ar2 = new float[ar.length]; + AudioFloatConverter.getConverter(frm).toFloatArray(bbuff, ar2); + + for (int i = 0; i < ar2.length; i++) + if(Math.abs(ar[i] - ar2[i]) > 0.001) + throw new Exception("conversion failure!"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/NewSoftAudioBuffer.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/NewSoftAudioBuffer.java new file mode 100644 index 00000000000..191c4218076 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioBuffer/NewSoftAudioBuffer.java @@ -0,0 +1,55 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioBuffer constructor */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewSoftAudioBuffer { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioFormat frm = new AudioFormat(8000, 8, 1, true, false); + SoftAudioBuffer buff = new SoftAudioBuffer(377, frm); + assertEquals(buff.getSize(), 377); + assertEquals(buff.getFormat(), frm); + assertTrue(buff.isSilent()); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/DummySourceDataLine.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/DummySourceDataLine.java new file mode 100644 index 00000000000..c9ea327c53b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/DummySourceDataLine.java @@ -0,0 +1,232 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.ArrayList; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.Control.Type; + +import com.sun.media.sound.AudioFloatConverter; + +/** + * This is a SourceDataLine simulator used for testing SoftSynthesizer + * without using real SourceDataLine / Audio Device. + * + * @author Karl Helgason + */ + +public class DummySourceDataLine implements SourceDataLine { + + private int bufferSize = -1; + + private AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false); + + private DataLine.Info sourceLineInfo; + + private boolean active = false; + + private long framepos = 0; + + private boolean opened = false; + + private int framesize = 0; + + public DummySourceDataLine() + { + ArrayList formats = new ArrayList(); + for (int channels = 1; channels <= 2; channels++) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + for (int bits = 16; bits < 32; bits += 8) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + } + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, true)); + } + AudioFormat[] formats_array = formats.toArray(new AudioFormat[formats + .size()]); + sourceLineInfo = new DataLine.Info(SourceDataLine.class, + formats_array, AudioSystem.NOT_SPECIFIED, + AudioSystem.NOT_SPECIFIED); + + } + + public void open() throws LineUnavailableException { + open(format); + } + + public void open(AudioFormat format) throws LineUnavailableException { + if (bufferSize == -1) + bufferSize = ((int) (format.getFrameRate() / 2)) + * format.getFrameSize(); + open(format, bufferSize); + } + + public void open(AudioFormat format, int bufferSize) + throws LineUnavailableException { + this.format = format; + this.bufferSize = bufferSize; + this.framesize = format.getFrameSize(); + opened = true; + } + + public boolean isOpen() { + return opened; + } + + public int write(byte[] b, int off, int len) { + if (!isOpen()) + return 0; + if (len % framesize != 0) + throw new IllegalArgumentException( + "Number of bytes does not represent an integral number of sample frames."); + + + int flen = len / framesize; + framepos += flen; + + long time = (long) (flen * (1000.0 / (double) getFormat() + .getSampleRate())); + try { + Thread.sleep(time); + } catch (InterruptedException e) { + e.printStackTrace(); + return 0; + } + + return len; + } + + public int available() { + return 0; + } + + public void drain() { + } + + public void flush() { + } + + public int getBufferSize() { + return bufferSize; + } + + public AudioFormat getFormat() { + return format; + } + + public int getFramePosition() { + return (int) getLongFramePosition(); + } + + public float getLevel() { + return AudioSystem.NOT_SPECIFIED; + } + + public long getLongFramePosition() { + return framepos; + } + + public long getMicrosecondPosition() { + return (long) (getLongFramePosition() * (1000000.0 / (double) getFormat() + .getSampleRate())); + } + + public boolean isActive() { + return active; + } + + public boolean isRunning() { + return active; + } + + public void start() { + active = true; + } + + public void stop() { + active = false; + } + + public void close() { + stop(); + } + + public Control getControl(Type control) { + throw new IllegalArgumentException("Unsupported control type : " + + control); + } + + public Control[] getControls() { + return new Control[0]; + } + + public javax.sound.sampled.Line.Info getLineInfo() { + return sourceLineInfo; + } + + public boolean isControlSupported(Type control) { + return false; + } + + public void addLineListener(LineListener listener) { + } + + public void removeLineListener(LineListener listener) { + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetFormat.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetFormat.java new file mode 100644 index 00000000000..6dc24e9daf2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetFormat.java @@ -0,0 +1,61 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioSynthesizer getFormat method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetFormat { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + AudioFormat defformat = synth.getFormat(); + assertTrue(defformat != null); + synth.openStream(null, null); + assertTrue(synth.getFormat().toString().equals(defformat.toString())); + synth.close(); + AudioFormat custformat = new AudioFormat(8000, 16, 1, true, false); + synth.openStream(custformat, null); + assertTrue(synth.getFormat().toString().equals(custformat.toString())); + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetPropertyInfo.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetPropertyInfo.java new file mode 100644 index 00000000000..1aae1eb0767 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/GetPropertyInfo.java @@ -0,0 +1,53 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioSynthesizer getPropertyInfo method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetPropertyInfo { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + AudioSynthesizerPropertyInfo[] info = synth.getPropertyInfo(null); + assertTrue(info != null); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/Open.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/Open.java new file mode 100644 index 00000000000..0df5862cc11 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/Open.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioSynthesizer open method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Open { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + SourceDataLine line = new DummySourceDataLine(); //AudioSystem.getSourceDataLine(new AudioFormat(44100, 16, 2, true, false)); + synth.open(line, null); + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/OpenStream.java b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/OpenStream.java new file mode 100644 index 00000000000..937f74afdb4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftAudioSynthesizer/OpenStream.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftAudioSynthesizer openStream method */ + +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class OpenStream { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.isOpen()); + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllNotesOff.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllNotesOff.java new file mode 100644 index 00000000000..05813fe8ecb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllNotesOff.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel allNotesOff method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AllNotesOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.noteOn(60, 64); + soft.read(1); + VoiceStatus[] v = soft.synth.getVoiceStatus(); + assertEquals(v[0].note, 60); + assertEquals(v[0].active, true); + channel.allNotesOff(); + soft.read(1); + v = soft.synth.getVoiceStatus(); + assertEquals(v[0].active, false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllSoundOff.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllSoundOff.java new file mode 100644 index 00000000000..aa6fcaab5b4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/AllSoundOff.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel allSoundOff method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class AllSoundOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.noteOn(60, 64); + soft.read(1); + VoiceStatus[] v = soft.synth.getVoiceStatus(); + assertEquals(v[0].note, 60); + assertEquals(v[0].active, true); + channel.allSoundOff(); + soft.read(1); + v = soft.synth.getVoiceStatus(); + assertEquals(v[0].active, false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/ChannelPressure.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ChannelPressure.java new file mode 100644 index 00000000000..5e8f00c4006 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ChannelPressure.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel channelPressure method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ChannelPressure { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setChannelPressure(10); + assertEquals(channel.getChannelPressure(), 10); + channel.setChannelPressure(90); + assertEquals(channel.getChannelPressure(), 90); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/Controller.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Controller.java new file mode 100644 index 00000000000..dff142381f8 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Controller.java @@ -0,0 +1,62 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel controller method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Controller { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + for (int i = 0; i < 128; i++) { + if(i == 0 || i == 32) continue; + channel.controlChange(i, 10); + assertEquals(channel.getController(i), 10); + channel.controlChange(i, 100); + assertEquals(channel.getController(i), 100); + } + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/LocalControl.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/LocalControl.java new file mode 100644 index 00000000000..074eb56800e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/LocalControl.java @@ -0,0 +1,60 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel localControl method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class LocalControl { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + // Local control not supported + // because this is a software synthesizer + // localControl() should always return false + assertEquals(channel.localControl(true), false); + assertEquals(channel.localControl(false), false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mono.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mono.java new file mode 100644 index 00000000000..148a8652680 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mono.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel mono method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Mono { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setMono(true); + assertEquals(channel.getMono(), true); + channel.setMono(false); + assertEquals(channel.getMono(), false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mute.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mute.java new file mode 100644 index 00000000000..d66824ce7c5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Mute.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel mute method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Mute { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setMute(true); + assertEquals(channel.getMute(), true); + channel.setMute(false); + assertEquals(channel.getMute(), false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff.java new file mode 100644 index 00000000000..839b568f14f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel noteOff method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NoteOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.noteOn(60, 64); + soft.read(1); + VoiceStatus[] v = soft.synth.getVoiceStatus(); + assertEquals(v[0].note, 60); + assertEquals(v[0].active, true); + channel.noteOff(60); + soft.read(1); + v = soft.synth.getVoiceStatus();; + assertEquals(v[0].active, false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java new file mode 100644 index 00000000000..01f1cd15336 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel noteOff method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NoteOff2 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.noteOn(60, 64); + soft.read(1); + VoiceStatus[] v = soft.synth.getVoiceStatus(); + assertEquals(v[0].note, 60); + assertEquals(v[0].active, true); + channel.noteOff(60); + soft.read(1); + v = soft.synth.getVoiceStatus();; + assertEquals(v[0].active, false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOn.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOn.java new file mode 100644 index 00000000000..810236e4523 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/NoteOn.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel noteOn method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NoteOn { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.noteOn(60, 64); + soft.read(1); + VoiceStatus[] v = soft.synth.getVoiceStatus(); + assertEquals(v[0].note, 60); + assertEquals(v[0].active, true); + channel.noteOn(60, 0); + soft.read(1); + v = soft.synth.getVoiceStatus(); + assertEquals(v[0].active, false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/Omni.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Omni.java new file mode 100644 index 00000000000..2801aa72786 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Omni.java @@ -0,0 +1,61 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel omni method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Omni { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setOmni(true); + // Poly or Omni not supported by GM2 + // getOmni() should always return false + assertEquals(channel.getOmni(), false); + channel.setOmni(false); + assertEquals(channel.getOmni(), false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/PitchBend.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/PitchBend.java new file mode 100644 index 00000000000..64ab6cbe7e0 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/PitchBend.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel pitchBend method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class PitchBend { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setPitchBend(10); + assertEquals(channel.getPitchBend(), 10); + channel.setPitchBend(9000); + assertEquals(channel.getPitchBend(), 9000); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/PolyPressure.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/PolyPressure.java new file mode 100644 index 00000000000..f69aab00876 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/PolyPressure.java @@ -0,0 +1,61 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel polyPressure method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class PolyPressure { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + for (int i = 0; i < 128; i++) { + channel.setPolyPressure(i, 10); + assertEquals(channel.getPolyPressure(i),10); + channel.setPolyPressure(i, 100); + assertEquals(channel.getPolyPressure(i),100); + } + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/ProgramChange.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ProgramChange.java new file mode 100644 index 00000000000..c202e51dd68 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ProgramChange.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel programChange method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProgramChange { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.programChange(36); + assertEquals(channel.getProgram(), 36); + channel.programChange(48); + assertEquals(channel.getProgram(), 48); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/ResetAllControllers.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ResetAllControllers.java new file mode 100644 index 00000000000..6fcd7743d8b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/ResetAllControllers.java @@ -0,0 +1,132 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel resetAllControllers method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ResetAllControllers { + + public static boolean[] dontResetControls = new boolean[128]; + static { + for (int i = 0; i < dontResetControls.length; i++) + dontResetControls[i] = false; + + dontResetControls[0] = true; // Bank Select (MSB) + dontResetControls[32] = true; // Bank Select (LSB) + dontResetControls[7] = true; // Channel Volume (MSB) + dontResetControls[8] = true; // Balance (MSB) + dontResetControls[10] = true; // Pan (MSB) + dontResetControls[11] = true; // Expression (MSB) + dontResetControls[91] = true; // Effects 1 Depth (default: Reverb Send) + dontResetControls[92] = true; // Effects 2 Depth (default: Tremolo Depth) + dontResetControls[93] = true; // Effects 3 Depth (default: Chorus Send) + dontResetControls[94] = true; // Effects 4 Depth (default: Celeste [Detune] Depth) + dontResetControls[95] = true; // Effects 5 Depth (default: Phaser Depth) + dontResetControls[70] = true; // Sound Controller 1 (default: Sound Variation) + dontResetControls[71] = true; // Sound Controller 2 (default: Timbre / Harmonic Quality) + dontResetControls[72] = true; // Sound Controller 3 (default: Release Time) + dontResetControls[73] = true; // Sound Controller 4 (default: Attack Time) + dontResetControls[74] = true; // Sound Controller 5 (default: Brightness) + dontResetControls[75] = true; // Sound Controller 6 (GM2 default: Decay Time) + dontResetControls[76] = true; // Sound Controller 7 (GM2 default: Vibrato Rate) + dontResetControls[77] = true; // Sound Controller 8 (GM2 default: Vibrato Depth) + dontResetControls[78] = true; // Sound Controller 9 (GM2 default: Vibrato Delay) + dontResetControls[79] = true; // Sound Controller 10 (GM2 default: Undefined) + dontResetControls[120] = true; // All Sound Off + dontResetControls[121] = true; // Reset All Controllers + dontResetControls[122] = true; // Local Control On/Off + dontResetControls[123] = true; // All Notes Off + dontResetControls[124] = true; // Omni Mode Off + dontResetControls[125] = true; // Omni Mode On + dontResetControls[126] = true; // Poly Mode Off + dontResetControls[127] = true; // Poly Mode On + + dontResetControls[6] = true; // Data Entry (MSB) + dontResetControls[38] = true; // Data Entry (LSB) + dontResetControls[96] = true; // Data Increment + dontResetControls[97] = true; // Data Decrement + dontResetControls[98] = true; // Non-Registered Parameter Number (LSB) + dontResetControls[99] = true; // Non-Registered Parameter Number(MSB) + dontResetControls[100] = true; // RPN = Null + dontResetControls[101] = true; // RPN = Null + } + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + // First let all controls contain non-default values + for (int i = 0; i < 128; i++) + channel.setPolyPressure(i, 10); + channel.setChannelPressure(10); + channel.setPitchBend(2192); + for (int i = 0; i < 120; i++) + channel.controlChange(i, 1); + channel.resetAllControllers(); + + // Now check if resetAllControllers did what it was suppose to do + + for (int i = 0; i < 128; i++) + assertEquals(channel.getPolyPressure(i), 0); + assertEquals(channel.getChannelPressure(), 0); + assertEquals(channel.getPitchBend(),8192); + for (int i = 0; i < 120; i++) + if(!dontResetControls[i]) + assertEquals(channel.getController(i), 0); + assertEquals(channel.getController(71), 64); // Filter Resonance + assertEquals(channel.getController(72), 64); // Release Time + assertEquals(channel.getController(73), 64); // Attack Time + assertEquals(channel.getController(74), 64); // Brightness + assertEquals(channel.getController(75), 64); // Decay Time + assertEquals(channel.getController(76), 64); // Vibrato Rate + assertEquals(channel.getController(77), 64); // Vibrato Depth + assertEquals(channel.getController(78), 64); // Vibrato Delay + assertEquals(channel.getController(8), 64); // Balance + assertEquals(channel.getController(11), 127); // Expression + assertEquals(channel.getController(98), 127); // NRPN Null + assertEquals(channel.getController(99), 127); // NRPN Null + assertEquals(channel.getController(100), 127); // RPN = Null + assertEquals(channel.getController(101), 127); // RPN = Null + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/SoftTestUtils.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/SoftTestUtils.java new file mode 100644 index 00000000000..f29983983d2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/SoftTestUtils.java @@ -0,0 +1,111 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.IOException; + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SoftTestUtils { + + public AudioSynthesizer synth = new SoftSynthesizer(); + public AudioInputStream stream; + public byte[] tmpbuffer = new byte[1024]; + + public static SF2Soundbank createTestSoundBank() + { + SF2Soundbank sf2 = new SF2Soundbank(); + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + float[] data = new float[44100+1000]; + float fr = 440/format.getSampleRate(); + for (int i = 0; i < data.length; i++) + data[i] = (float)Math.sin(i*fr*2*Math.PI); + byte[] bdata = new byte[data.length*format.getFrameSize()]; + AudioFloatConverter.getConverter(format).toByteArray(data, bdata); + SF2Sample sample = new SF2Sample(sf2); + sample.setName("Test Sample"); + sample.setData(bdata); + sample.setStartLoop(500); + sample.setEndLoop(data.length - 500); + sample.setSampleRate((long) format.getSampleRate()); + sample.setOriginalPitch(69); + sf2.addResource(sample); + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Test Layer"); + sf2.addResource(layer); + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.setSample(sample); + layer.getRegions().add(region); + SF2Instrument ins = new SF2Instrument(sf2); + ins.setName("Test Instrument"); + sf2.addInstrument(ins); + SF2InstrumentRegion insregion = new SF2InstrumentRegion(); + insregion.setLayer(layer); + ins.getRegions().add(insregion); + + return sf2; + } + + public SoftTestUtils() throws Exception { + stream = synth.openStream(null, null); + synth.unloadAllInstruments(synth.getDefaultSoundbank()); + synth.loadAllInstruments(createTestSoundBank()); + } + + public void close() throws Exception { + stream.close(); + stream = null; + synth.close(); + synth = null; + } + + public void read(double seconds) throws IOException + { + int bufflen = + stream.getFormat().getFrameSize() * + (int)(stream.getFormat().getFrameRate() * seconds); + while(bufflen != 0) + { + if(bufflen > 1024) + bufflen -= stream.read(tmpbuffer,0,1024); + else + bufflen -= stream.read(tmpbuffer,0, bufflen); + } + } + + public VoiceStatus findVoice(int channel, int note) { + VoiceStatus[] v = synth.getVoiceStatus(); + for (int k = 0; k < v.length; k++) + if(v[k].active) + if(v[k].channel == channel) + if(v[k].note == note) + return v[k]; + return null; + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftChannel/Solo.java b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Solo.java new file mode 100644 index 00000000000..a575ac6b6c7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftChannel/Solo.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftChannel solo method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Solo { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + + channel.setSolo(true); + assertEquals(channel.getSolo(), true); + channel.setSolo(false); + assertEquals(channel.getSolo(), false); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftCubicResampler/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftCubicResampler/Interpolate.java new file mode 100644 index 00000000000..ed50cff4344 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftCubicResampler/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftCubicResampler interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftCubicResampler resampler = new SoftCubicResampler(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.005) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.005) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.005) + fail("Interpolation failed, error="+max); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLanczosResampler/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftLanczosResampler/Interpolate.java new file mode 100644 index 00000000000..664952dbbd2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLanczosResampler/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLanczosResampler interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftLanczosResampler resampler = new SoftLanczosResampler(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.01) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.01) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.01) + fail("Interpolation failed, error="+max); + } +} \ No newline at end of file diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix.java new file mode 100644 index 00000000000..ed64ae24e4c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix.java @@ -0,0 +1,96 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_mix { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer in2 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out2 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] testdata2 = new float[in2.getSize()]; + float[] n1a = in1.array(); + float[] n2a = in2.array(); + float[] out1a = out1.array(); + float[] out2a = out2.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*0.9f; + testdata2[i] = (float)Math.sin(i*0.4)*0.9f; + n1a[i] = testdata1[i]; + n2a[i] = testdata2[i]; + out1a[i] = 1; + out2a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(true); + limiter.setInput(0, in1); + limiter.setInput(1, in2); + limiter.setOutput(0, out1); + limiter.setOutput(1, out2); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i] - testdata1[i] - 1) > 0.00001) + throw new Exception("input != output"); + if(Math.abs(out2a[i] - testdata2[i] - 1) > 0.00001) + throw new Exception("input != output"); + } + + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono.java new file mode 100644 index 00000000000..2a78f5b1e1e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_mix_mono { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(new AudioFormat(44100, 16, 1, true, false), null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] n1a = in1.array(); + float[] out1a = out1.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*0.9f; + n1a[i] = testdata1[i]; + out1a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(true); + limiter.setInput(0, in1); + limiter.setOutput(0, out1); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i] - testdata1[i] - 1) > 0.00001) + throw new Exception("input != output"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono_overdrive.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono_overdrive.java new file mode 100644 index 00000000000..f99670d06f5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_mono_overdrive.java @@ -0,0 +1,84 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_mix_mono_overdrive { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(new AudioFormat(44100, 16, 1, true, false), null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] n1a = in1.array(); + float[] out1a = out1.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*2.5f; + n1a[i] = testdata1[i]; + out1a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(true); + limiter.setInput(0, in1); + limiter.setOutput(0, out1); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i]-1) > 1.0) + throw new Exception("abs(output)>1"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_overdrive.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_overdrive.java new file mode 100644 index 00000000000..1161c010c48 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_mix_overdrive.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_mix_overdrive { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer in2 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out2 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] testdata2 = new float[in2.getSize()]; + float[] n1a = in1.array(); + float[] n2a = in2.array(); + float[] out1a = out1.array(); + float[] out2a = out2.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*2.5f; + testdata2[i] = (float)Math.sin(i*0.4)*2.5f; + n1a[i] = testdata1[i]; + n2a[i] = testdata2[i]; + out1a[i] = 1; + out2a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(true); + limiter.setInput(0, in1); + limiter.setInput(1, in2); + limiter.setOutput(0, out1); + limiter.setOutput(1, out2); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i]-1) > 1.0) + throw new Exception("abs(output)>1"); + if(Math.abs(out2a[i]-1) > 1.0) + throw new Exception("abs(output)>1"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal.java new file mode 100644 index 00000000000..af3b145bf55 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_normal { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer in2 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out2 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] testdata2 = new float[in2.getSize()]; + float[] n1a = in1.array(); + float[] n2a = in2.array(); + float[] out1a = out1.array(); + float[] out2a = out2.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*0.9f; + testdata2[i] = (float)Math.sin(i*0.4)*0.9f; + n1a[i] = testdata1[i]; + n2a[i] = testdata2[i]; + out1a[i] = 1; + out2a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(false); + limiter.setInput(0, in1); + limiter.setInput(1, in2); + limiter.setOutput(0, out1); + limiter.setOutput(1, out2); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i] - testdata1[i]) > 0.00001) + throw new Exception("input != output"); + if(Math.abs(out2a[i] - testdata2[i]) > 0.00001) + throw new Exception("input != output"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal_mono.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal_mono.java new file mode 100644 index 00000000000..beb7db7d416 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_normal_mono.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_normal_mono { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(new AudioFormat(44100, 16, 1, true, false), null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] n1a = in1.array(); + float[] out1a = out1.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*0.9f; + n1a[i] = testdata1[i]; + out1a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(false); + limiter.setInput(0, in1); + limiter.setOutput(0, out1); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i] - testdata1[i]) > 0.00001) + throw new Exception("input != output"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive.java new file mode 100644 index 00000000000..8df2be7bb18 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_overdrive { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer in2 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out2 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] testdata2 = new float[in2.getSize()]; + float[] n1a = in1.array(); + float[] n2a = in2.array(); + float[] out1a = out1.array(); + float[] out2a = out2.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*2.5f; + testdata2[i] = (float)Math.sin(i*0.4)*2.5f; + n1a[i] = testdata1[i]; + n2a[i] = testdata2[i]; + out1a[i] = 1; + out2a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(false); + limiter.setInput(0, in1); + limiter.setInput(1, in2); + limiter.setOutput(0, out1); + limiter.setOutput(1, out2); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i]) > 1.0) + throw new Exception("abs(output)>1"); + if(Math.abs(out2a[i]) > 1.0) + throw new Exception("abs(output)>1"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive_mono.java b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive_mono.java new file mode 100644 index 00000000000..882bc48a4c7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLimiter/ProcessAudio_replace_overdrive_mono.java @@ -0,0 +1,83 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLimiter processAudio method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class ProcessAudio_replace_overdrive_mono { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftSynthesizer synth = new SoftSynthesizer(); + synth.openStream(new AudioFormat(44100, 16, 1, true, false), null); + + SoftAudioBuffer in1 = new SoftAudioBuffer(250, synth.getFormat()); + SoftAudioBuffer out1 = new SoftAudioBuffer(250, synth.getFormat()); + + float[] testdata1 = new float[in1.getSize()]; + float[] n1a = in1.array(); + float[] out1a = out1.array(); + for (int i = 0; i < n1a.length; i++) { + testdata1[i] = (float)Math.sin(i*0.3)*2.5f; + n1a[i] = testdata1[i]; + out1a[i] = 1; + } + + SoftLimiter limiter = new SoftLimiter(); + limiter.init(44100, 147); + limiter.setMixMode(false); + limiter.setInput(0, in1); + limiter.setOutput(0, out1); + limiter.processControlLogic(); + limiter.processAudio(); + limiter.processControlLogic(); + limiter.processAudio(); + // Limiter should delay audio by one buffer, + // and there should almost no different in output v.s. input + for (int i = 0; i < n1a.length; i++) { + if(Math.abs(out1a[i]) > 1.0) + throw new Exception("abs(output)>1"); + } + + synth.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler/Interpolate.java new file mode 100644 index 00000000000..c75b007ea60 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLinearResampler interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftLinearResampler resampler = new SoftLinearResampler(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.001) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.001) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.001) + fail("Interpolation failed, error="+max); + } +} \ No newline at end of file diff --git a/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler2/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler2/Interpolate.java new file mode 100644 index 00000000000..c3822abd225 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftLinearResampler2/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftLinearResampler2 interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftLinearResampler2 resampler = new SoftLinearResampler2(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + } +} \ No newline at end of file diff --git a/jdk/test/javax/sound/midi/Gervill/SoftPointResampler/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftPointResampler/Interpolate.java new file mode 100644 index 00000000000..743469ab869 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftPointResampler/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftPointResampler interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftPointResampler resampler = new SoftPointResampler(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.2) + fail("Interpolation failed, error="+max); + } +} \ No newline at end of file diff --git a/jdk/test/javax/sound/midi/Gervill/SoftProvider/GetDevice.java b/jdk/test/javax/sound/midi/Gervill/SoftProvider/GetDevice.java new file mode 100644 index 00000000000..74ba903b64b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftProvider/GetDevice.java @@ -0,0 +1,70 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftProvider getDevice method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetDevice { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + + private static class FakeInfo extends Info { + public FakeInfo() { + super("a", "b", "c", "d"); + } + } + + public static void main(String[] args) throws Exception { + SoftProvider provider = new SoftProvider(); + Info[] infos = provider.getDeviceInfo(); + assertTrue(infos.length > 0); + for (int i = 0; i < infos.length; i++) { + assertTrue(infos[i] != null); + MidiDevice d = provider.getDevice(infos[i]); + assertTrue(d instanceof SoftSynthesizer); + } + assertTrue(provider.getDevice(new FakeInfo()) == null); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Close.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Close.java new file mode 100644 index 00000000000..2347918e492 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Close.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver close method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Close { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + assertEquals(soft.synth.getReceivers().size(), 1); + receiver.close(); + assertEquals(soft.synth.getReceivers().size(), 0); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ActiveSense.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ActiveSense.java new file mode 100644 index 00000000000..bee35b3763a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ActiveSense.java @@ -0,0 +1,82 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_ActiveSense { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void sendActiveSens(Receiver r) throws Exception + { + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.ACTIVE_SENSING); + r.send(smsg, -1); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + sendActiveSens(receiver); + + // 1. Check if notes are keept active + // if send active sens every 200-300 msec + + sendActiveSens(receiver); + channel.noteOn(60, 64); + assertTrue(soft.findVoice(0,60) != null); + for (int i = 0; i < 10; i++) { + soft.read(0.2); // read 200 msec + sendActiveSens(receiver); + assertTrue(soft.findVoice(0,60) != null); + } + // 2. Now we stop send active sense message + // and the note should be killed off + soft.read(2); + assertTrue(soft.findVoice(0,60) == null); + + + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllNotesOff.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllNotesOff.java new file mode 100644 index 00000000000..39a42d6d537 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllNotesOff.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_AllNotesOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + channel.noteOn(60, 64); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 123,0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllSoundOff.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllSoundOff.java new file mode 100644 index 00000000000..bfb236cdaf1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_AllSoundOff.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_AllSoundOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + channel.noteOn(60, 64); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 120,0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ChannelPressure.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ChannelPressure.java new file mode 100644 index 00000000000..62d4378d1a8 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ChannelPressure.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_ChannelPressure { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CHANNEL_PRESSURE,0, 10,0); + receiver.send(smsg, -1); + assertEquals(channel.getChannelPressure(), 10); + smsg.setMessage(ShortMessage.CHANNEL_PRESSURE,0, 90,0); + receiver.send(smsg, -1); + assertEquals(channel.getChannelPressure(), 90); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Controller.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Controller.java new file mode 100644 index 00000000000..ff4ef6f87be --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Controller.java @@ -0,0 +1,66 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_Controller { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + for (int i = 0; i < 128; i++) { + if(i == 0 || i == 32) continue; + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, i,10); + receiver.send(smsg, -1); + assertEquals(channel.getController(i), 10); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, i,100); + receiver.send(smsg, -1); + assertEquals(channel.getController(i), 100); + } + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Mono.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Mono.java new file mode 100644 index 00000000000..ab07878c0e5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Mono.java @@ -0,0 +1,75 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_Mono { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 126,100); + receiver.send(smsg, -1); + assertEquals(channel.getMono(), false); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 126,1); + receiver.send(smsg, -1); + assertEquals(channel.getMono(), true); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 127,0); + receiver.send(smsg, -1); + assertEquals(channel.getMono(), false); + + // Check if send mono triggers AllNotesOff + channel.noteOn(60, 64); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 127,0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOff.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOff.java new file mode 100644 index 00000000000..02685037561 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOff.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_NoteOff { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 64); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + smsg.setMessage(ShortMessage.NOTE_OFF,0, 60, 0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn.java new file mode 100644 index 00000000000..d701833ada0 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_NoteOn { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 64); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_AllChannels.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_AllChannels.java new file mode 100644 index 00000000000..1e9a4099ae7 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_AllChannels.java @@ -0,0 +1,71 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_NoteOn_AllChannels { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + for (int i = 0; i < 15; i++) { + if(i == 9) i++; + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.NOTE_ON,i, 60, 64); + receiver.send(smsg, -1); + soft.read(1); + VoiceStatus voice = soft.findVoice(i,60); + assertTrue(voice != null); + smsg.setMessage(ShortMessage.NOTE_ON,i, 60, 0); + receiver.send(smsg, -1); + soft.read(1); + voice = soft.findVoice(i,60); + assertTrue(voice == null); + soft.read(1); + } + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Delayed.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Delayed.java new file mode 100644 index 00000000000..a64c673b068 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Delayed.java @@ -0,0 +1,67 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_NoteOn_Delayed { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 64); + receiver.send(smsg, 2000000); // Delay sending note for 2 sec + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + soft.read(2); + assertTrue(soft.findVoice(0,60) != null); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Multiple.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Multiple.java new file mode 100644 index 00000000000..183ae5f679f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_NoteOn_Multiple.java @@ -0,0 +1,76 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_NoteOn_Multiple { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 64); + receiver.send(smsg, -1); + smsg.setMessage(ShortMessage.NOTE_ON,0, 61, 64); + receiver.send(smsg, -1); + smsg.setMessage(ShortMessage.NOTE_ON,0, 62, 64); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + assertTrue(soft.findVoice(0,61) != null); + assertTrue(soft.findVoice(0,62) != null); + + smsg.setMessage(ShortMessage.NOTE_ON,0, 60, 0); + receiver.send(smsg, -1); + smsg.setMessage(ShortMessage.NOTE_ON,0, 61, 0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + assertTrue(soft.findVoice(0,61) == null); + assertTrue(soft.findVoice(0,62) != null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Omni.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Omni.java new file mode 100644 index 00000000000..a3cd1b29f42 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_Omni.java @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_Omni { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 125,0); + receiver.send(smsg, -1); + // Poly or Omni not supported by GM2 + // getOmni() should always return false + assertEquals(channel.getOmni(), false); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 124,0); + receiver.send(smsg, -1); + assertEquals(channel.getOmni(), false); + + // Check if send omni triggers AllNotesOff + channel.noteOn(60, 64); + soft.read(1); + assertTrue(soft.findVoice(0,60) != null); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 124,0); + receiver.send(smsg, -1); + soft.read(1); + assertTrue(soft.findVoice(0,60) == null); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PitchBend.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PitchBend.java new file mode 100644 index 00000000000..097b9bbe2f4 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PitchBend.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_PitchBend { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.PITCH_BEND,0, 10,0); + receiver.send(smsg, -1); + assertEquals(channel.getPitchBend(), 10); + smsg.setMessage(ShortMessage.PITCH_BEND,0, 9000%128,9000/128); + receiver.send(smsg, -1); + assertEquals(channel.getPitchBend(), 9000); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PolyPressure.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PolyPressure.java new file mode 100644 index 00000000000..decd2d21555 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_PolyPressure.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_PolyPressure { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + for (int i = 0; i < 128; i++) { + smsg.setMessage(ShortMessage.POLY_PRESSURE,0, i, 10); + receiver.send(smsg, -1); + assertEquals(channel.getPolyPressure(i),10); + smsg.setMessage(ShortMessage.POLY_PRESSURE,0, i, 100); + receiver.send(smsg, -1); + assertEquals(channel.getPolyPressure(i),100); + } + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ProgramChange.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ProgramChange.java new file mode 100644 index 00000000000..a8b33e95749 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ProgramChange.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_ProgramChange { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.PROGRAM_CHANGE,0, 36,0); + receiver.send(smsg, -1); + assertEquals(channel.getProgram(), 36); + smsg.setMessage(ShortMessage.PROGRAM_CHANGE,0, 48,0); + receiver.send(smsg, -1); + assertEquals(channel.getProgram(), 48); + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ResetAllControllers.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ResetAllControllers.java new file mode 100644 index 00000000000..62f6e2e8c61 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/Send_ResetAllControllers.java @@ -0,0 +1,136 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftReceiver send method */ + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Send_ResetAllControllers { + + public static boolean[] dontResetControls = new boolean[128]; + static { + for (int i = 0; i < dontResetControls.length; i++) + dontResetControls[i] = false; + + dontResetControls[0] = true; // Bank Select (MSB) + dontResetControls[32] = true; // Bank Select (LSB) + dontResetControls[7] = true; // Channel Volume (MSB) + dontResetControls[8] = true; // Balance (MSB) + dontResetControls[10] = true; // Pan (MSB) + dontResetControls[11] = true; // Expression (MSB) + dontResetControls[91] = true; // Effects 1 Depth (default: Reverb Send) + dontResetControls[92] = true; // Effects 2 Depth (default: Tremolo Depth) + dontResetControls[93] = true; // Effects 3 Depth (default: Chorus Send) + dontResetControls[94] = true; // Effects 4 Depth (default: Celeste [Detune] Depth) + dontResetControls[95] = true; // Effects 5 Depth (default: Phaser Depth) + dontResetControls[70] = true; // Sound Controller 1 (default: Sound Variation) + dontResetControls[71] = true; // Sound Controller 2 (default: Timbre / Harmonic Quality) + dontResetControls[72] = true; // Sound Controller 3 (default: Release Time) + dontResetControls[73] = true; // Sound Controller 4 (default: Attack Time) + dontResetControls[74] = true; // Sound Controller 5 (default: Brightness) + dontResetControls[75] = true; // Sound Controller 6 (GM2 default: Decay Time) + dontResetControls[76] = true; // Sound Controller 7 (GM2 default: Vibrato Rate) + dontResetControls[77] = true; // Sound Controller 8 (GM2 default: Vibrato Depth) + dontResetControls[78] = true; // Sound Controller 9 (GM2 default: Vibrato Delay) + dontResetControls[79] = true; // Sound Controller 10 (GM2 default: Undefined) + dontResetControls[120] = true; // All Sound Off + dontResetControls[121] = true; // Reset All Controllers + dontResetControls[122] = true; // Local Control On/Off + dontResetControls[123] = true; // All Notes Off + dontResetControls[124] = true; // Omni Mode Off + dontResetControls[125] = true; // Omni Mode On + dontResetControls[126] = true; // Poly Mode Off + dontResetControls[127] = true; // Poly Mode On + + dontResetControls[6] = true; // Data Entry (MSB) + dontResetControls[38] = true; // Data Entry (LSB) + dontResetControls[96] = true; // Data Increment + dontResetControls[97] = true; // Data Decrement + dontResetControls[98] = true; // Non-Registered Parameter Number (LSB) + dontResetControls[99] = true; // Non-Registered Parameter Number(MSB) + dontResetControls[100] = true; // RPN = Null + dontResetControls[101] = true; // RPN = Null + } + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTestUtils soft = new SoftTestUtils(); + MidiChannel channel = soft.synth.getChannels()[0]; + Receiver receiver = soft.synth.getReceiver(); + + // First let all controls contain non-default values + for (int i = 0; i < 128; i++) + channel.setPolyPressure(i, 10); + channel.setChannelPressure(10); + channel.setPitchBend(2192); + for (int i = 0; i < 120; i++) + channel.controlChange(i, 1); + + ShortMessage smsg = new ShortMessage(); + smsg.setMessage(ShortMessage.CONTROL_CHANGE,0, 121,0); + receiver.send(smsg, -1); + + // Now check if resetAllControllers did what it was suppose to do + + for (int i = 0; i < 128; i++) + assertEquals(channel.getPolyPressure(i), 0); + assertEquals(channel.getChannelPressure(), 0); + assertEquals(channel.getPitchBend(),8192); + for (int i = 0; i < 120; i++) + if(!dontResetControls[i]) + assertEquals(channel.getController(i), 0); + assertEquals(channel.getController(71), 64); // Filter Resonance + assertEquals(channel.getController(72), 64); // Release Time + assertEquals(channel.getController(73), 64); // Attack Time + assertEquals(channel.getController(74), 64); // Brightness + assertEquals(channel.getController(75), 64); // Decay Time + assertEquals(channel.getController(76), 64); // Vibrato Rate + assertEquals(channel.getController(77), 64); // Vibrato Depth + assertEquals(channel.getController(78), 64); // Vibrato Delay + assertEquals(channel.getController(8), 64); // Balance + assertEquals(channel.getController(11), 127); // Expression + assertEquals(channel.getController(98), 127); // NRPN Null + assertEquals(channel.getController(99), 127); // NRPN Null + assertEquals(channel.getController(100), 127); // RPN = Null + assertEquals(channel.getController(101), 127); // RPN = Null + + soft.close(); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftReceiver/SoftTestUtils.java b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/SoftTestUtils.java new file mode 100644 index 00000000000..f29983983d2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftReceiver/SoftTestUtils.java @@ -0,0 +1,111 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.IOException; + +import javax.sound.midi.*; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class SoftTestUtils { + + public AudioSynthesizer synth = new SoftSynthesizer(); + public AudioInputStream stream; + public byte[] tmpbuffer = new byte[1024]; + + public static SF2Soundbank createTestSoundBank() + { + SF2Soundbank sf2 = new SF2Soundbank(); + AudioFormat format = new AudioFormat(44100, 16, 1, true, false); + float[] data = new float[44100+1000]; + float fr = 440/format.getSampleRate(); + for (int i = 0; i < data.length; i++) + data[i] = (float)Math.sin(i*fr*2*Math.PI); + byte[] bdata = new byte[data.length*format.getFrameSize()]; + AudioFloatConverter.getConverter(format).toByteArray(data, bdata); + SF2Sample sample = new SF2Sample(sf2); + sample.setName("Test Sample"); + sample.setData(bdata); + sample.setStartLoop(500); + sample.setEndLoop(data.length - 500); + sample.setSampleRate((long) format.getSampleRate()); + sample.setOriginalPitch(69); + sf2.addResource(sample); + SF2Layer layer = new SF2Layer(sf2); + layer.setName("Test Layer"); + sf2.addResource(layer); + SF2LayerRegion region = new SF2LayerRegion(); + region.putInteger(SF2Region.GENERATOR_SAMPLEMODES, 1); + region.setSample(sample); + layer.getRegions().add(region); + SF2Instrument ins = new SF2Instrument(sf2); + ins.setName("Test Instrument"); + sf2.addInstrument(ins); + SF2InstrumentRegion insregion = new SF2InstrumentRegion(); + insregion.setLayer(layer); + ins.getRegions().add(insregion); + + return sf2; + } + + public SoftTestUtils() throws Exception { + stream = synth.openStream(null, null); + synth.unloadAllInstruments(synth.getDefaultSoundbank()); + synth.loadAllInstruments(createTestSoundBank()); + } + + public void close() throws Exception { + stream.close(); + stream = null; + synth.close(); + synth = null; + } + + public void read(double seconds) throws IOException + { + int bufflen = + stream.getFormat().getFrameSize() * + (int)(stream.getFormat().getFrameRate() * seconds); + while(bufflen != 0) + { + if(bufflen > 1024) + bufflen -= stream.read(tmpbuffer,0,1024); + else + bufflen -= stream.read(tmpbuffer,0, bufflen); + } + } + + public VoiceStatus findVoice(int channel, int note) { + VoiceStatus[] v = synth.getVoiceStatus(); + for (int k = 0; k < v.length; k++) + if(v[k].active) + if(v[k].channel == channel) + if(v[k].note == note) + return v[k]; + return null; + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSincResampler/Interpolate.java b/jdk/test/javax/sound/midi/Gervill/SoftSincResampler/Interpolate.java new file mode 100644 index 00000000000..b5ca59784e2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSincResampler/Interpolate.java @@ -0,0 +1,113 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSincResampler interpolate method */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Interpolate { + + private static float getResamplerTestValue(double i) + { + return (float)Math.sin(i / 10.0); + } + + private static void perfectInterpolation(float[] in_offset, float in_end, + float[] startpitch, float pitchstep, float[] out, int[] out_offset, + int out_end) { + + float pitch = startpitch[0]; + float ix = in_offset[0]; + int ox = out_offset[0]; + float ix_end = in_end; + int ox_end = out_end; + if (pitchstep == 0f) { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + } + } else { + while (ix < ix_end && ox < ox_end) { + out[ox++] = getResamplerTestValue(ix); + ix += pitch; + pitch += pitchstep; + } + } + in_offset[0] = ix; + out_offset[0] = ox; + startpitch[0] = pitch; + + } + + private static float testResampler(SoftAbstractResampler resampler, float p_pitch, float p_pitch2) + { + float[] testbuffer = new float[4096]; + float[] testbuffer2 = new float[1024]; + float[] testbuffer3 = new float[1024]; + for (int i = 0; i < testbuffer.length; i++) + testbuffer[i] = getResamplerTestValue(i); + int pads = resampler.getPadding(); + float pitchstep = (p_pitch2 - p_pitch)/1024f; + int[] out_offset2 = {0}; + int[] out_offset3 = {0}; + resampler.interpolate(testbuffer, new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer2, out_offset2, testbuffer2.length); + perfectInterpolation(new float[] {pads}, testbuffer.length - pads, new float[] {p_pitch}, pitchstep, testbuffer3, out_offset3, testbuffer3.length); + int out_off = out_offset2[0]; + if(out_offset3[0] < out_off) + out_off = out_offset3[0]; + float ac_error = 0; + int counter = 0; + for (int i = pads; i < out_off; i++) { + ac_error += Math.abs(testbuffer2[i] - testbuffer3[i]); + counter++; + } + return ac_error / ((float)counter); + } + + private static void fail(String error) throws Exception + { + throw new RuntimeException(error); + } + + public static void main(String[] args) throws Exception { + SoftSincResampler resampler = new SoftSincResampler(); + float max = testResampler(resampler, 0.3f, 0.3f); + if(max > 0.0001) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 0.3f, 0.01f); + if(max > 0.0001) + fail("Interpolation failed, error="+max); + max = testResampler(resampler, 1.0f, 0.00f); + if(max > 0.0001) + fail("Interpolation failed, error="+max); + } +} \ No newline at end of file diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Close.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Close.java new file mode 100644 index 00000000000..a36ee01791a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Close.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer close method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class Close { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + synth.close(); + assertTrue(!synth.isOpen()); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/DummySourceDataLine.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/DummySourceDataLine.java new file mode 100644 index 00000000000..c9ea327c53b --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/DummySourceDataLine.java @@ -0,0 +1,232 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.ArrayList; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Control; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.AudioFormat.Encoding; +import javax.sound.sampled.Control.Type; + +import com.sun.media.sound.AudioFloatConverter; + +/** + * This is a SourceDataLine simulator used for testing SoftSynthesizer + * without using real SourceDataLine / Audio Device. + * + * @author Karl Helgason + */ + +public class DummySourceDataLine implements SourceDataLine { + + private int bufferSize = -1; + + private AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false); + + private DataLine.Info sourceLineInfo; + + private boolean active = false; + + private long framepos = 0; + + private boolean opened = false; + + private int framesize = 0; + + public DummySourceDataLine() + { + ArrayList formats = new ArrayList(); + for (int channels = 1; channels <= 2; channels++) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, 8, channels, channels, + AudioSystem.NOT_SPECIFIED, false)); + for (int bits = 16; bits < 32; bits += 8) { + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(Encoding.PCM_SIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(Encoding.PCM_UNSIGNED, + AudioSystem.NOT_SPECIFIED, bits, channels, channels + * bits / 8, AudioSystem.NOT_SPECIFIED, true)); + } + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4, + AudioSystem.NOT_SPECIFIED, true)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, false)); + formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT, + AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8, + AudioSystem.NOT_SPECIFIED, true)); + } + AudioFormat[] formats_array = formats.toArray(new AudioFormat[formats + .size()]); + sourceLineInfo = new DataLine.Info(SourceDataLine.class, + formats_array, AudioSystem.NOT_SPECIFIED, + AudioSystem.NOT_SPECIFIED); + + } + + public void open() throws LineUnavailableException { + open(format); + } + + public void open(AudioFormat format) throws LineUnavailableException { + if (bufferSize == -1) + bufferSize = ((int) (format.getFrameRate() / 2)) + * format.getFrameSize(); + open(format, bufferSize); + } + + public void open(AudioFormat format, int bufferSize) + throws LineUnavailableException { + this.format = format; + this.bufferSize = bufferSize; + this.framesize = format.getFrameSize(); + opened = true; + } + + public boolean isOpen() { + return opened; + } + + public int write(byte[] b, int off, int len) { + if (!isOpen()) + return 0; + if (len % framesize != 0) + throw new IllegalArgumentException( + "Number of bytes does not represent an integral number of sample frames."); + + + int flen = len / framesize; + framepos += flen; + + long time = (long) (flen * (1000.0 / (double) getFormat() + .getSampleRate())); + try { + Thread.sleep(time); + } catch (InterruptedException e) { + e.printStackTrace(); + return 0; + } + + return len; + } + + public int available() { + return 0; + } + + public void drain() { + } + + public void flush() { + } + + public int getBufferSize() { + return bufferSize; + } + + public AudioFormat getFormat() { + return format; + } + + public int getFramePosition() { + return (int) getLongFramePosition(); + } + + public float getLevel() { + return AudioSystem.NOT_SPECIFIED; + } + + public long getLongFramePosition() { + return framepos; + } + + public long getMicrosecondPosition() { + return (long) (getLongFramePosition() * (1000000.0 / (double) getFormat() + .getSampleRate())); + } + + public boolean isActive() { + return active; + } + + public boolean isRunning() { + return active; + } + + public void start() { + active = true; + } + + public void stop() { + active = false; + } + + public void close() { + stop(); + } + + public Control getControl(Type control) { + throw new IllegalArgumentException("Unsupported control type : " + + control); + } + + public Control[] getControls() { + return new Control[0]; + } + + public javax.sound.sampled.Line.Info getLineInfo() { + return sourceLineInfo; + } + + public boolean isControlSupported(Type control) { + return false; + } + + public void addLineListener(LineListener listener) { + } + + public void removeLineListener(LineListener listener) { + } + +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments.java new file mode 100644 index 00000000000..3711e6bfd02 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getAvailableInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetAvailableInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(defsbk.getInstruments().length == synth.getAvailableInstruments().length); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetChannels.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetChannels.java new file mode 100644 index 00000000000..15191c824eb --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetChannels.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getChannels method */ + +import javax.sound.midi.MidiChannel; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetChannels { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.getChannels() != null); + assertTrue(synth.getChannels().length == 16); + MidiChannel[] channels = synth.getChannels(); + for (int i = 0; i < channels.length; i++) { + assertTrue(channels[i] != null); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDefaultSoundbank.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDefaultSoundbank.java new file mode 100644 index 00000000000..f78bd5b620d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDefaultSoundbank.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getDefaultSoundbank method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetDefaultSoundbank { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.getDefaultSoundbank() != null); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDeviceInfo.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDeviceInfo.java new file mode 100644 index 00000000000..1b8fbf84d9d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetDeviceInfo.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getDeviceInfo method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetDeviceInfo { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + assertTrue(synth.getDeviceInfo() != null); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLatency.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLatency.java new file mode 100644 index 00000000000..4d9a76514af --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLatency.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getLatency method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetLatency { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(new DummySourceDataLine(), null); + assertTrue(synth.getLatency() != -1); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments.java new file mode 100644 index 00000000000..7902595aeca --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getLoadedInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetLoadedInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + synth.unloadAllInstruments(defsbk); + synth.loadAllInstruments(defsbk); + assertTrue(synth.getLoadedInstruments().length != 0); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxPolyphony.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxPolyphony.java new file mode 100644 index 00000000000..95d034c1d5a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxPolyphony.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getMaxPolyphony method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetMaxPolyphony { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.getMaxPolyphony() != -1); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxReceivers.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxReceivers.java new file mode 100644 index 00000000000..0b5e2f4f069 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxReceivers.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getMaxReceivers method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetMaxReceivers { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + assertTrue(synth.getMaxReceivers() == -1); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxTransmitters.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxTransmitters.java new file mode 100644 index 00000000000..0cfeb784b53 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMaxTransmitters.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getMaxTransmitters method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetMaxTransmitters { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + assertTrue(synth.getMaxTransmitters() == 0); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMicrosecondPosition.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMicrosecondPosition.java new file mode 100644 index 00000000000..080ab599380 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetMicrosecondPosition.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getMicrosecondPosition method */ + +import java.io.IOException; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetMicrosecondPosition { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + AudioInputStream stream = synth.openStream(null, null); + assertTrue(synth.getMicrosecondPosition() == 0); + AudioFormat format = stream.getFormat(); + byte[] buff = new byte[((int)format.getFrameRate())*format.getFrameSize()];; + stream.read(buff); + assertTrue(Math.abs(synth.getMicrosecondPosition()-1000000) < 10000); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver.java new file mode 100644 index 00000000000..88ba59bb3b6 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getReceiver method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetReceiver { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(new DummySourceDataLine(), null); + Receiver recv = synth.getReceiver(); + assertTrue(recv != null); + Receiver recv2 = synth.getReceiver(); + assertTrue(recv2 != null); + assertTrue(recv2 != recv); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver2.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver2.java new file mode 100644 index 00000000000..012de3fb21a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceiver2.java @@ -0,0 +1,62 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getReceiver method */ + +import javax.sound.midi.Receiver; +import javax.sound.midi.ShortMessage; + +import com.sun.media.sound.AudioSynthesizer; +import com.sun.media.sound.SoftSynthesizer; + +public class GetReceiver2 { + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + Receiver recv = synth.getReceiver(); + assertTrue(recv != null); + ShortMessage sm = new ShortMessage(); + sm.setMessage(ShortMessage.NOTE_OFF, 0, 64, 64); + synth.open(new DummySourceDataLine(), null); + recv.send(sm, -1); + synth.close(); + try + { + recv.send(sm, -1); + throw new RuntimeException("Exception not thrown!"); + } + catch(Exception e) + { + // Just checking if exception is thrown + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceivers.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceivers.java new file mode 100644 index 00000000000..b7937039a3e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetReceivers.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getReceivers method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetReceivers { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(new DummySourceDataLine(), null); + assertTrue(synth.getReceivers().size() == 0); + Receiver recv = synth.getReceiver(); + assertTrue(synth.getReceivers().size() == 1); + recv.close(); + assertTrue(synth.getReceivers().size() == 0); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitter.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitter.java new file mode 100644 index 00000000000..d65ec380963 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitter.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getTransmitter method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetTransmitter { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(new DummySourceDataLine(), null); + try + { + synth.getTransmitter(); + throw new Exception("MidiUnavailableException not thrown!"); + } catch (MidiUnavailableException e) { + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitters.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitters.java new file mode 100644 index 00000000000..ac6addc6b35 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetTransmitters.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getTransmitters method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetTransmitters { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(new DummySourceDataLine(), null); + assertTrue(synth.getTransmitters().size() == 0); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetVoiceStatus.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetVoiceStatus.java new file mode 100644 index 00000000000..327e29342c0 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/GetVoiceStatus.java @@ -0,0 +1,61 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer getVoiceStatus method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.VoiceStatus; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class GetVoiceStatus { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + VoiceStatus[] v = synth.getVoiceStatus(); + assertTrue(v != null); + assertTrue(synth.getChannels().length != synth.getMaxPolyphony()); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java new file mode 100644 index 00000000000..15379d5601c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java @@ -0,0 +1,105 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer implicit open/close using getReceiver. */ + +import java.lang.reflect.Field; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Receiver; +import javax.sound.midi.Synthesizer; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class ImplicitOpenClose { + + public static void main(String[] args) throws Exception { + Field f = SoftSynthesizer.class.getDeclaredField("testline"); + f.setAccessible(true); + f.set(null, new DummySourceDataLine()); + + Synthesizer synth = new SoftSynthesizer(); + + ReferenceCountingDevice rcd = (ReferenceCountingDevice)synth; + + // Test single open/close cycle + + Receiver recv = rcd.getReceiverReferenceCounting(); + if(!synth.isOpen()) + throw new Exception("Synthesizer not open!"); + recv.close(); + if(synth.isOpen()) + throw new Exception("Synthesizer not closed!"); + + // Test using 2 receiver cycle + + Receiver recv1 = rcd.getReceiverReferenceCounting(); + if(!synth.isOpen()) + throw new Exception("Synthesizer not open!"); + Receiver recv2 = rcd.getReceiverReferenceCounting(); + if(!synth.isOpen()) + throw new Exception("Synthesizer not open!"); + + recv2.close(); + if(!synth.isOpen()) + throw new Exception("Synthesizer was closed!"); + recv1.close(); + if(synth.isOpen()) + throw new Exception("Synthesizer not closed!"); + + // Test for explicit,implicit conflict + + synth.open(); + Receiver recv3 = rcd.getReceiverReferenceCounting(); + if(!synth.isOpen()) + throw new Exception("Synthesizer not open!"); + recv3.close(); + if(!synth.isOpen()) + throw new Exception("Synthesizer was closed!"); + synth.close(); + if(synth.isOpen()) + throw new Exception("Synthesizer not closed!"); + + // Test for implicit,explicit conflict + + recv3 = rcd.getReceiverReferenceCounting(); + synth.open(); + if(!synth.isOpen()) + throw new Exception("Synthesizer not open!"); + recv3.close(); + if(!synth.isOpen()) + throw new Exception("Synthesizer was closed!"); + synth.close(); + if(synth.isOpen()) + throw new Exception("Synthesizer not closed!"); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsOpen.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsOpen.java new file mode 100644 index 00000000000..27c5559a02a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsOpen.java @@ -0,0 +1,59 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer isOpen method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class IsOpen { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.isOpen()); + synth.close(); + assertTrue(!synth.isOpen()); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsSoundbankSupported.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsSoundbankSupported.java new file mode 100644 index 00000000000..0a8879c532c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/IsSoundbankSupported.java @@ -0,0 +1,95 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer isSoundbankSupported method */ + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.midi.SoundbankResource; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class IsSoundbankSupported { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + sbk.addInstrument(ins); + assertTrue(synth.isSoundbankSupported(sbk)); + Soundbank dummysbk = new Soundbank() + { + public String getName() { + return null; + } + public String getVersion() { + return null; + } + public String getVendor() { + return null; + } + public String getDescription() { + return null; + } + public SoundbankResource[] getResources() { + return null; + } + public Instrument[] getInstruments() { + Instrument ins = new Instrument(null, null, null, null) + { + public Object getData() { + return null; + } + }; + return new Instrument[] {ins}; + } + public Instrument getInstrument(Patch patch) { + return null; + } + }; + assertTrue(!synth.isSoundbankSupported(dummysbk)); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java new file mode 100644 index 00000000000..c97b8a1ce8d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer loadAllInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class LoadAllInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(0,1)); + sbk.addInstrument(ins); + SimpleInstrument ins2 = new SimpleInstrument(); + ins2.setPatch(new Patch(0,2)); + sbk.addInstrument(ins2); + synth.loadAllInstruments(sbk); + assertTrue(synth.getLoadedInstruments().length == 2); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java new file mode 100644 index 00000000000..2a2db707cb6 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer loadAllInstrument method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class LoadInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(0,1)); + sbk.addInstrument(ins); + SimpleInstrument ins2 = new SimpleInstrument(); + ins2.setPatch(new Patch(0,2)); + sbk.addInstrument(ins2); + synth.loadInstrument(ins2); + assertTrue(synth.getLoadedInstruments().length == 1); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java new file mode 100644 index 00000000000..bfdeb3eb7cd --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java @@ -0,0 +1,73 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer loadAllInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class LoadInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(0,1)); + sbk.addInstrument(ins); + SimpleInstrument ins2 = new SimpleInstrument(); + ins2.setPatch(new Patch(0,2)); + sbk.addInstrument(ins2); + synth.loadInstruments(sbk, new Patch[] {ins2.getPatch()}); + assertTrue(synth.getLoadedInstruments().length == 1); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java new file mode 100644 index 00000000000..332fd8bcd4c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java @@ -0,0 +1,64 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer open method */ + +import java.lang.reflect.Field; + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class Open { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + Field f = SoftSynthesizer.class.getDeclaredField("testline"); + f.setAccessible(true); + f.set(null, new DummySourceDataLine()); + + AudioSynthesizer synth = new SoftSynthesizer(); + synth.open(); + assertTrue(synth.isOpen()); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/OpenStream.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/OpenStream.java new file mode 100644 index 00000000000..5defef66791 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/OpenStream.java @@ -0,0 +1,58 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer openStream method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class OpenStream { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + assertTrue(synth.isOpen()); + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java new file mode 100644 index 00000000000..6c21fe1f5d2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java @@ -0,0 +1,76 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer remapInstrument method */ + +import javax.sound.midi.Instrument; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class RemapInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + Instrument ins0 = defsbk.getInstrument(new Patch(0,0)); + Instrument ins10 = defsbk.getInstrument(new Patch(0,10)); + assertTrue(synth.remapInstrument(ins0, ins10)); + Instrument[] loaded = synth.getLoadedInstruments(); + for (int i = 0; i < loaded.length; i++) { + if(loaded[i].getPatch().getBank() == 0) + if(loaded[i].getPatch().getProgram() == 10) + { + assertEquals(loaded[i].getName(), ins0.getName()); + break; + } + } + + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/TestRender1.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/TestRender1.java new file mode 100644 index 00000000000..56a2ef8caf2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/TestRender1.java @@ -0,0 +1,214 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer simple note rendering in many settings */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.sound.sampled.*; +import javax.sound.midi.*; + +import com.sun.media.sound.*; + +public class TestRender1 { + + public static double send(Sequence seq, Receiver recv) { + float divtype = seq.getDivisionType(); + assert (seq.getDivisionType() == Sequence.PPQ); + Track[] tracks = seq.getTracks(); + int[] trackspos = new int[tracks.length]; + int mpq = 60000000 / 100; + int seqres = seq.getResolution(); + long lasttick = 0; + long curtime = 0; + while (true) { + MidiEvent selevent = null; + int seltrack = -1; + for (int i = 0; i < tracks.length; i++) { + int trackpos = trackspos[i]; + Track track = tracks[i]; + if (trackpos < track.size()) { + MidiEvent event = track.get(trackpos); + if (selevent == null + || event.getTick() < selevent.getTick()) { + selevent = event; + seltrack = i; + } + } + } + if (seltrack == -1) + break; + trackspos[seltrack]++; + long tick = selevent.getTick(); + if (divtype == Sequence.PPQ) + curtime += ((tick - lasttick) * mpq) / seqres; + else + curtime = (long) ((tick * 1000000.0 * divtype) / seqres); + lasttick = tick; + MidiMessage msg = selevent.getMessage(); + if (msg instanceof MetaMessage) { + if (divtype == Sequence.PPQ) + if (((MetaMessage) msg).getType() == 0x51) { + byte[] data = ((MetaMessage) msg).getData(); + mpq = ((data[0] & 0xff) << 16) + | ((data[1] & 0xff) << 8) | (data[2] & 0xff); + } + } else { + if (recv != null) + recv.send(msg, curtime); + } + } + + return curtime / 1000000.0; + } + + public static void test(AudioFormat format, Map info) + throws Exception { + OutputStream nullout = new OutputStream() { + public void write(int b) throws IOException { + } + + public void write(byte[] b, int off, int len) throws IOException { + } + + public void write(byte[] b) throws IOException { + } + }; + render(nullout, format, info); + } + + public static void render(OutputStream os, AudioFormat format, + Map info) throws Exception { + AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer(); + AudioInputStream stream = synth.openStream(format, info); + Receiver recv = synth.getReceiver(); + Soundbank defsbk = synth.getDefaultSoundbank(); + if (defsbk != null) + synth.unloadAllInstruments(defsbk); + synth.loadAllInstruments(soundbank); + + double totalTime = 5; + send(sequence, recv); + + long len = (long) (stream.getFormat().getFrameRate() * (totalTime + 4)); + stream = new AudioInputStream(stream, stream.getFormat(), len); + + long t = System.currentTimeMillis(); + AudioSystem.write(stream, AudioFileFormat.Type.WAVE, os); + t = System.currentTimeMillis() - t; + stream.close(); + } + + + static Soundbank soundbank; + + static Sequence sequence; + + public static InputStream getInputStream(String filename) throws IOException + { + File file = new File(System.getProperty("test.src", "."), filename); + FileInputStream fis = new FileInputStream(file); + return new BufferedInputStream(fis); + } + + public static void main(String[] args) throws Exception { + + InputStream sb = getInputStream("ding.sf2"); + soundbank = MidiSystem.getSoundbank(sb); + sb.close(); + + InputStream si = getInputStream("expresso.mid"); + sequence = MidiSystem.getSequence(si); + si.close(); + + AudioFormat format; + Map info = new HashMap(); + { + format = new AudioFormat(22050, 16, 2, true, false); + test(format, info); + format = new AudioFormat(44100, 16, 2, true, false); + test(format, info); + } + { + format = new AudioFormat(44100, 8, 2, true, false); + test(format, info); + format = new AudioFormat(44100, 16, 2, true, false); + test(format, info); + format = new AudioFormat(44100, 24, 2, true, false); + test(format, info); + } + { + format = new AudioFormat(44100, 16, 1, true, false); + test(format, info); + format = new AudioFormat(44100, 16, 2, true, false); + test(format, info); + } + { + format = new AudioFormat(44100, 16, 2, true, false); + + info.clear(); + info.put("control rate", 100f); + test(format, info); + info.clear(); + info.put("control rate", 147f); + test(format, info); + + } + { + format = new AudioFormat(44100, 16, 2, true, false); + + info.clear(); + info.put("interpolation", "point"); + test(format, info); + info.clear(); + info.put("interpolation", "linear"); + test(format, info); + info.clear(); + info.put("interpolation", "cubic"); + test(format, info); + } + { + format = new AudioFormat(44100, 16, 2, true, false); + info.clear(); + info.put("max polyphony", 4); + test(format, info); + info.clear(); + info.put("max polyphony", 16); + test(format, info); + info.clear(); + + } + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java new file mode 100644 index 00000000000..e3ded2e8265 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java @@ -0,0 +1,69 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer unloadAllInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class UnloadAllInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + assertTrue(synth.getAvailableInstruments().length == 0); + synth.loadAllInstruments(defsbk); + assertTrue(synth.getLoadedInstruments().length != 0); + synth.unloadAllInstruments(defsbk); + assertTrue(synth.getLoadedInstruments().length == 0); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java new file mode 100644 index 00000000000..06fc326b722 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java @@ -0,0 +1,75 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer unloadInstrument method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class UnloadInstrument { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(0,1)); + sbk.addInstrument(ins); + SimpleInstrument ins2 = new SimpleInstrument(); + ins2.setPatch(new Patch(0,2)); + sbk.addInstrument(ins2); + synth.loadInstrument(ins2); + assertTrue(synth.getLoadedInstruments().length == 1); + synth.unloadInstrument(ins2); + assertTrue(synth.getLoadedInstruments().length == 0); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java new file mode 100644 index 00000000000..01f23f27c20 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java @@ -0,0 +1,75 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftSynthesizer unloadInstruments method */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.midi.Soundbank; +import javax.sound.sampled.*; +import javax.sound.midi.MidiDevice.Info; + +import com.sun.media.sound.*; + +public class UnloadInstruments { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + AudioSynthesizer synth = new SoftSynthesizer(); + synth.openStream(null, null); + Soundbank defsbk = synth.getDefaultSoundbank(); + if(defsbk != null) + { + assertTrue(synth.getLoadedInstruments().length == 0); + synth.unloadAllInstruments(defsbk); + SimpleSoundbank sbk = new SimpleSoundbank(); + SimpleInstrument ins = new SimpleInstrument(); + ins.setPatch(new Patch(0,1)); + sbk.addInstrument(ins); + SimpleInstrument ins2 = new SimpleInstrument(); + ins2.setPatch(new Patch(0,2)); + sbk.addInstrument(ins2); + synth.loadInstrument(ins2); + assertTrue(synth.getLoadedInstruments().length == 1); + synth.unloadInstruments(sbk, new Patch[] {ins2.getPatch()}); + assertTrue(synth.getLoadedInstruments().length == 0); + } + synth.close(); + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ding.sf2 b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ding.sf2 new file mode 100644 index 00000000000..86327f056a4 Binary files /dev/null and b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ding.sf2 differ diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/expresso.mid b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/expresso.mid new file mode 100644 index 00000000000..816d0e03393 Binary files /dev/null and b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/expresso.mid differ diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetName.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetName.java new file mode 100644 index 00000000000..d869b49956c --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetName.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning getName method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetName { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTuning tuning = new SoftTuning(); + tuning.setName("custom"); + assertEquals(tuning.getName(), "custom"); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuning.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuning.java new file mode 100644 index 00000000000..f3187d0333e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuning.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning getTuning method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetTuning { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTuning tuning = new SoftTuning(); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) { + assertTrue(Math.abs(tunings[i]-i*100) < 0.00001); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuningInt.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuningInt.java new file mode 100644 index 00000000000..2b9fbf7f2e1 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/GetTuningInt.java @@ -0,0 +1,53 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning getTuning(int) method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class GetTuningInt { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTuning tuning = new SoftTuning(); + assertTrue(Math.abs(tuning.getTuning(36)-3600) < 0.00001); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load1.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load1.java new file mode 100644 index 00000000000..3ba88574166 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load1.java @@ -0,0 +1,101 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load1 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning.shtml + // 0x01 BULK TUNING DUMP + SoftTuning tuning = new SoftTuning(); + byte[] name; + name = "Testing123 ".getBytes("ascii"); + + int[] msg = new int[24+3*128]; + int[] head = {0xf0,0x7e,0x7f,0x08,0x01,0x00}; + int ox = 0; + for (int i = 0; i < head.length; i++) + msg[ox++] = head[i]; + for (int i = 0; i < name.length; i++) + msg[ox++] = name[i]; + for (int i = 0; i < 128; i++) { + msg[ox++] = i; + msg[ox++] = 64; + msg[ox++] = 0; + } + + // Calc checksum + int x = msg[1] & 0xFF; // 7E + x = x ^ (msg[2] & 0xFF); // + x = x ^ (msg[4] & 0xFF); // nn + x = x ^ (msg[5] & 0xFF); // tt + for (int i = 22; i < msg.length - 2; i++) + x = x ^ (msg[i] & 0xFF); + msg[ox++] = (x & 127); + + msg[ox++] = 0xf7; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + + tuning.load(bmsg); + assertEquals(tuning.getName(), "Testing123 "); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + 50)) < 0.00001); + + // Check if tuning fails if checksum is wrong + /* + msg[msg.length - 2] += 10; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning = new SoftTuning(); + tuning.load(bmsg); + assertTrue(!tuning.getName().equals("Testing123 ")); + */ + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load2.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load2.java new file mode 100644 index 00000000000..e3c614b1538 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load2.java @@ -0,0 +1,71 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load2 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning.shtml + // 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME) + SoftTuning tuning = new SoftTuning(); + int[] msg = {0xf0,0x7f,0x7f,0x08,0x02,0x10,0x02, + 36,36,64,0, + 40,70,0,0, + 0xf7}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) { + if(i == 36) + assertTrue(Math.abs(tunings[i]-3650)< 0.00001); + else if(i == 40) + assertTrue(Math.abs(tunings[i]-7000) < 0.00001); + else + assertTrue(Math.abs(tunings[i]-i*100) < 0.00001); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load4.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load4.java new file mode 100644 index 00000000000..158e56990fc --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load4.java @@ -0,0 +1,104 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load4 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning_extens.shtml + // 0x04 KEY-BASED TUNING DUMP + SoftTuning tuning = new SoftTuning(); + byte[] name; + name = "Testing123 ".getBytes("ascii"); + + int[] msg = new int[25+3*128]; + int[] head = {0xf0,0x7e,0x7f,0x08,0x04,0x00,0x00}; + int ox = 0; + for (int i = 0; i < head.length; i++) + msg[ox++] = head[i]; + for (int i = 0; i < name.length; i++) + msg[ox++] = name[i]; + for (int i = 0; i < 128; i++) { + msg[ox++] = i; + msg[ox++] = 64; + msg[ox++] = 0; + } + + // Calc checksum + int x = msg[1] & 0xFF; + for (int i = 2; i < msg.length - 2; i++) + x = x ^ (msg[i] & 0xFF); + msg[ox++] = (x & 127); + + msg[ox++] = 0xf7; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + + tuning.load(bmsg); + assertEquals(tuning.getName(), "Testing123 "); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + 50)) < 0.00001); + + // Check if tuning fails if checksum is wrong + msg[msg.length - 2] += 10; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning = new SoftTuning(); + tuning.load(bmsg); + assertTrue(!tuning.getName().equals("Testing123 ")); + + // Check if tuning fails if checksum is wrong + msg[msg.length - 2] += 10; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning = new SoftTuning(); + tuning.load(bmsg); + assertTrue(!tuning.getName().equals("Testing123 ")); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load5.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load5.java new file mode 100644 index 00000000000..1469086e01a --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load5.java @@ -0,0 +1,87 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load5 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning_extens.shtml + // 0x05 SCALE/OCTAVE TUNING DUMP, 1 byte format + SoftTuning tuning = new SoftTuning(); + + byte[] name; + name = "Testing123 ".getBytes("ascii"); + int[] msg = {0xf0,0x7e,0x7f,0x08,0x05,0,0, + name[0],name[1],name[2],name[3],name[4],name[5],name[6], + name[7],name[8],name[9],name[10],name[11],name[12],name[13], + name[14],name[15], + 5,10,15,20,25,30,35,40,45,50,51,52,0, + 0xf7}; + // Calc checksum + int x = msg[1] & 0xFF; + for (int i = 2; i < msg.length - 2; i++) + x = x ^ (msg[i] & 0xFF); + msg[msg.length-2] = (x & 127); + + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + (oct[i%12]-64))) < 0.00001); + + // Check if tuning fails if checksum is wrong + msg[msg.length - 2] += 10; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning = new SoftTuning(); + tuning.load(bmsg); + assertTrue(!tuning.getName().equals("Testing123 ")); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load6.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load6.java new file mode 100644 index 00000000000..147ddc39e16 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load6.java @@ -0,0 +1,91 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import java.io.UnsupportedEncodingException; + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load6 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning_extens.shtml + // 0x06 SCALE/OCTAVE TUNING DUMP, 2 byte format + SoftTuning tuning = new SoftTuning(); + + byte[] name; + name = "Testing123 ".getBytes("ascii"); + int[] msg = {0xf0,0x7e,0x7f,0x08,0x06,0,0, + name[0],name[1],name[2],name[3],name[4],name[5],name[6], + name[7],name[8],name[9],name[10],name[11],name[12],name[13], + name[14],name[15], + 5,10,15,20,25,30,35,40,45,50,51,52, + 5,10,15,20,25,30,35,40,45,50,51,52, + 0,0xf7}; + // Calc checksum + int x = msg[1] & 0xFF; + for (int i = 2; i < msg.length - 2; i++) + x = x ^ (msg[i] & 0xFF); + msg[msg.length-2] = (x & 127); + + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52,5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + { + double c = (oct[(i%12)*2]*128 + oct[(i%12)*2+1] -8192)*(100.0/8192.0); + assertTrue(Math.abs(tunings[i]-(i*100 + (c))) < 0.00001); + } + + // Check if tuning fails if checksum is wrong + msg[msg.length - 2] += 10; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning = new SoftTuning(); + tuning.load(bmsg); + assertTrue(!tuning.getName().equals("Testing123 ")); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load7.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load7.java new file mode 100644 index 00000000000..41e8e6467fc --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load7.java @@ -0,0 +1,72 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load7 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning_extens.shtml + // 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK) + SoftTuning tuning = new SoftTuning(); + int[] msg = {0xf0,0x7f,0x7f,0x08,0x07,0x00,0x00,0x02, + 36,36,64,0, + 40,70,0,0, + 0xf7}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) { + if(i == 36) + assertTrue(Math.abs(tunings[i]-3650)< 0.00001); + else if(i == 40) + assertTrue(Math.abs(tunings[i]-7000) < 0.00001); + else + assertTrue(Math.abs(tunings[i]-i*100) < 0.00001); + } + + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load8.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load8.java new file mode 100644 index 00000000000..60f8205163e --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load8.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load8 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning-scale.shtml + // 0x08 scale/octave tuning 1-byte form (Non Real-Time/REAL-TIME) + SoftTuning tuning = new SoftTuning(); + int[] msg = {0xf0,0x7f,0x7f,0x08,0x08,0x03,0x7f,0x7f, + 5,10,15,20,25,30,35,40,45,50,51,52, + 0xf7}; + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + (oct[i%12]-64))) < 0.00001); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load9.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load9.java new file mode 100644 index 00000000000..4dc0c2837cf --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/Load9.java @@ -0,0 +1,69 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning load method */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class Load9 { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // http://www.midi.org/about-midi/tuning-scale.shtml + // 0x09 scale/octave tuning 2-byte form (Non Real-Time/REAL-TIME) + SoftTuning tuning = new SoftTuning(); + int[] msg = {0xf0,0x7f,0x7f,0x08,0x09,0x03,0x7f,0x7f, + 5,10,15,20,25,30,35,40,45,50,51,52, + 5,10,15,20,25,30,35,40,45,50,51,52, + 0xf7}; + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52,5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + tuning.load(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + { + double c = (oct[(i%12)*2]*128 + oct[(i%12)*2+1] -8192)*(100.0/8192.0); + assertTrue(Math.abs(tunings[i]-(i*100 + (c))) < 0.00001); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuning.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuning.java new file mode 100644 index 00000000000..5fada28e6be --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuning.java @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning constructor */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewSoftTuning { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTuning tuning = new SoftTuning(); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) { + assertTrue(Math.abs(tunings[i]-i*100) < 0.00001); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningByteArray.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningByteArray.java new file mode 100644 index 00000000000..d61f503e777 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningByteArray.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning constructor */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewSoftTuningByteArray { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // RealTime: Scale/Octave tuning in 1-byte format + int[] msg = {0xf0,0x7f,0x7f,0x08,0x08,0x03,0x7f,0x7f, + 5,10,15,20,25,30,35,40,45,50,51,52, + 0xf7}; + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + SoftTuning tuning = new SoftTuning(bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + (oct[i%12]-64))) < 0.00001); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatch.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatch.java new file mode 100644 index 00000000000..ee7cced0e76 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatch.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning constructor */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewSoftTuningPatch { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + SoftTuning tuning = new SoftTuning(new Patch(8,32)); + assertEquals(tuning.getPatch().getProgram(), 32); + assertEquals(tuning.getPatch().getBank(), 8); + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatchByteArray.java b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatchByteArray.java new file mode 100644 index 00000000000..20faf9d914d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/SoftTuning/NewSoftTuningPatchByteArray.java @@ -0,0 +1,65 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @summary Test SoftTuning constructor */ + +import javax.sound.midi.MidiUnavailableException; +import javax.sound.midi.Patch; +import javax.sound.sampled.*; + +import com.sun.media.sound.*; + +public class NewSoftTuningPatchByteArray { + + private static void assertEquals(Object a, Object b) throws Exception + { + if(!a.equals(b)) + throw new RuntimeException("assertEquals fails!"); + } + + private static void assertTrue(boolean value) throws Exception + { + if(!value) + throw new RuntimeException("assertTrue fails!"); + } + + public static void main(String[] args) throws Exception { + // RealTime: Scale/Octave tuning in 1-byte format + int[] msg = {0xf0,0x7f,0x7f,0x08,0x08,0x03,0x7f,0x7f, + 5,10,15,20,25,30,35,40,45,50,51,52, + 0xf7}; + int[] oct = {5,10,15,20,25,30,35,40,45,50,51,52}; + byte[] bmsg = new byte[msg.length]; + for (int i = 0; i < bmsg.length; i++) + bmsg[i] = (byte)msg[i]; + SoftTuning tuning = new SoftTuning(new Patch(8,32),bmsg); + double[] tunings = tuning.getTuning(); + for (int i = 0; i < tunings.length; i++) + assertTrue(Math.abs(tunings[i]-(i*100 + (oct[i%12]-64))) < 0.00001); + assertEquals(tuning.getPatch().getProgram(), 32); + assertEquals(tuning.getPatch().getBank(), 8); + } +} diff --git a/jdk/test/javax/swing/JColorChooser/Test4222508.html b/jdk/test/javax/swing/JColorChooser/Test4222508.html new file mode 100644 index 00000000000..4614fb7de47 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4222508.html @@ -0,0 +1,9 @@ + + +Use the check box above the color chooser to disable it. +You could not choose a color using by the disable color chooser. + + + + + diff --git a/jdk/test/javax/swing/JColorChooser/Test4222508.java b/jdk/test/javax/swing/JColorChooser/Test4222508.java new file mode 100644 index 00000000000..85b83572568 --- /dev/null +++ b/jdk/test/javax/swing/JColorChooser/Test4222508.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 4222508 + * @summary Tests the color chooser disabling + * @author Sergey Malenkov + * @run applet/manual=yesno Test4222508.html + */ + +import java.awt.BorderLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.JApplet; +import javax.swing.JCheckBox; +import javax.swing.JColorChooser; + +public final class Test4222508 extends JApplet implements ItemListener { + + private JCheckBox checkbox; + private JColorChooser chooser; + + @Override + public void init() { + this.chooser = new JColorChooser(); + this.checkbox = new JCheckBox("Enable the color chooser below", true); + this.checkbox.addItemListener(this); + add(BorderLayout.NORTH, this.checkbox); + add(BorderLayout.CENTER, this.chooser); + } + + public void itemStateChanged(ItemEvent event) { + this.chooser.setEnabled(this.checkbox.isSelected()); + } +} diff --git a/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.html b/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.html new file mode 100644 index 00000000000..8de6fdd0792 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.html @@ -0,0 +1,8 @@ + + + +1. Go into 'subdir' folder via double click +2. Return to parent directory +3. Go into 'subdir' folder: select 'subdir' folder and press the 'Open' button + + diff --git a/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.java b/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.java new file mode 100644 index 00000000000..ede1533746d --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/6698013/bug6698013.java @@ -0,0 +1,174 @@ +/* @test %W% %E% + @bug 6698013 + @summary JFileChooser can no longer navigate non-local file systems. + @author Pavel Porvatov + @run applet/manual=done bug6698013.html +*/ + +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; +import java.io.File; + +public class bug6698013 extends JApplet { + + final static VirtualFile root = new VirtualFile("testdir", true); + + final static VirtualFile rootFile = new VirtualFile("testdir/test.txt", false); + + final static VirtualFile subdir = new VirtualFile("testdir/subdir", true); + + final static VirtualFile subdirFile = new VirtualFile("testdir/subdir/subtest.txt", false); + + public static void main(String[] args) { + JFileChooser chooser = new JFileChooser(new VirtualFileSystemView()); + chooser.setCurrentDirectory(root); + chooser.showSaveDialog(null); + } + + public void init() { + JFileChooser chooser = new JFileChooser(new VirtualFileSystemView()); + chooser.setCurrentDirectory(root); + chooser.showSaveDialog(null); + } +} + +class VirtualFileSystemView extends FileSystemView { + + public boolean isRoot(File dir) { + return bug6698013.root.equals(dir); + } + + public File createNewFolder(File dir) { + return null; + } + + public File[] getRoots() { + return new File[]{bug6698013.root}; + } + + public boolean isDrive(File dir) { + return false; + } + + public boolean isFloppyDrive(File dir) { + return false; + } + + public File getParentDirectory(File dir) { + if (dir == null) { + return null; + } + + return new VirtualFile(dir.getPath(), true).getParentFile(); + } + + public File[] getFiles(File dir, boolean hide_hidden) { + if (dir.equals(bug6698013.root)) { + return new File[]{bug6698013.rootFile, bug6698013.subdir}; + } + + if (dir.equals(bug6698013.subdir)) { + return new File[]{bug6698013.subdirFile}; + } + + return null; + } + + public File getHomeDirectory() { + return bug6698013.root; + } + + public File getDefaultDirectory() { + return getHomeDirectory(); + } + + public String getSystemDisplayName(File file) { + return file.getName(); + } + + public Boolean isTraversable(File file) { + return Boolean.valueOf(file.isDirectory()); + } +} + +/** + * A Virtual File. Contains a path and a directory flag that + * represents the location of a virtual file to be contained in the + * Virtual FileSystemView. + */ +class VirtualFile extends File { + + private static final long serialVersionUID = 0L; + + private String path; + + private boolean directory; + + public VirtualFile(String path, boolean directory) { + super(path); + this.path = path; + this.directory = directory; + } + + public File getParentFile() { + int index = path.lastIndexOf('/'); + + if (index == -1) { + return null; + } + + return new VirtualFile(path.substring(0, index), true); + } + + public File getCanonicalFile() { + return this; + } + + public String getParent() { + File parent_file = getParentFile(); + + return parent_file == null ? null : parent_file.getPath(); + } + + public String getName() { + int index = path.lastIndexOf('/'); + + return index == -1 ? path : path.substring(index + 1); + } + + public String getPath() { + return path; + } + + public String getAbsolutePath() { + return path; + } + + public String getCanonicalPath() { + return path; + } + + public String toString() { + return path; + } + + public boolean equals(Object obj) { + return obj instanceof VirtualFile && path.equals(obj.toString()); + } + + public int hashCode() { + return path.hashCode(); + } + + public boolean canWrite() { + return true; + } + + public boolean isDirectory() { + return directory; + } + + public boolean exists() { + return true; + } +} diff --git a/jdk/test/javax/swing/JSlider/6794836/bug6794836.java b/jdk/test/javax/swing/JSlider/6794836/bug6794836.java new file mode 100644 index 00000000000..d59deaeb8e4 --- /dev/null +++ b/jdk/test/javax/swing/JSlider/6794836/bug6794836.java @@ -0,0 +1,80 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6794836 + * @summary BasicSliderUI throws NullPointerExc when JSlider maximum is Integer.MAX_VALUE + * @author Pavel Porvatov + * @run main bug6794836 + */ + +import javax.swing.*; +import javax.swing.plaf.basic.BasicSliderUI; +import java.lang.reflect.Method; +import java.util.Hashtable; + +public class bug6794836 { + public static void main(String[] args) throws Exception { + new bug6794836().run(); + } + + public void run() throws Exception { + JSlider slider = new JSlider(0, Integer.MAX_VALUE); + + slider.setPaintLabels(true); + + JLabel minLabel = new JLabel("Min"); + JLabel maxLabel = new JLabel("Max"); + + Hashtable labelTable = new Hashtable(); + + labelTable.put(Integer.MIN_VALUE, minLabel); + labelTable.put(Integer.MAX_VALUE, maxLabel); + + slider.setLabelTable(labelTable); + + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + + if (invokeMethod("getHighestValueLabel", ui) != maxLabel) { + fail("invalid getHighestValueLabel result"); + } + + if (invokeMethod("getLowestValueLabel", ui) != minLabel) { + fail("invalid getLowestValueLabel result"); + } + + System.out.println("The bug6794836 test passed"); + } + + private static Object invokeMethod(String name, BasicSliderUI ui) throws Exception { + Method method = BasicSliderUI.class.getDeclaredMethod(name, null); + + method.setAccessible(true); + + return method.invoke(ui, null); + } + + private static void fail(String s) { + throw new RuntimeException("Test failed: " + s); + } +} diff --git a/jdk/test/sun/security/krb5/DnsFallback.java b/jdk/test/sun/security/krb5/DnsFallback.java index 95fbf3b165b..54aa8301eff 100644 --- a/jdk/test/sun/security/krb5/DnsFallback.java +++ b/jdk/test/sun/security/krb5/DnsFallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,8 @@ /* * @test * @bug 6673164 - * @summary dns_fallback parse error + * @bug 6552334 + * @summary fix dns_fallback parse error, and use dns by default */ import sun.security.krb5.*; @@ -31,6 +32,8 @@ import java.io.*; public class DnsFallback { public static void main(String[] args) throws Exception { + + // for 6673164 check("true", "true", true); check("false", "true", false); check("true", "false", true); @@ -39,6 +42,9 @@ public class DnsFallback { check("false", null, false); check(null, "true", true); check(null, "false", false); + + // for 6552334 + check(null, null, true); } static void check(String realm, String fallback, boolean output) throws Exception { diff --git a/jdk/test/sun/security/krb5/ParseCAPaths.java b/jdk/test/sun/security/krb5/ParseCAPaths.java new file mode 100644 index 00000000000..9f6772d4fca --- /dev/null +++ b/jdk/test/sun/security/krb5/ParseCAPaths.java @@ -0,0 +1,98 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6789935 + * @summary cross-realm capath search error + */ + +import java.util.Arrays; +import sun.security.krb5.Realm; + +public class ParseCAPaths { + static boolean failed = false; + public static void main(String[] args) throws Exception { + System.setProperty("java.security.krb5.conf", System.getProperty("test.src", ".") +"/krb5-capaths.conf"); + //System.setProperty("sun.security.krb5.debug", "true"); + + // Standard example + check("ANL.GOV", "TEST.ANL.GOV", "ANL.GOV"); + check("ANL.GOV", "ES.NET", "ANL.GOV"); + check("ANL.GOV", "PNL.GOV", "ANL.GOV", "ES.NET"); + check("ANL.GOV", "NERSC.GOV", "ANL.GOV", "ES.NET"); + // Hierachical + check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM"); // 2 common + check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM", // 1 common + "COM", "N3.COM"); + check("N1.COM", "N2.COM", "N1.COM", "COM"); // 1 common + check("N1", "N2", "N1"); // 0 common + // Extra garbages + check("A1.COM", "A4.COM", "A1.COM", "A2.COM"); + check("B1.COM", "B3.COM", "B1.COM", "B2.COM"); + // Missing is "." + check("C1.COM", "C3.COM", "C1.COM", "C2.COM"); + // Multiple path + check("D1.COM", "D4.COM", "D1.COM", "D2.COM"); + check("E1.COM", "E4.COM", "E1.COM", "E2.COM"); + check("F1.COM", "F4.COM", "F1.COM", "F9.COM"); + // Infinite loop + check("G1.COM", "G3.COM", "G1.COM", "COM"); + check("H1.COM", "H3.COM", "H1.COM"); + check("I1.COM", "I4.COM", "I1.COM", "I5.COM"); + + if (failed) { + throw new Exception("Failed somewhere."); + } + } + + static void check(String from, String to, String... paths) { + try { + check2(from, to, paths); + } catch (Exception e) { + failed = true; + e.printStackTrace(); + } + } + static void check2(String from, String to, String... paths) + throws Exception { + System.out.println(from + " -> " + to); + System.out.println(" expected: " + Arrays.toString(paths)); + String[] result = Realm.getRealmsList(from, to); + System.out.println(" result: " + Arrays.toString(result)); + if (result == null) { + if (paths.length == 0) { + // OK + } else { + throw new Exception("Shouldn't have a valid path."); + } + } else if(result.length != paths.length) { + throw new Exception("Length of path not correct"); + } else { + for (int i=0; i bs = ((X509Certificate)ks.getCertificate(alias)).getExtendedKeyUsage(); + int found = 0; + for (String p: pos) { + if (bs.contains(p)) { + found++; + } else { + throw new RuntimeException("EKU: not included " + p); + } + } + if (found != bs.size()) { + throw new RuntimeException("EKU: more items than expected"); + } + } + } + CheckEKU cx = new CheckEKU(); + assertTrue(((X509CertImpl)ks.getCertificate("eku1")).getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical()); + assertTrue(!((X509CertImpl)ks.getCertificate("eku2")).getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical()); + cx.check(ks, "eku1", "1.3.6.1.5.5.7.3.1"); + cx.check(ks, "eku2", "1.3.6.1.5.5.7.3.2"); + cx.check(ks, "eku3", "1.3.6.1.5.5.7.3.3"); + cx.check(ks, "eku4", "1.3.6.1.5.5.7.3.4"); + cx.check(ks, "eku8", "1.3.6.1.5.5.7.3.8"); + cx.check(ks, "eku9", "1.3.6.1.5.5.7.3.9"); + cx.check(ks, "eku10", "2.5.29.37.0"); + cx.check(ks, "eku11", "1.3.6.1.5.5.7.3.4", "1.2.3.4", "1.3.5.7"); + + // SAN + testOK("", pre+"san1 -ext san:critical=email:me@me.org"); + testOK("", pre+"san2 -ext san=uri:http://me.org"); + testOK("", pre+"san3 -ext san=dns:me.org"); + testOK("", pre+"san4 -ext san=ip:192.168.0.1"); + testOK("", pre+"san5 -ext san=oid:1.2.3.4"); + testOK("", pre+"san235 -ext san=uri:http://me.org,dns:me.org,oid:1.2.3.4"); + + ks = loadStore("x.jks", "changeit", "JKS"); + class CheckSAN { + // Please sort items with name type + void check(KeyStore ks, String alias, int type, Object... items) throws Exception { + int pos = 0; + System.err.print("x"); + Object[] names = null; + if (type == 0) names = ((X509Certificate)ks.getCertificate(alias)).getSubjectAlternativeNames().toArray(); + else names = ((X509Certificate)ks.getCertificate(alias)).getIssuerAlternativeNames().toArray(); + Arrays.sort(names, new Comparator() { + public int compare(Object o1, Object o2) { + int i1 = (Integer)((List)o1).get(0); + int i2 = (Integer)((List)o2).get(0); + return i1 - i2; + } + }); + for (Object o: names) { + List l = (List)o; + for (Object o2: l) { + if (!items[pos++].equals(o2)) { + throw new RuntimeException("Not equals at " + pos + + ": " + items[pos-1] + " vs " + o2); + } + } + } + if (pos != items.length) { + throw new RuntimeException("Extra items, pos is " + pos); + } + } + } + CheckSAN csan = new CheckSAN(); + assertTrue(((X509CertImpl)ks.getCertificate("san1")).getSubjectAlternativeNameExtension().isCritical()); + assertTrue(!((X509CertImpl)ks.getCertificate("san2")).getSubjectAlternativeNameExtension().isCritical()); + csan.check(ks, "san1", 0, 1, "me@me.org"); + csan.check(ks, "san2", 0, 6, "http://me.org"); + csan.check(ks, "san3", 0, 2, "me.org"); + csan.check(ks, "san4", 0, 7, "192.168.0.1"); + csan.check(ks, "san5", 0, 8, "1.2.3.4"); + csan.check(ks, "san235", 0, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4"); + + // IAN + testOK("", pre+"ian1 -ext ian:critical=email:me@me.org"); + testOK("", pre+"ian2 -ext ian=uri:http://me.org"); + testOK("", pre+"ian3 -ext ian=dns:me.org"); + testOK("", pre+"ian4 -ext ian=ip:192.168.0.1"); + testOK("", pre+"ian5 -ext ian=oid:1.2.3.4"); + testOK("", pre+"ian235 -ext ian=uri:http://me.org,dns:me.org,oid:1.2.3.4"); + + ks = loadStore("x.jks", "changeit", "JKS"); + assertTrue(((X509CertImpl)ks.getCertificate("ian1")).getIssuerAlternativeNameExtension().isCritical()); + assertTrue(!((X509CertImpl)ks.getCertificate("ian2")).getIssuerAlternativeNameExtension().isCritical()); + csan.check(ks, "ian1", 1, 1, "me@me.org"); + csan.check(ks, "ian2", 1, 6, "http://me.org"); + csan.check(ks, "ian3", 1, 2, "me.org"); + csan.check(ks, "ian4", 1, 7, "192.168.0.1"); + csan.check(ks, "ian5", 1, 8, "1.2.3.4"); + csan.check(ks, "ian235", 1, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4"); + + // SIA + testOK("", pre+"sia1 -ext sia=care:uri:ldap://ca.com/cn=CA"); + testOK("", pre+"sia2 -ext sia=ts:email:ts@ca.com"); + testFail("SIA never critical", pre+"sia3 -ext sia:critical=ts:email:ts@ca.com"); + + ks = loadStore("x.jks", "changeit", "JKS"); + class CheckSia { + void check(KeyStore ks, String alias, int type, Object... items) throws Exception { + int pos = 0; + System.err.print("x"); + AccessDescription[] ads = null; + if (type == 0) { + SubjectInfoAccessExtension siae = (SubjectInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.SubjectInfoAccess_Id); + ads = siae.getAccessDescriptions().toArray(new AccessDescription[0]); + } else { + AuthorityInfoAccessExtension aiae = (AuthorityInfoAccessExtension)((X509CertImpl)ks.getCertificate(alias)).getExtension(PKIXExtensions.AuthInfoAccess_Id); + ads = aiae.getAccessDescriptions().toArray(new AccessDescription[0]); + } + Arrays.sort(ads, new Comparator() { + @Override + public int compare(AccessDescription o1, AccessDescription o2) { + return o1.getAccessMethod().toString().compareTo(o2.getAccessMethod().toString()); + } + }); + for (AccessDescription ad: ads) { + if (!ad.getAccessMethod().equals(items[pos++]) || + !new Integer(ad.getAccessLocation().getType()).equals(items[pos++])) { + throw new RuntimeException("Not same type at " + pos); + } + String name = null; + switch (ad.getAccessLocation().getType()) { + case 1: + name = ((RFC822Name)ad.getAccessLocation().getName()).getName(); + break; + case 6: + name = ((URIName)ad.getAccessLocation().getName()).getURI().toString(); + break; + default: + throw new RuntimeException("Not implemented: " + ad); + } + if (!name.equals(items[pos++])) { + throw new Exception("Name not same for " + ad + " at pos " + pos); + } + } + } + } + CheckSia csia = new CheckSia(); + assertTrue(!((X509CertImpl)ks.getCertificate("sia1")).getExtension(PKIXExtensions.SubjectInfoAccess_Id).isCritical()); + csia.check(ks, "sia1", 0, AccessDescription.Ad_CAREPOSITORY_Id, 6, "ldap://ca.com/cn=CA"); + csia.check(ks, "sia2", 0, AccessDescription.Ad_TIMESTAMPING_Id, 1, "ts@ca.com"); + + // AIA + testOK("", pre+"aia1 -ext aia=cai:uri:ldap://ca.com/cn=CA"); + testOK("", pre+"aia2 -ext aia=ocsp:email:ocsp@ca.com"); + testFail("AIA never critical", pre+"aia3 -ext aia:critical=ts:email:ts@ca.com"); + + ks = loadStore("x.jks", "changeit", "JKS"); + assertTrue(!((X509CertImpl)ks.getCertificate("aia1")).getExtension(PKIXExtensions.AuthInfoAccess_Id).isCritical()); + csia.check(ks, "aia1", 1, AccessDescription.Ad_CAISSUERS_Id, 6, "ldap://ca.com/cn=CA"); + csia.check(ks, "aia2", 1, AccessDescription.Ad_OCSP_Id, 1, "ocsp@ca.com"); + + // OID + testOK("", pre+"oid1 -ext 1.2.3:critical=0102"); + testOK("", pre+"oid2 -ext 1.2.3"); + testOK("", pre+"oid12 -ext 1.2.3 -ext 1.2.4=01:02:03"); + + ks = loadStore("x.jks", "changeit", "JKS"); + class CheckOid { + void check(KeyStore ks, String alias, String oid, byte[] value) throws Exception { + int pos = 0; + System.err.print("x"); + Extension ex = ((X509CertImpl)ks.getCertificate(alias)).getExtension(new ObjectIdentifier(oid)); + if (!Arrays.equals(value, ex.getValue())) { + throw new RuntimeException("Not same content in " + alias + " for " + oid); + } + } + } + CheckOid coid = new CheckOid(); + assertTrue(((X509CertImpl)ks.getCertificate("oid1")).getExtension(new ObjectIdentifier("1.2.3")).isCritical()); + assertTrue(!((X509CertImpl)ks.getCertificate("oid2")).getExtension(new ObjectIdentifier("1.2.3")).isCritical()); + coid.check(ks, "oid1", "1.2.3", new byte[]{1,2}); + coid.check(ks, "oid2", "1.2.3", new byte[]{}); + coid.check(ks, "oid12", "1.2.3", new byte[]{}); + coid.check(ks, "oid12", "1.2.4", new byte[]{1,2,3}); + + // honored + testOK("", pre+"ca"); + testOK("", pre+"a"); + // request: BC,KU,1.2.3,1.2.4,1.2.5 + testOK("", simple+"-alias a -certreq " + + "-ext BC=1 -ext KU=crl " + + "-ext 1.2.3=01 -ext 1.2.4:critical=0102 -ext 1.2.5=010203 " + + "-rfc -file test.req"); + // printcertreq + testOK("", "-printcertreq -file test.req"); + // issue: deny KU, change criticality of 1.2.3 and 1.2.4, change content of BC, add 2.3.4 + testOK("", simple+"-gencert -alias ca -infile test.req -ext " + + "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " + + "-ext BC=2 -ext 2.3.4=01020304 " + + "-debug -rfc -outfile test.cert"); + testOK("", simple+"-importcert -file test.cert -alias a"); + ks = loadStore("x.jks", "changeit", "JKS"); + X509CertImpl a = (X509CertImpl)ks.getCertificate("a"); + assertTrue(a.getAuthorityKeyIdentifierExtension() != null); + assertTrue(a.getSubjectKeyIdentifierExtension() != null); + assertTrue(a.getKeyUsage() == null); + assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical()); + assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical()); + assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical()); + assertTrue(a.getExtensionValue("1.2.3").length == 3); + assertTrue(a.getExtensionValue("1.2.4").length == 4); + assertTrue(a.getExtensionValue("1.2.5").length == 5); + assertTrue(a.getBasicConstraints() == 2); + assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical()); + assertTrue(a.getExtensionValue("2.3.4").length == 6); + + remove("x.jks"); + remove("test.req"); + remove("test.cert"); + } + void i18nTest() throws Exception { // 1. keytool -help remove("x.jks"); - try { - test("", "-help"); - assertTrue(false, "Cannot come here"); - } catch(RuntimeException e) { - assertTrue(e.getMessage().indexOf("NO ERROR, SORRY") != -1, "No error"); - } + testOK("", "-help"); + // 2. keytool -genkey -v -keysize 512 Enter "a" for the keystore password. Check error (password too short). Enter "password" for the keystore password. Hit 'return' for "first and last name", "organizational unit", "City", "State", and "Country Code". Type "yes" when they ask you if everything is correct. Type 'return' for new key password. testOK("a\npassword\npassword\nMe\nHere\nNow\nPlace\nPlace\nUS\nyes\n\n", "-genkey -v -keysize 512 -keystore x.jks"); // 3. keytool -list -v -storepass password testOK("", "-list -v -storepass password -keystore x.jks"); // 4. keytool -list -v Type "a" for the keystore password. Check error (wrong keystore password). testFail("a\n", "-list -v -keystore x.jks"); - assertTrue(ex.indexOf("password was incorrect") != -1, ""); + assertTrue(ex.indexOf("password was incorrect") != -1); // 5. keytool -genkey -v -keysize 512 Enter "password" as the password. Check error (alias 'mykey' already exists). testFail("password\n", "-genkey -v -keysize 512 -keystore x.jks"); - assertTrue(ex.indexOf("alias already exists") != -1, ""); + assertTrue(ex.indexOf("alias already exists") != -1); // 6. keytool -genkey -v -keysize 512 -alias mykey2 -storepass password Hit 'return' for "first and last name", "organizational unit", "City", "State", and "Country Code". Type "yes" when they ask you if everything is correct. Type 'return' for new key password. testOK("\n\n\n\n\n\nyes\n\n", "-genkey -v -keysize 512 -alias mykey2 -storepass password -keystore x.jks"); // 7. keytool -list -v Type 'password' for the store password. testOK("password\n", "-list -v -keystore x.jks"); // 8. keytool -keypasswd -v -alias mykey2 -storepass password Type "a" for the new key password. Type "aaaaaa" for the new key password. Type "bbbbbb" when re-entering the new key password. Type "a" for the new key password. Check Error (too many failures). testFail("a\naaaaaa\nbbbbbb\na\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks"); - assertTrue(ex.indexOf("Too many failures - try later") != -1, ""); + assertTrue(ex.indexOf("Too many failures - try later") != -1); // 9. keytool -keypasswd -v -alias mykey2 -storepass password Type "aaaaaa" for the new key password. Type "aaaaaa" when re-entering the new key password. testOK("aaaaaa\naaaaaa\n", "-keypasswd -v -alias mykey2 -storepass password -keystore x.jks"); // 10. keytool -selfcert -v -alias mykey -storepass password @@ -864,7 +1207,7 @@ public class KeyToolTest { testOK("", "-export -v -alias mykey -file cert -storepass password -keystore x.jks"); // 13. keytool -import -v -file cert -storepass password Check error (Certificate reply and cert are the same) testFail("", "-import -v -file cert -storepass password -keystore x.jks"); - assertTrue(ex.indexOf("Certificate reply and certificate in keystore are identical") != -1, ""); + assertTrue(ex.indexOf("Certificate reply and certificate in keystore are identical") != -1); // 14. keytool -printcert -file cert testOK("", "-printcert -file cert -keystore x.jks"); remove("cert"); @@ -875,26 +1218,26 @@ public class KeyToolTest { // 1. keytool -storepasswd -storepass password -new abc Check error (password too short) testFail("", "-storepasswd -storepass password -new abc"); - assertTrue(ex.indexOf("New password must be at least 6 characters") != -1, ""); + assertTrue(ex.indexOf("New password must be at least 6 characters") != -1); // Changed, no NONE needed now // 2. keytool -list -storetype PKCS11 Check error (-keystore must be NONE) //testFail("", "-list -storetype PKCS11"); - //assertTrue(err.indexOf("keystore must be NONE") != -1, ""); + //assertTrue(err.indexOf("keystore must be NONE") != -1); // 3. keytool -storepasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation) testFail("", "-storepasswd -storetype PKCS11 -keystore NONE"); - assertTrue(ex.indexOf("UnsupportedOperationException") != -1, ""); + assertTrue(ex.indexOf("UnsupportedOperationException") != -1); // 4. keytool -keypasswd -storetype PKCS11 -keystore NONE Check error (unsupported operation) testFail("", "-keypasswd -storetype PKCS11 -keystore NONE"); - assertTrue(ex.indexOf("UnsupportedOperationException") != -1, ""); + assertTrue(ex.indexOf("UnsupportedOperationException") != -1); // 5. keytool -list -protected -storepass password Check error (password can not be specified with -protected) testFail("", "-list -protected -storepass password -keystore x.jks"); - assertTrue(ex.indexOf("if -protected is specified, then") != -1, ""); + assertTrue(ex.indexOf("if -protected is specified, then") != -1); // 6. keytool -keypasswd -protected -keypass password Check error (password can not be specified with -protected) testFail("", "-keypasswd -protected -keypass password -keystore x.jks"); - assertTrue(ex.indexOf("if -protected is specified, then") != -1, ""); + assertTrue(ex.indexOf("if -protected is specified, then") != -1); // 7. keytool -keypasswd -protected -new password Check error (password can not be specified with -protected) testFail("", "-keypasswd -protected -new password -keystore x.jks"); - assertTrue(ex.indexOf("if -protected is specified, then") != -1, ""); + assertTrue(ex.indexOf("if -protected is specified, then") != -1); remove("x.jks"); } @@ -911,11 +1254,11 @@ public class KeyToolTest { testOK("", "-printcert -file genkey.cert"); testOK("", p11Arg + "-storepass test12 -selfcert -alias genkey -dname cn=selfCert"); testOK("", p11Arg + "-storepass test12 -list -alias genkey -v"); - assertTrue(out.indexOf("Owner: CN=selfCert") != -1, ""); + assertTrue(out.indexOf("Owner: CN=selfCert") != -1); //(check that cert subject DN is [cn=selfCert]) testOK("", p11Arg + "-storepass test12 -delete -alias genkey"); testOK("", p11Arg + "-storepass test12 -list"); - assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, ""); + assertTrue(out.indexOf("Your keystore contains 0 entries") != -1); //(check for empty database listing) //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db"); remove("genkey.cert"); @@ -943,6 +1286,15 @@ public class KeyToolTest { t.sqeTest(); t.testAll(); t.i18nTest(); + t.v3extTest("RSA"); + t.v3extTest("DSA"); + boolean testEC = true; + try { + KeyPairGenerator.getInstance("EC"); + } catch (NoSuchAlgorithmException nae) { + testEC = false; + } + if (testEC) t.v3extTest("EC"); } if (System.getProperty("nss") != null) { diff --git a/jdk/test/sun/security/tools/keytool/autotest.sh b/jdk/test/sun/security/tools/keytool/autotest.sh index 04c00c14ebf..e3431836b1a 100644 --- a/jdk/test/sun/security/tools/keytool/autotest.sh +++ b/jdk/test/sun/security/tools/keytool/autotest.sh @@ -1,5 +1,5 @@ # -# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ # @summary (almost) all keytool behaviors # @author Weijun Wang # +# This test is only executed on several platforms +# # set a few environment variables so that the shell-script can run stand-alone # in the source directory if [ "${TESTSRC}" = "" ] ; then @@ -88,7 +90,7 @@ cp ${NSS}${FS}db${FS}secmod.db . chmod u+w key3.db chmod u+w cert8.db -echo | ${TESTJAVA}${FS}bin${FS}java -Dfile -Dnss \ +echo | ${TESTJAVA}${FS}bin${FS}java -Dnss \ -Dnss.lib=${NSS}${FS}lib${FS}${PF}${FS}${LIBNAME} \ KeyToolTest status=$? @@ -99,8 +101,8 @@ rm -f key3.db rm -f secmod.db rm HumanInputStream*.class -rm KeyToolTest.class -rm TestException.class +rm KeyToolTest*.class +rm TestException.class exit $status diff --git a/jdk/test/sun/security/tools/keytool/standard.sh b/jdk/test/sun/security/tools/keytool/standard.sh new file mode 100644 index 00000000000..fe4a0a81312 --- /dev/null +++ b/jdk/test/sun/security/tools/keytool/standard.sh @@ -0,0 +1,64 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @summary (almost) all keytool behaviors +# @author Weijun Wang +# +# This test is always excecuted. +# +# set a few environment variables so that the shell-script can run stand-alone +# in the source directory +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi +if [ "${TESTCLASSES}" = "" ] ; then + TESTCLASSES="." +fi +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + ;; + * ) + FS="/" + ;; +esac + +${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}KeyToolTest.java || exit 10 + +echo | ${TESTJAVA}${FS}bin${FS}java -Dfile KeyToolTest +status=$? + +rm HumanInputStream*.class +rm KeyToolTest*.class +rm TestException.class + +exit $status + diff --git a/jdk/test/sun/security/util/DerValue/EmptyValue.java b/jdk/test/sun/security/util/DerValue/EmptyValue.java new file mode 100644 index 00000000000..b2803802957 --- /dev/null +++ b/jdk/test/sun/security/util/DerValue/EmptyValue.java @@ -0,0 +1,44 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6804045 + * @summary DerValue does not accept empty OCTET STRING + */ + +import sun.security.util.DerValue; + +public class EmptyValue { + + public static void main(String[] args) throws Exception { + DerValue v = new DerValue(new byte[]{4,0}); + if (v.getOctetString().length != 0) { + throw new Exception("Get octet string error"); + } + v = new DerValue(new byte[]{0x30,0}); + if (v.data.available() != 0) { + throw new Exception("Get sequence error"); + } + } +} diff --git a/jdk/test/sun/security/x509/Extensions/BCNull.java b/jdk/test/sun/security/x509/Extensions/BCNull.java new file mode 100644 index 00000000000..e906f576992 --- /dev/null +++ b/jdk/test/sun/security/x509/Extensions/BCNull.java @@ -0,0 +1,37 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @summary BasicConstraintsExtension does not encode when (ca==false && pathLen<0) + * @bug 6803376 + */ + +import sun.security.x509.BasicConstraintsExtension; +import java.io.ByteArrayOutputStream; + +public class BCNull { + public static void main(String [] args) throws Exception { + new BasicConstraintsExtension(false, -1).encode(new ByteArrayOutputStream()); + } +} diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index f885bbeb2db..7b0ada3c594 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -5518,3 +5518,11 @@ FormatData/is_IS/NumberPatterns/1=#,##0. \u00A4;-#,##0. \u00A4 FormatData/sv/AmPmMarkers/0=fm FormatData/sv/AmPmMarkers/1=em +# JE, GG, IM (6544471) +LocaleNames//JE=Jersey +LocaleNames//GG=Guernsey +LocaleNames//IM=Isle Of Man + +# BL, MF (6627549) +LocaleNames//BL=Saint Barth\u00e9lemy +LocaleNames//MF=Saint Martin diff --git a/langtools/.hgtags b/langtools/.hgtags index 8a9c92a42b0..6e74f307ed3 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -19,3 +19,8 @@ ded6b40f558e8d19b3c17715b3d67ee001606645 jdk7-b41 5e5567c2db56a931cf07768218c20903d9828b5f jdk7-b42 e2f8f6daee9decd5721d598dacf4d0b5915651df jdk7-b43 28f0b10d6c1afc106465c13b8c663a6afa4fb1a1 jdk7-b44 +30db5e0aaf83fe262d9a7227d3fc3e451cd5d459 jdk7-b45 +be546a6c08e3c31fba2edcae1de43ae3515d2e59 jdk7-b46 +2b8f6bab23926aa32b9cf7e4c540b9d1ce74b7d5 jdk7-b47 +c53007f34195f69223bdd4125ec6c0740f7d6736 jdk7-b48 +d17d927ad9bdfafae32451645d182acb7bed7be6 jdk7-b49 diff --git a/langtools/make/README b/langtools/make/README index 466426d8ad6..bc8873178ef 100644 --- a/langtools/make/README +++ b/langtools/make/README @@ -15,7 +15,7 @@ that expect to be able to build this workspace with GNU Make. System Requirements: Ant: version 1.6.5 or later - NetBeans: version 5.0 or later (optional) + NetBeans: version 6.0 or later (optional) JDK: currently version 1.5.0, although 1.6.0 is recommended OS: any system supporting the above tools diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 38fd0f4705d..6e792bb106d 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -66,7 +66,7 @@ javac.no.jdk.warnings = -XDignore.symbol.file=true # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all,-deprecation,-fallthrough,-serial,-unchecked,-cast +javac.lint.opts = -Xlint:all -Werror # options for the task for javac javadoc.jls3.url=http://java.sun.com/docs/books/jls/ diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 79bd060dd69..770f3dd040c 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -392,6 +392,7 @@ + @@ -433,6 +434,7 @@ + @@ -471,6 +473,7 @@ + @@ -493,6 +496,7 @@ destdir="@{gensrc.dir}" includes="**/*.properties"/> - - + diff --git a/langtools/make/netbeans/README b/langtools/make/netbeans/README index 7208e598e6a..58cfec07cee 100644 --- a/langtools/make/netbeans/README +++ b/langtools/make/netbeans/README @@ -1,28 +1,39 @@ -Working on the "langtools" workspace using NetBeans. +Using NetBeans to work on the langtools repository. -This directory (make/netbeans) contains NetBeans projects that -allow you to work on the various tools using the NetBeans IDE. +Netbeans 6.0 or later is recommended. -NetBeans 5.0 or later is required and sufficient to use these -projects. This is different from other projects in OpenJDK, -which requires version 6.0 or later. +The "langtools" project in this directory allows you to +edit, run, test and debug the tools in the OpenJDK langtools +repository. -The following projects are provided: +The repository contains a number of tools: + apt, javac, javadoc and its doclets, javah and javap. -compiler: for working on the compiler, javac -javadoc: for working on the documentation tool, javadoc -doclets: for working on the standard doclets used by the - documentation tool, javadoc -javah: for working on the C header tool, javah -javap: for working on the disassembler, javap -apt: for working on the annotation processing tool, apt. - Note that this is just provided for completeness; - the tool has been superceded by new features in javac, - and work on apt itself is discouraged. +Build Properties. -However, any tool can be worked on from any project; the only difference -between these projects is the behavior of the standard NetBeans actions, -so that "Build" in the compiler project will build the compiler, etc. +To build this repository, you must set some properties for Ant. +You can set these properties in a number of ways: +- Set the properties in the Properties panel under Tool> Options> Ant. + Properties set this way will apply globally to all the langtools + repositories you may be working on. +- Create a file build.properties in the root directory of a + langtools repository, and set the properties in that file. + These properties will be specific to that repository. +To build the repository, at a minimum you must set the "boot.java.home" +property. To run the tools, you must also set "target.java.home". To +run the regression tests, you must set "jtreg.home". + +By default, the build and test targets will build and test all +of these tools. The run and debug targets will prompt you for the +name of a tool to execute. + +As an alternative, you can focus on a single tool. When you do +this, you will still see all the source code for all the tools, +but the various Ant targets will now be focussed on the selected tool. +To focus on a tool, bring up the context menu on the "langtools" +project (i.e. right-click on the project) and select "Select Tool". +This brings up a dialog which allows you to specify which tool you +wish to work on, and the arguments to use if and when you run it. diff --git a/langtools/make/netbeans/apt/README b/langtools/make/netbeans/apt/README deleted file mode 100644 index 6fa70ee080e..00000000000 --- a/langtools/make/netbeans/apt/README +++ /dev/null @@ -1,15 +0,0 @@ -"apt" project README. - -This project is for working on the annotation processing tool (apt) -in the OpenJDK langtools component. - -The tool was provided in Java 1.5, but has been superceded by new -features in the compiler (javac) in Java 6. apt itself is now -deprecated, and any further devlopment on it is strongly discouraged. - -The main class for the tool is com.sun.tools.apt.Main. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/apt/build.xml b/langtools/make/netbeans/apt/build.xml deleted file mode 100644 index 6b4a72e3a4a..00000000000 --- a/langtools/make/netbeans/apt/build.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/apt/nbproject/project.xml b/langtools/make/netbeans/apt/nbproject/project.xml deleted file mode 100644 index 6987228768f..00000000000 --- a/langtools/make/netbeans/apt/nbproject/project.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - -]> - - org.netbeans.modules.ant.freeform - - - - apt - - ../../.. - - - - - ${root} - - - - java - ${root}/src/share/classes - - - - tests - ${root}/test - - - - build - ${root}/make - - - - &standard-ide-actions-no-javadoc; - - - folder - ${root}/build/classes - build - - - - - - ${root}/src/share/classes - - - - ${root}/test - - - - ${root}/make - - - - README - - - - &standard-context-menu-items-no-javadoc; - - - - - - - ${root}/src/share/classes - ${root}/build/classes - 1.5 - - - - diff --git a/langtools/make/netbeans/common/shared.xml b/langtools/make/netbeans/common/shared.xml deleted file mode 100644 index 015a08c8b77..00000000000 --- a/langtools/make/netbeans/common/shared.xml +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - - - - - - - - - Must set property 'includes' - - - - - - - - - - - - - Must set property 'run.classname' - - - - - - - - Some tests failed; see report for details. - - - - - - - - - - - - - Must set property 'debug.classname' - - - - - - - - Must set property 'jtreg.tests' - - - - - - - - Must set property 'class' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/common/standard-context-menu-items-no-javadoc.ent b/langtools/make/netbeans/common/standard-context-menu-items-no-javadoc.ent deleted file mode 100644 index c40ee69c213..00000000000 --- a/langtools/make/netbeans/common/standard-context-menu-items-no-javadoc.ent +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/common/standard-ide-actions-no-javadoc.ent b/langtools/make/netbeans/common/standard-ide-actions-no-javadoc.ent deleted file mode 100644 index 912daf729a8..00000000000 --- a/langtools/make/netbeans/common/standard-ide-actions-no-javadoc.ent +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - build - - - - clean - - - - clean - build - - - - compile-single - ${root}/src/share/classes - - includes - ${root}/src/share/classes - \.java$ - relative-path - - , - - - - - - run - - - - run-single - - run.classname - ${root}/src/share/classes - \.java$ - java-name - - - - - - - - - - jtreg - - jtreg.tests - ${root}/test - \.(java|sh)$ - relative-path - - , - - - - - - jtreg - - - - debug-nb - - - - debug-single-nb - - debug.classname - ${root}/src/share/classes - \.java$ - java-name - - - - - - - - - - debug-jtreg-nb - - jtreg.tests - ${root}/test - \.(java|sh)$ - relative-path - - - - - - - - debug-fix - ${root}/src/share/classes - - class - ${root}/src/share/classes - \.java$ - relative-path-noext - - - - - - - - -javadoc-nb - diff --git a/langtools/make/netbeans/compiler/README b/langtools/make/netbeans/compiler/README deleted file mode 100644 index 9dc7ff11888..00000000000 --- a/langtools/make/netbeans/compiler/README +++ /dev/null @@ -1,11 +0,0 @@ -"compiler" project README. - -This project is for working on the compiler tool (javac) -in the OpenJDK langtools component. - -The main class for the tool is com.sun.tools.javac.Main. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/compiler/build.xml b/langtools/make/netbeans/compiler/build.xml deleted file mode 100644 index 1c1df801a52..00000000000 --- a/langtools/make/netbeans/compiler/build.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/compiler/nbproject/project.xml b/langtools/make/netbeans/compiler/nbproject/project.xml deleted file mode 100644 index ac52705ef99..00000000000 --- a/langtools/make/netbeans/compiler/nbproject/project.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - -]> - - org.netbeans.modules.ant.freeform - - - - compiler - - ../../.. - - - - - ${root} - - - - java - ${root}/src/share/classes - - - - tests - ${root}/test - - - - build - ${root}/make - - - - &standard-ide-actions; - - - folder - ${root}/build/classes - build - - - - - - ${root}/src/share/classes - - - - ${root}/test - - - - ${root}/make - - - - README - - - - &standard-context-menu-items; - - - - - - - ${root}/src/share/classes - ${root}/build/classes - 1.5 - - - - diff --git a/langtools/make/netbeans/doclets/README b/langtools/make/netbeans/doclets/README deleted file mode 100644 index eb7e61b6524..00000000000 --- a/langtools/make/netbeans/doclets/README +++ /dev/null @@ -1,16 +0,0 @@ -"doclets" project README. - -This project is for working on the standard doclets used by -the documentation tool (javadoc) in the OpenJDK langtools component. - -The doclets are invoked as part of the documentation tool (javadoc). -Using this project, you can also browse javadoc and any tools in langtools. -If you build the doclets, javadoc will be built automatically as well, -if necessary. - -The doclets are found in com.sun.tools.doclets. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/doclets/build.xml b/langtools/make/netbeans/doclets/build.xml deleted file mode 100644 index a390161c14d..00000000000 --- a/langtools/make/netbeans/doclets/build.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/doclets/nbproject/project.xml b/langtools/make/netbeans/doclets/nbproject/project.xml deleted file mode 100644 index f0fa2f45d74..00000000000 --- a/langtools/make/netbeans/doclets/nbproject/project.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - -]> - - org.netbeans.modules.ant.freeform - - - - doclets - - ../../.. - - - - - ${root} - - - - java - ${root}/src/share/classes - - - - tests - ${root}/test - - - - build - ${root}/make - - - - &standard-ide-actions-no-javadoc; - - - folder - ${root}/build/classes - build - - - - - - ${root}/src/share/classes - - - - ${root}/test - - - - ${root}/make - - - - README - - - - &standard-context-menu-items-no-javadoc; - - - - - - - ${root}/src/share/classes - ${root}/build/classes - 1.5 - - - - diff --git a/langtools/make/netbeans/javadoc/README b/langtools/make/netbeans/javadoc/README deleted file mode 100644 index e0027ccb397..00000000000 --- a/langtools/make/netbeans/javadoc/README +++ /dev/null @@ -1,16 +0,0 @@ -"javadoc" project README. - -This project is for working on the documentation tool (javadoc) -in the OpenJDK langtools component. - -javadoc is built on top of the compiler (javac). Using this -project, you can also browse javac and any tools in langtools. -If you build javadoc, javac will be built automatically as well, -if necessary. - -The main class for the tool is com.sun.tools.javadoc.Main. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/javadoc/build.xml b/langtools/make/netbeans/javadoc/build.xml deleted file mode 100644 index ba565a6bc58..00000000000 --- a/langtools/make/netbeans/javadoc/build.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/javah/README b/langtools/make/netbeans/javah/README deleted file mode 100644 index 6e94fb1f68d..00000000000 --- a/langtools/make/netbeans/javah/README +++ /dev/null @@ -1,21 +0,0 @@ -"javah" project README. - -This project is for working on the native header tool (javah) -in the OpenJDK langtools component. - -javah is built on top of the documentation tool (javadoc). Using this -project, you can also browse javadoc and any other tools in langtools. -If you build javah, javadoc will be built automatically as well, -if necessary. - -javah is in the process of being converted so that it runs directly on -top of the compiler, javac, using the annotation processing API, -instead of on top of the documentation tool, javadoc, using the -Doclet API. - -The main class for the tool is com.sun.tools.javah.Main. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/javah/build.xml b/langtools/make/netbeans/javah/build.xml deleted file mode 100644 index 578cd1458a9..00000000000 --- a/langtools/make/netbeans/javah/build.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/javah/nbproject/project.xml b/langtools/make/netbeans/javah/nbproject/project.xml deleted file mode 100644 index d4db76f39be..00000000000 --- a/langtools/make/netbeans/javah/nbproject/project.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - -]> - - org.netbeans.modules.ant.freeform - - - - javah - - ../../.. - - - - - ${root} - - - - java - ${root}/src/share/classes - - - - tests - ${root}/test - - - - build - ${root}/make - - - - &standard-ide-actions-no-javadoc; - - - folder - ${root}/build/classes - build - - - - - - ${root}/src/share/classes - - - - ${root}/test - - - - ${root}/make - - - - README - - - - &standard-context-menu-items-no-javadoc; - - - - - - - ${root}/src/share/classes - ${root}/build/classes - 1.5 - - - - diff --git a/langtools/make/netbeans/javap/README b/langtools/make/netbeans/javap/README deleted file mode 100644 index fb08ece3ee7..00000000000 --- a/langtools/make/netbeans/javap/README +++ /dev/null @@ -1,11 +0,0 @@ -"javap" project README. - -This project is for working on the disassembler tool (javap) -in the OpenJDK langtools component. - -The main class for the tool is sun.tools.javap.Main. - -NetBeans 5.0 or later is required and sufficient to use this -project, and others in the OpenJDK langtools component. -This is different from other projects in OpenJDK, which -require version 6.0 or later. diff --git a/langtools/make/netbeans/javap/build.xml b/langtools/make/netbeans/javap/build.xml deleted file mode 100644 index 818a933d5e4..00000000000 --- a/langtools/make/netbeans/javap/build.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/langtools/make/netbeans/javap/nbproject/project.xml b/langtools/make/netbeans/javap/nbproject/project.xml deleted file mode 100644 index 692e6726cf8..00000000000 --- a/langtools/make/netbeans/javap/nbproject/project.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - -]> - - org.netbeans.modules.ant.freeform - - - - javap - - ../../.. - - - - - ${root} - - - - java - ${root}/src/share/classes - - - - tests - ${root}/test - - - - build - ${root}/make - - - - &standard-ide-actions-no-javadoc; - - - folder - ${root}/build/classes - build - - - - - - ${root}/src/share/classes - - - - ${root}/test - - - - ${root}/make - - - - README - - - - &standard-context-menu-items-no-javadoc; - - - - - - - ${root}/src/share/classes - ${root}/build/classes - 1.5 - - - - diff --git a/langtools/make/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml new file mode 100644 index 00000000000..8f2b95f3031 --- /dev/null +++ b/langtools/make/netbeans/langtools/build.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set property 'includes' + + + + + + + + + + + + + + Must set property 'run.classname' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Some tests failed; see report for details. + + + + + + + + + + + + + Must set property 'debug.classname' + + + + + + + Must set property 'jtreg.tests' + + + + + + + + Must set property 'class' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/langtools/make/netbeans/javadoc/nbproject/project.xml b/langtools/make/netbeans/langtools/nbproject/project.xml similarity index 94% rename from langtools/make/netbeans/javadoc/nbproject/project.xml rename to langtools/make/netbeans/langtools/nbproject/project.xml index 61ebeb3b7af..e7509600556 100644 --- a/langtools/make/netbeans/javadoc/nbproject/project.xml +++ b/langtools/make/netbeans/langtools/nbproject/project.xml @@ -1,6 +1,6 @@ - + + ]> org.netbeans.modules.ant.freeform - javadoc + langtools ../../.. diff --git a/langtools/make/netbeans/common/standard-context-menu-items.ent b/langtools/make/netbeans/langtools/nbproject/standard-context-menu-items.ent similarity index 95% rename from langtools/make/netbeans/common/standard-context-menu-items.ent rename to langtools/make/netbeans/langtools/nbproject/standard-context-menu-items.ent index f6e1a96bb84..ab0568a009d 100644 --- a/langtools/make/netbeans/common/standard-context-menu-items.ent +++ b/langtools/make/netbeans/langtools/nbproject/standard-context-menu-items.ent @@ -1,6 +1,6 @@ + + + + diff --git a/langtools/make/netbeans/common/standard-ide-actions.ent b/langtools/make/netbeans/langtools/nbproject/standard-ide-actions.ent similarity index 92% rename from langtools/make/netbeans/common/standard-ide-actions.ent rename to langtools/make/netbeans/langtools/nbproject/standard-ide-actions.ent index 912daf729a8..3081fdfcdf0 100644 --- a/langtools/make/netbeans/common/standard-ide-actions.ent +++ b/langtools/make/netbeans/langtools/nbproject/standard-ide-actions.ent @@ -108,11 +108,11 @@ - debug-nb + debug - debug-single-nb + debug-single debug.classname ${root}/src/share/classes @@ -130,7 +130,7 @@ --> - debug-jtreg-nb + debug-jtreg jtreg.tests ${root}/test @@ -157,5 +157,17 @@ - -javadoc-nb + javadoc + + + + select-tool + + + + test-select-tool-1 + + + + test-select-tool-2 diff --git a/langtools/make/tools/SelectTool/SelectToolTask.java b/langtools/make/tools/SelectTool/SelectToolTask.java new file mode 100644 index 00000000000..0646c306e8a --- /dev/null +++ b/langtools/make/tools/SelectTool/SelectToolTask.java @@ -0,0 +1,284 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import javax.swing.SwingUtilities; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + * Task to allow the user to control langtools tools built when using NetBeans. + * + * There are two primary modes. + * 1) Property mode. In this mode, property names are provided to get values + * that may be specified by the user, either directly in a GUI dialog, or + * read from a properties file. If the GUI dialog is invoked, values may + * optionally be set for future use. + * 2) Setup mode. In this mode, no property names are provided, and the GUI + * is invoked to allow the user to set or reset values for use in property mode. + */ +public class SelectToolTask extends Task { + /** + * Set the location of the private properties file used to keep the retain + * user preferences for this repository. + */ + public void setPropertyFile(File propertyFile) { + this.propertyFile = propertyFile; + } + + /** + * Set the name of the property which will be set to the name of the + * selected tool, if any. If no tool is selected, the property will + * remain unset. + */ + public void setToolProperty(String toolProperty) { + this.toolProperty = toolProperty; + } + + /** + * Set the name of the property which will be set to the execution args of the + * selected tool, if any. The args default to an empty string. + */ + public void setArgsProperty(String argsProperty) { + this.argsProperty = argsProperty; + } + + /** + * Specify whether or not to pop up a dialog if the user has not specified + * a default value for a property. + */ + public void setAskIfUnset(boolean askIfUnset) { + this.askIfUnset = askIfUnset; + } + + @Override + public void execute() { + Project p = getProject(); + + Properties props = readProperties(propertyFile); + toolName = props.getProperty("tool.name"); + if (toolName != null) { + toolArgs = props.getProperty(toolName + ".args", ""); + } + + if (toolProperty == null || + askIfUnset && (toolName == null + || (argsProperty != null && toolArgs == null))) { + showGUI(props); + } + + // finally, return required values, if any + if (toolProperty != null && !(toolName == null || toolName.equals(""))) { + p.setProperty(toolProperty, toolName); + + if (argsProperty != null && toolArgs != null) + p.setProperty(argsProperty, toolArgs); + } + } + + void showGUI(Properties fileProps) { + Properties guiProps = new Properties(fileProps); + JOptionPane p = createPane(guiProps); + p.createDialog("Select Tool").setVisible(true); + + toolName = (String) toolChoice.getSelectedItem(); + toolArgs = argsField.getText(); + + if (defaultCheck.isSelected()) { + if (toolName.equals("")) { + fileProps.remove("tool.name"); + } else { + fileProps.put("tool.name", toolName); + fileProps.put(toolName + ".args", toolArgs); + } + writeProperties(propertyFile, fileProps); + } + } + + JOptionPane createPane(final Properties props) { + JPanel body = new JPanel(new GridBagLayout()); + GridBagConstraints lc = new GridBagConstraints(); + lc.insets.right = 10; + lc.insets.bottom = 3; + GridBagConstraints fc = new GridBagConstraints(); + fc.anchor = GridBagConstraints.WEST; + fc.gridx = 1; + fc.gridwidth = GridBagConstraints.REMAINDER; + fc.insets.bottom = 3; + + JLabel toolLabel = new JLabel("Tool:"); + body.add(toolLabel, lc); + String[] toolChoices = { "apt", "javac", "javadoc", "javah", "javap" }; + if (true || toolProperty == null) { + // include empty value in setup mode + List l = new ArrayList(Arrays.asList(toolChoices)); + l.add(0, ""); + toolChoices = l.toArray(new String[l.size()]); + } + toolChoice = new JComboBox(toolChoices); + if (toolName != null) + toolChoice.setSelectedItem(toolName); + toolChoice.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + String tn = (String) e.getItem(); + argsField.setText(getDefaultArgsForTool(props, tn)); + if (toolProperty != null) + okButton.setEnabled(!tn.equals("")); + } + }); + body.add(toolChoice, fc); + + argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40); + if (toolProperty == null || argsProperty != null) { + JLabel argsLabel = new JLabel("Args:"); + body.add(argsLabel, lc); + body.add(argsField, fc); + argsField.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + } + public void focusLost(FocusEvent e) { + String toolName = (String) toolChoice.getSelectedItem(); + if (toolName.length() > 0) + props.put(toolName + ".args", argsField.getText()); + } + }); + } + + defaultCheck = new JCheckBox("Set as default"); + if (toolProperty == null) + defaultCheck.setSelected(true); + else + body.add(defaultCheck, fc); + + final JOptionPane p = new JOptionPane(body); + okButton = new JButton("OK"); + okButton.setEnabled(toolProperty == null || (toolName != null && !toolName.equals(""))); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JDialog d = (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, p); + d.setVisible(false); + } + }); + p.setOptions(new Object[] { okButton }); + + return p; + } + + Properties readProperties(File file) { + Properties p = new Properties(); + if (file != null && file.exists()) { + Reader in = null; + try { + in = new BufferedReader(new FileReader(file)); + p.load(in); + in.close(); + } catch (IOException e) { + throw new BuildException("error reading property file", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + throw new BuildException("cannot close property file", e); + } + } + } + } + return p; + } + + void writeProperties(File file, Properties p) { + if (file != null) { + Writer out = null; + try { + File dir = file.getParentFile(); + if (dir != null && !dir.exists()) + dir.mkdirs(); + out = new BufferedWriter(new FileWriter(file)); + p.store(out, "langtools properties"); + out.close(); + } catch (IOException e) { + throw new BuildException("error writing property file", e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + throw new BuildException("cannot close property file", e); + } + } + } + } + } + + String getDefaultArgsForTool(Properties props, String tn) { + return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", ""); + } + + // Ant task parameters + private boolean askIfUnset; + private String toolProperty; + private String argsProperty; + private File propertyFile; + + // GUI components + private JComboBox toolChoice; + private JTextField argsField; + private JCheckBox defaultCheck; + private JButton okButton; + + // Result values for the client + private String toolName; + private String toolArgs; +} diff --git a/langtools/src/share/classes/com/sun/tools/apt/comp/AnnotationProcessingError.java b/langtools/src/share/classes/com/sun/tools/apt/comp/AnnotationProcessingError.java index 582b21c2ee9..f14dc60e6e3 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/comp/AnnotationProcessingError.java +++ b/langtools/src/share/classes/com/sun/tools/apt/comp/AnnotationProcessingError.java @@ -26,6 +26,7 @@ package com.sun.tools.apt.comp; public class AnnotationProcessingError extends Error { + private static final long serialVersionUID = 3279196183341719287L; AnnotationProcessingError(Throwable cause) { super(cause); } diff --git a/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java b/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java index abd09f5bf9e..d01887b6888 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java +++ b/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java @@ -316,8 +316,13 @@ public class Apt extends ListBuffer> { } providers = list.iterator(); - } else - providers = sun.misc.Service.providers(AnnotationProcessorFactory.class, aptCL); + } else { + @SuppressWarnings("unchecked") + Iterator iter = + sun.misc.Service.providers(AnnotationProcessorFactory.class, aptCL); + providers = iter; + + } } java.util.Map> factoryToAnnotation = diff --git a/langtools/src/share/classes/com/sun/tools/apt/comp/UsageMessageNeededException.java b/langtools/src/share/classes/com/sun/tools/apt/comp/UsageMessageNeededException.java index cbbbf8675cf..64a83ddb2c4 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/comp/UsageMessageNeededException.java +++ b/langtools/src/share/classes/com/sun/tools/apt/comp/UsageMessageNeededException.java @@ -26,4 +26,6 @@ package com.sun.tools.apt.comp; -public class UsageMessageNeededException extends RuntimeException {} +public class UsageMessageNeededException extends RuntimeException { + private static final long serialVersionUID = -3265159608992825840L; +} diff --git a/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java index 4b632d2d4ee..433a7dedf51 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/apt/main/JavaCompiler.java @@ -233,6 +233,7 @@ public class JavaCompiler extends com.sun.tools.javac.main.JavaCompiler { ListBuffer classes = new ListBuffer(); try { + JavacFileManager fm = (JavacFileManager)fileManager; //parse all files ListBuffer trees = new ListBuffer(); for (List l = filenames; l.nonEmpty(); l = l.tail) { @@ -250,7 +251,8 @@ public class JavaCompiler extends com.sun.tools.javac.main.JavaCompiler { continue; } } - trees.append(parse(l.head)); + JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next(); + trees.append(parse(fo)); } //enter symbols for all files diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/apt/RoundCompleteEventImpl.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/apt/RoundCompleteEventImpl.java index ae3a2258e6b..403ea6ffb51 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/apt/RoundCompleteEventImpl.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/apt/RoundCompleteEventImpl.java @@ -30,6 +30,8 @@ import com.sun.mirror.apt.RoundCompleteEvent; import com.sun.mirror.apt.RoundState; public class RoundCompleteEventImpl extends RoundCompleteEvent { + private static final long serialVersionUID = 7067621446720784300L; + public RoundCompleteEventImpl(AnnotationProcessorEnvironment source, RoundState rs) { super(source, rs); diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java index 64727fda4c1..9505eb2230d 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/declaration/AnnotationProxyMaker.java @@ -252,6 +252,7 @@ class AnnotationProxyMaker { */ private void typeMismatch(final Method method, final Attribute attr) { value = new ExceptionProxy() { + private static final long serialVersionUID = 8473323277815075163L; public String toString() { return ""; // eg: @Anno(value=) } @@ -270,6 +271,7 @@ class AnnotationProxyMaker { * type. */ private static class MirroredTypeExceptionProxy extends ExceptionProxy { + private static final long serialVersionUID = 6662035281599933545L; private MirroredTypeException ex; @@ -311,6 +313,7 @@ class AnnotationProxyMaker { * types. */ private static class MirroredTypesExceptionProxy extends ExceptionProxy { + private static final long serialVersionUID = -6670822532616693951L; private MirroredTypesException ex; diff --git a/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeVariableImpl.java b/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeVariableImpl.java index f96e01e0cd8..3d6a9fcaa80 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeVariableImpl.java +++ b/langtools/src/share/classes/com/sun/tools/apt/mirror/type/TypeVariableImpl.java @@ -64,7 +64,7 @@ public class TypeVariableImpl extends TypeMirrorImpl implements TypeVariable { * {@inheritDoc} */ public TypeParameterDeclaration getDeclaration() { - TypeSymbol sym = (TypeSymbol) type.tsym; + TypeSymbol sym = type.tsym; return env.declMaker.getTypeParameterDeclaration(sym); } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Annotation.java b/langtools/src/share/classes/com/sun/tools/classfile/Annotation.java index 9138132c636..37423cacc67 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Annotation.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Annotation.java @@ -37,6 +37,7 @@ import java.io.IOException; */ public class Annotation { static class InvalidAnnotation extends AttributeException { + private static final long serialVersionUID = -4620480740735772708L; InvalidAnnotation(String msg) { super(msg); } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/AttributeException.java b/langtools/src/share/classes/com/sun/tools/classfile/AttributeException.java index ee3decd947a..55d23f9c63b 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/AttributeException.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/AttributeException.java @@ -32,6 +32,7 @@ package com.sun.tools.classfile; * deletion without notice. */ public class AttributeException extends Exception { + private static final long serialVersionUID = -4231486387714867770L; AttributeException() { } AttributeException(String msg) { diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java index c3d8dff0fdf..ce99e119ade 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java @@ -37,6 +37,7 @@ import java.io.IOException; */ public class Code_attribute extends Attribute { public class InvalidIndex extends AttributeException { + private static final long serialVersionUID = -8904527774589382802L; InvalidIndex(int index) { this.index = index; } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java index f6a0bda55b0..b9acd9640d9 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java @@ -38,6 +38,7 @@ import java.io.IOException; public class ConstantPool { public class InvalidIndex extends ConstantPoolException { + private static final long serialVersionUID = -4350294289300939730L; InvalidIndex(int index) { super(index); } @@ -50,6 +51,7 @@ public class ConstantPool { } public class UnexpectedEntry extends ConstantPoolException { + private static final long serialVersionUID = 6986335935377933211L; UnexpectedEntry(int index, int expected_tag, int found_tag) { super(index); this.expected_tag = expected_tag; @@ -67,6 +69,7 @@ public class ConstantPool { } public class InvalidEntry extends ConstantPoolException { + private static final long serialVersionUID = 1000087545585204447L; InvalidEntry(int index, int tag) { super(index); this.tag = tag; @@ -82,6 +85,7 @@ public class ConstantPool { } public class EntryNotFound extends ConstantPoolException { + private static final long serialVersionUID = 2885537606468581850L; EntryNotFound(Object value) { super(-1); this.value = value; diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPoolException.java b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPoolException.java index 03a89b9d080..31d3473e6ca 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPoolException.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPoolException.java @@ -33,6 +33,7 @@ package com.sun.tools.classfile; * deletion without notice. */ public class ConstantPoolException extends Exception { + private static final long serialVersionUID = -2324397349644754565L; ConstantPoolException(int index) { this.index = index; } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Descriptor.java b/langtools/src/share/classes/com/sun/tools/classfile/Descriptor.java index 510fe09f4a7..e446955399f 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Descriptor.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Descriptor.java @@ -38,6 +38,7 @@ import java.io.IOException; */ public class Descriptor { public class InvalidDescriptor extends DescriptorException { + private static final long serialVersionUID = 1L; InvalidDescriptor(String desc) { this.desc = desc; this.index = -1; diff --git a/langtools/src/share/classes/com/sun/tools/classfile/DescriptorException.java b/langtools/src/share/classes/com/sun/tools/classfile/DescriptorException.java index 97d0538c74c..fad9a2ff361 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/DescriptorException.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/DescriptorException.java @@ -33,4 +33,5 @@ package com.sun.tools.classfile; * deletion without notice. */ public class DescriptorException extends Exception { + private static final long serialVersionUID = 2411890273788901032L; } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java index 4f4fd93bf27..26a9b6f9736 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/StackMapTable_attribute.java @@ -37,6 +37,7 @@ import java.io.IOException; */ public class StackMapTable_attribute extends Attribute { static class InvalidStackMap extends AttributeException { + private static final long serialVersionUID = -5659038410855089780L; InvalidStackMap(String msg) { super(msg); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java index 524bd2472a3..70d487da2ba 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java @@ -493,4 +493,14 @@ public class ConfigurationImpl extends Configuration { public Comparator getMemberComparator() { return null; } + + /** + * {@inheritDoc} + */ + public Locale getLocale() { + if (root instanceof com.sun.tools.javadoc.RootDocImpl) + return ((com.sun.tools.javadoc.RootDocImpl)root).getLocale(); + else + return Locale.getDefault(); + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index 8a668cdc819..352eeb7010b 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -244,6 +244,29 @@ public class HtmlDocletWriter extends HtmlDocWriter { } } + /** + * Check whether there are any tags to be printed. + * + * @param doc the Doc object to check for tags. + * @return true if there are tags to be printed else return false. + */ + protected boolean hasTagsToPrint(Doc doc) { + if (doc instanceof MethodDoc) { + ClassDoc[] intfacs = ((MethodDoc)doc).containingClass().interfaces(); + MethodDoc overriddenMethod = ((MethodDoc)doc).overriddenMethod(); + if ((intfacs.length > 0 && + new ImplementedMethods((MethodDoc)doc, this.configuration).build().length > 0) || + overriddenMethod != null) { + return true; + } + } + TagletOutputImpl output = new TagletOutputImpl(""); + TagletWriter.genTagOuput(configuration.tagletManager, doc, + configuration.tagletManager.getCustomTags(doc), + getTagletWriterInstance(false), output); + return (output.toString().trim().isEmpty()); + } + /** * Returns a TagletWriter that knows how to write HTML. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java index 5b770658eca..3e84b00dbb6 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java @@ -164,4 +164,20 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl public void writeMemberFooter(FieldDoc member) { writer.dlEnd(); } + + /** + * Check to see if member details should be printed. If + * nocomment option set or if there is no text to be printed + * for deprecation info, inline comment, no serial tag or inline tags, + * do not print member details. + */ + public boolean shouldPrintMemberDetails(FieldDoc field) { + if (!configuration().nocomment) + if((field.inlineTags().length > 0) || + (field.tags("serial").length > 0) || (writer.hasTagsToPrint(field))) + return true; + if (!Util.isDeprecated(field)) + return true; + return false; + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 630ed3669c4..d7e7ee1696e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -119,7 +119,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { */ protected void generateIndex() { for (int i = 0; i < groupList.size(); i++) { - String groupname = (String)groupList.get(i); + String groupname = groupList.get(i); List list = groupPackageMap.get(groupname); if (list != null && list.size() > 0) { printIndexContents(list.toArray(new PackageDoc[list.size()]), diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletOutputImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletOutputImpl.java index af8532486fe..9ecb4d6d5af 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletOutputImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/TagletOutputImpl.java @@ -67,4 +67,10 @@ public class TagletOutputImpl implements TagletOutput { return output.toString(); } + /** + * Check whether the taglet output is empty. + */ + public boolean isEmpty() { + return (toString().trim().isEmpty()); + } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java index 8644af9a22f..d4cdd39b1ce 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java @@ -25,12 +25,11 @@ package com.sun.tools.doclets.formats.html.markup; -import com.sun.tools.doclets.internal.toolkit.*; - -import com.sun.javadoc.*; import java.io.*; import java.util.*; -import com.sun.tools.doclets.internal.toolkit.util.*; + +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; /** @@ -56,8 +55,9 @@ public abstract class HtmlDocWriter extends HtmlWriter { super(configuration, null, configuration.destDirName + filename, configuration.docencoding); + // use File to normalize file separators configuration.message.notice("doclet.Generating_0", - configuration.destDirName + filename); + new File(configuration.destDirName, filename)); } public HtmlDocWriter(Configuration configuration, @@ -65,10 +65,10 @@ public abstract class HtmlDocWriter extends HtmlWriter { super(configuration, configuration.destDirName + path, filename, configuration.docencoding); + // use File to normalize file separators configuration.message.notice("doclet.Generating_0", - configuration.destDirName + - ((path.length() > 0)? - path + File.separator: "") + filename); + new File(configuration.destDirName, + ((path.length() > 0)? path + File.separator: "") + filename)); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 21fb7e642b0..cdafe1be907 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -85,7 +85,7 @@ public class HtmlWriter extends PrintWriter { * Print <HTML> tag. Add a newline character at the end. */ public void html() { - println(""); + println(""); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index 11b37b34498..eb8960f4c65 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -706,6 +706,11 @@ public abstract class Configuration { new FileInputStream(new File(builderXMLPath)); } + /** + * Return the Locale for this document. + */ + public abstract Locale getLocale(); + /** * Return the comparator that will be used to sort member documentation. * To no do any sorting, return null. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java index 06fbb613365..d1de4df22dd 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/SerializedFormWriter.java @@ -152,6 +152,17 @@ public interface SerializedFormWriter { * @param member the member to write the header for. */ public void writeMemberFooter(FieldDoc member); + + /** + * Check to see if member details should be printed. If + * nocomment option set or if there is no text to be printed + * for deprecation info, inline comment, no serial tag or inline tags, + * do not print member details. + * + * @param member the member to check details for. + * @return true if details need to be printed + */ + public boolean shouldPrintMemberDetails(FieldDoc member); } /** diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java index 7f025b6ff5b..1434bc0cd0a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java @@ -402,17 +402,18 @@ public class SerializedFormBuilder extends AbstractBuilder { public void buildFieldSerializationOverview(ClassDoc classDoc) { if (classDoc.definesSerializableFields()) { FieldDoc serialPersistentField = - (FieldDoc)((Util.asList(classDoc.serializableFields()).get(0))); - String comment = serialPersistentField.commentText(); - if (comment.length() > 0) { + Util.asList(classDoc.serializableFields()).get(0); + // Check to see if there are inline comments, tags or deprecation + // information to be printed. + if (fieldWriter.shouldPrintMemberDetails(serialPersistentField)) { fieldWriter.writeHeader( configuration.getText("doclet.Serialized_Form_class")); + fieldWriter.writeMemberDeprecatedInfo(serialPersistentField); if (!configuration.nocomment) { - fieldWriter.writeMemberDeprecatedInfo(serialPersistentField); fieldWriter.writeMemberDescription(serialPersistentField); fieldWriter.writeMemberTags(serialPersistentField); - fieldWriter.writeMemberFooter(serialPersistentField); } + fieldWriter.writeMemberFooter(serialPersistentField); } } } @@ -428,6 +429,16 @@ public class SerializedFormBuilder extends AbstractBuilder { } } + /** + * Build the field deprecation information. + */ + public void buildFieldDeprecationInfo() { + if (!currentClass.definesSerializableFields()) { + FieldDoc field = (FieldDoc)currentMember; + fieldWriter.writeMemberDeprecatedInfo(field); + } + } + /** * Build the field information. */ @@ -459,7 +470,6 @@ public class SerializedFormBuilder extends AbstractBuilder { "doclet.MissingSerialTag", cd.qualifiedName(), field.name()); } - fieldWriter.writeMemberDeprecatedInfo(field); fieldWriter.writeMemberDescription(field); fieldWriter.writeMemberTags(field); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml index 2ecd8369005..8eaa2d77abc 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml @@ -1,30 +1,30 @@ - - - + + + @@ -183,8 +183,8 @@ + - @@ -193,6 +193,7 @@ + diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java index 906cc011705..c08965e5b7d 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocletAbortException.java @@ -26,6 +26,7 @@ package com.sun.tools.doclets.internal.toolkit.util; public class DocletAbortException extends RuntimeException { + private static final long serialVersionUID = -9131058909576418984L; public DocletAbortException() { } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java index 4055b914822..9f0b6417d6c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java @@ -80,47 +80,15 @@ public class MessageRetriever { this.resourcelocation = resourcelocation; } - /** - * get and format message string from resource - * - * @param key selects message from resource - */ - public String getText(String key) { - return getText(key, (String)null); - } - /** * Get and format message string from resource * * @param key selects message from resource - * @param a1 Argument, to be repalced in the message. - */ - public String getText(String key, String a1) { - return getText(key, a1, null); - } - - /** - * Get and format message string from resource - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public String getText(String key, String a1, String a2) { - return getText(key, a1, a2, null); - } - - /** - * Get and format message string from resource - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. + * @param args arguments to be replaced in the message. * @throws MissingResourceException when the key does not * exist in the properties file. */ - public String getText(String key, String a1, String a2, String a3) throws MissingResourceException { + public String getText(String key, Object... args) throws MissingResourceException { if (messageRB == null) { try { messageRB = ResourceBundle.getBundle(resourcelocation); @@ -130,7 +98,7 @@ public class MessageRetriever { } } String message = messageRB.getString(key); - return MessageFormat.format(message, a1, a2, a3); + return MessageFormat.format(message, args); } /** @@ -195,87 +163,20 @@ public class MessageRetriever { * * @param pos the position of the source * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void error(SourcePosition pos, String key) { - printError(pos, getText(key)); + public void error(SourcePosition pos, String key, Object... args) { + printError(pos, getText(key, args)); } /** * Print error message, increment error count. * * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void error(String key) { - printError(getText(key)); - } - - /** - * Print error message, increment error count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void error(SourcePosition pos, String key, String a1) { - printError(pos, getText(key, a1)); - } - - /** - * Print error message, increment error count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void error(String key, String a1) { - printError(getText(key, a1)); - } - - /** - * Print error message, increment error count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void error(SourcePosition pos, String key, String a1, String a2) { - printError(pos, getText(key, a1, a2)); - } - - /** - * Print error message, increment error count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void error(String key, String a1, String a2) { - printError(getText(key, a1, a2)); - } - - /** - * Print error message, increment error count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void error(SourcePosition pos, String key, String a1, String a2, String a3) { - printError(pos, getText(key, a1, a2, a3)); - } - - /** - * Print error message, increment error count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void error(String key, String a1, String a2, String a3) { - printError(getText(key, a1, a2, a3)); + public void error(String key, Object... args) { + printError(getText(key, args)); } /** @@ -283,87 +184,20 @@ public class MessageRetriever { * * @param pos the position of the source * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void warning(SourcePosition pos, String key) { - printWarning(pos, getText(key)); + public void warning(SourcePosition pos, String key, Object... args) { + printWarning(pos, getText(key, args)); } /** * Print warning message, increment warning count. * * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void warning(String key) { - printWarning(getText(key)); - } - - /** - * Print warning message, increment warning count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void warning(SourcePosition pos, String key, String a1) { - printWarning(pos, getText(key, a1)); - } - - /** - * Print warning message, increment warning count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void warning(String key, String a1) { - printWarning(getText(key, a1)); - } - - /** - * Print warning message, increment warning count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void warning(SourcePosition pos, String key, String a1, String a2) { - printWarning(pos, getText(key, a1, a2)); - } - - /** - * Print warning message, increment warning count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void warning(String key, String a1, String a2) { - printWarning(getText(key, a1, a2)); - } - - /** - * Print warning message, increment warning count. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void warning(SourcePosition pos, String key, String a1, String a2, String a3) { - printWarning(pos, getText(key, a1, a2, a3)); - } - - /** - * Print warning message, increment warning count. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void warning(String key, String a1, String a2, String a3) { - printWarning(getText(key, a1, a2, a3)); + public void warning(String key, Object... args) { + printWarning(getText(key, args)); } /** @@ -371,85 +205,19 @@ public class MessageRetriever { * * @param pos the position of the source * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void notice(SourcePosition pos, String key) { - printNotice(pos, getText(key)); + public void notice(SourcePosition pos, String key, Object... args) { + printNotice(pos, getText(key, args)); } /** * Print a message. * * @param key selects message from resource + * @param args arguments to be replaced in the message. */ - public void notice(String key) { - printNotice(getText(key)); - } - - /** - * Print a message. - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void notice(SourcePosition pos, String key, String a1) { - printNotice(pos, getText(key, a1)); - } - - /** - * Print a message. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - */ - public void notice(String key, String a1) { - printNotice(getText(key, a1)); - } - - /** - * Print a message. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void notice(SourcePosition pos, String key, String a1, String a2) { - printNotice(pos, getText(key, a1, a2)); - } - - /** - * Print a message. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - */ - public void notice(String key, String a1, String a2) { - printNotice(getText(key, a1, a2)); - } - - /** - * Print a message. - * - * @param pos the position of the source - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void notice(SourcePosition pos, String key, String a1, String a2, String a3) { - printNotice(pos, getText(key, a1, a2, a3)); - } - - /** - * Print a message. - * - * @param key selects message from resource - * @param a1 first argument to be replaced in the message. - * @param a2 second argument to be replaced in the message. - * @param a3 third argument to be replaced in the message. - */ - public void notice(String key, String a1, String a2, String a3) { - printNotice(getText(key, a1, a2, a3)); + public void notice(String key, Object... args) { + printNotice(getText(key, args)); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java index 67a82e8a3b3..3de2951e062 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SourceToHTMLConverter.java @@ -25,10 +25,12 @@ package com.sun.tools.doclets.internal.toolkit.util; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.javadoc.*; import java.io.*; import java.util.*; +import javax.tools.FileObject; + +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; /** * Converts Java Source Code to HTML. @@ -123,16 +125,27 @@ public class SourceToHTMLConverter { if (cd == null || outputdir == null) { return; } - File file; - SourcePosition sp = cd.position(); - if (sp == null || (file = sp.file()) == null) { - return; - } try { + SourcePosition sp = cd.position(); + if (sp == null) + return; + Reader r; + // temp hack until we can update SourcePosition API. + if (sp instanceof com.sun.tools.javadoc.SourcePositionImpl) { + FileObject fo = ((com.sun.tools.javadoc.SourcePositionImpl) sp).fileObject(); + if (fo == null) + return; + r = fo.openReader(true); + } else { + File file = sp.file(); + if (file == null) + return; + r = new FileReader(file); + } + LineNumberReader reader = new LineNumberReader(r); int lineno = 1; String line; StringBuffer output = new StringBuffer(); - LineNumberReader reader = new LineNumberReader(new FileReader(file)); try { while ((line = reader.readLine()) != null) { output.append(formatLine(line, configuration.sourcetab, lineno)); @@ -142,7 +155,7 @@ public class SourceToHTMLConverter { reader.close(); } output = addLineNumbers(output.toString()); - output.insert(0, getHeader()); + output.insert(0, getHeader(configuration)); output.append(getFooter()); writeToFile(output.toString(), outputdir, cd.name(), configuration); } catch (Exception e){ @@ -192,10 +205,11 @@ public class SourceToHTMLConverter { /** * Get the header. + * @param configuration the Doclet configuration * @return the header to the output file */ - protected static String getHeader() { - StringBuffer result = new StringBuffer("" + DocletConstants.NL); + protected static String getHeader(Configuration configuration) { + StringBuffer result = new StringBuffer("" + DocletConstants.NL); result.append("" + DocletConstants.NL); result.append("
" + DocletConstants.NL);
         return result.toString();
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java
index 9b7b668b6c0..1d5eb19c22e 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java
@@ -25,10 +25,11 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
+import java.io.*;
+import java.util.*;
+
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.*;
-import java.util.*;
-import java.io.*;
 
 /**
  * Utilities Class for Doclets.
@@ -579,7 +580,7 @@ public class Util {
      * @param docencoding Encoding to be used for this file.
      * @exception IOException Exception raised by the FileWriter is passed on
      * to next level.
-     * @exception UnSupportedEncodingException Exception raised by the
+     * @exception UnsupportedEncodingException Exception raised by the
      * OutputStreamWriter is passed on to next level.
      * @return Writer Writer for the file getting generated.
      * @see java.io.FileOutputStream
@@ -598,9 +599,7 @@ public class Util {
             fos = new FileOutputStream(filename);
         }
         if (docencoding == null) {
-            OutputStreamWriter oswriter = new OutputStreamWriter(fos);
-            docencoding = oswriter.getEncoding();
-            return oswriter;
+            return new OutputStreamWriter(fos);
         } else {
             return new OutputStreamWriter(fos, docencoding);
         }
diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java
index 6fd51b146b1..1c035fb0ab1 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java
@@ -25,16 +25,18 @@
 package com.sun.tools.javac.api;
 
 import java.util.Locale;
+import java.util.Set;
 import javax.tools.Diagnostic;
+import com.sun.tools.javac.api.DiagnosticFormatter.*;
 
 /**
- * Provides simple functionalities for javac diagnostic formatting
+ * Provides simple functionalities for javac diagnostic formatting.
  * @param  type of diagnostic handled by this formatter
  */
 public interface DiagnosticFormatter> {
 
     /**
-     * Whether the source code output for this diagnostic is to be displayed
+     * Whether the source code output for this diagnostic is to be displayed.
      *
      * @param diag diagnostic to be formatted
      * @return true if the source line this diagnostic refers to is to be displayed
@@ -42,7 +44,7 @@ public interface DiagnosticFormatter> {
     boolean displaySource(D diag);
 
     /**
-     * Format the contents of a diagnostics
+     * Format the contents of a diagnostics.
      *
      * @param diag the diagnostic to be formatted
      * @param l locale object to be used for i18n
@@ -115,4 +117,97 @@ public interface DiagnosticFormatter> {
          */
         OFFSET
     }
+
+    /**
+     * Get a list of all the enabled verbosity options.
+     * @return verbosity options
+     */
+    public Configuration getConfiguration();
+    //where
+
+    /**
+     * This interface provides functionalities for tuning the output of a
+     * diagnostic formatter in multiple ways.
+     */
+    interface Configuration {
+        /**
+         * Configure the set of diagnostic parts that should be displayed
+         * by the formatter.
+         * @param options options to set
+         */
+        public void setVisible(Set visibleParts);
+
+        /**
+         * Retrieve the set of diagnostic parts that should be displayed
+         * by the formatter.
+         * @return verbosity options
+         */
+        public Set getVisible();
+
+        //where
+        /**
+         * A given diagnostic message can be divided into sub-parts each of which
+         * might/might not be displayed by the formatter, according to the
+         * current configuration settings.
+         */
+        public enum DiagnosticPart {
+            /**
+             * Short description of the diagnostic - usually one line long.
+             */
+            SUMMARY,
+            /**
+             * Longer description that provides additional details w.r.t. the ones
+             * in the diagnostic's description.
+             */
+            DETAILS,
+            /**
+             * Source line the diagnostic refers to (if applicable).
+             */
+            SOURCE,
+            /**
+             * Subdiagnostics attached to a given multiline diagnostic.
+             */
+            SUBDIAGNOSTICS,
+            /**
+             * JLS paragraph this diagnostic might refer to (if applicable).
+             */
+            JLS;
+        }
+
+        /**
+         * Set a limit for multiline diagnostics.
+         * Note: Setting a limit has no effect if multiline diagnostics are either
+         * fully enabled or disabled.
+         *
+         * @param limit the kind of limit to be set
+         * @param value the limit value
+         */
+        public void setMultilineLimit(MultilineLimit limit, int value);
+
+        /**
+         * Get a multiline diagnostic limit.
+         *
+         * @param limit the kind of limit to be retrieved
+         * @return limit value or -1 if no limit is set
+         */
+        public int getMultilineLimit(MultilineLimit limit);
+        //where
+        /**
+         * A multiline limit control the verbosity of multiline diagnostics
+         * either by setting a maximum depth of nested multidiagnostics,
+         * or by limiting the amount of subdiagnostics attached to a given
+         * diagnostic (or both).
+         */
+        public enum MultilineLimit {
+            /**
+             * Controls the maximum depth of nested multiline diagnostics.
+             */
+            DEPTH,
+            /**
+             * Controls the maximum amount of subdiagnostics that are part of a
+             * given multiline diagnostic.
+             */
+            LENGTH;
+        }
+    }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/Messages.java b/langtools/src/share/classes/com/sun/tools/javac/api/Messages.java
index 7b67fe617cd..bc38794fe2d 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/api/Messages.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/Messages.java
@@ -44,7 +44,7 @@ public interface Messages {
     void add(String bundleName) throws MissingResourceException;
 
     /**
-     * Get a localized formatted string
+     * Get a localized formatted string.
      * @param l locale in which the text is to be localized
      * @param key locale-independent message key
      * @param args misc message arguments
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
index 2a1de89d886..cc9c8100069 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
@@ -709,12 +709,31 @@ public class Types {
         case UNDETVAR:
             if (s.tag == WILDCARD) {
                 UndetVar undetvar = (UndetVar)t;
-                undetvar.inst = glb(upperBound(s), undetvar.inst);
-                // We should check instantiated type against any of the
-                // undetvar's lower bounds.
-                for (Type t2 : undetvar.lobounds) {
-                    if (!isSubtype(t2, undetvar.inst))
-                        return false;
+                WildcardType wt = (WildcardType)s;
+                switch(wt.kind) {
+                    case UNBOUND: //similar to ? extends Object
+                    case EXTENDS: {
+                        Type bound = upperBound(s);
+                        // We should check the new upper bound against any of the
+                        // undetvar's lower bounds.
+                        for (Type t2 : undetvar.lobounds) {
+                            if (!isSubtype(t2, bound))
+                                return false;
+                        }
+                        undetvar.hibounds = undetvar.hibounds.prepend(bound);
+                        break;
+                    }
+                    case SUPER: {
+                        Type bound = lowerBound(s);
+                        // We should check the new lower bound against any of the
+                        // undetvar's lower bounds.
+                        for (Type t2 : undetvar.hibounds) {
+                            if (!isSubtype(bound, t2))
+                                return false;
+                        }
+                        undetvar.lobounds = undetvar.lobounds.prepend(bound);
+                        break;
+                    }
                 }
                 return true;
             } else {
@@ -930,12 +949,16 @@ public class Types {
                 }
 
                 if (t.isCompound()) {
+                    Warner oldWarner = warnStack.head;
+                    warnStack.head = Warner.noWarnings;
                     if (!visit(supertype(t), s))
                         return false;
                     for (Type intf : interfaces(t)) {
                         if (!visit(intf, s))
                             return false;
                     }
+                    if (warnStack.head.unchecked == true)
+                        oldWarner.warnUnchecked();
                     return true;
                 }
 
@@ -2108,9 +2131,6 @@ public class Types {
                                   List to) {
         if (tvars.isEmpty())
             return tvars;
-        if (tvars.tail.isEmpty())
-            // fast common case
-            return List.of(substBound((TypeVar)tvars.head, from, to));
         ListBuffer newBoundsBuf = lb();
         boolean changed = false;
         // calculate new bounds
@@ -2150,8 +2170,14 @@ public class Types {
         Type bound1 = subst(t.bound, from, to);
         if (bound1 == t.bound)
             return t;
-        else
-            return new TypeVar(t.tsym, bound1, syms.botType);
+        else {
+            // create new type variable without bounds
+            TypeVar tv = new TypeVar(t.tsym, null, syms.botType);
+            // the new bound should use the new type variable in place
+            // of the old
+            tv.bound = subst(bound1, List.of(t), List.of(tv));
+            return tv;
+        }
     }
     // 
 
@@ -2825,6 +2851,16 @@ public class Types {
     // 
 
     // 
+    public Type glb(List ts) {
+        Type t1 = ts.head;
+        for (Type t2 : ts.tail) {
+            if (t1.isErroneous())
+                return t1;
+            t1 = glb(t1, t2);
+        }
+        return t1;
+    }
+    //where
     public Type glb(Type t, Type s) {
         if (s == null)
             return t;
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
index cfd47e6fb4a..9e0b2582b91 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
@@ -154,33 +154,15 @@ public class Infer {
                 that.inst = syms.objectType;
             else if (that.hibounds.tail.isEmpty())
                 that.inst = that.hibounds.head;
-            else {
-                for (List bs = that.hibounds;
-                     bs.nonEmpty() && that.inst == null;
-                     bs = bs.tail) {
-                    // System.out.println("hibounds = " + that.hibounds);//DEBUG
-                    if (isSubClass(bs.head, that.hibounds))
-                        that.inst = types.fromUnknownFun.apply(bs.head);
-                }
-                if (that.inst == null) {
-                    int classCount = 0, interfaceCount = 0;
-                    for (Type t : that.hibounds) {
-                        if (t.tag == CLASS) {
-                            if (t.isInterface())
-                                interfaceCount++;
-                            else
-                                classCount++;
-                        }
-                    }
-                    if ((that.hibounds.size() == classCount + interfaceCount) && classCount == 1)
-                        that.inst = types.makeCompoundType(that.hibounds);
-                }
-                if (that.inst == null || !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
-                    throw ambiguousNoInstanceException
-                        .setMessage("no.unique.maximal.instance.exists",
-                                    that.qtype, that.hibounds);
-            }
+            else
+                that.inst = types.glb(that.hibounds);
         }
+        if (that.inst == null ||
+            that.inst.isErroneous() ||
+            !types.isSubtypeUnchecked(that.inst, that.hibounds, warn))
+            throw ambiguousNoInstanceException
+                .setMessage("no.unique.maximal.instance.exists",
+                            that.qtype, that.hibounds);
     }
     //where
         private boolean isSubClass(Type t, final List ts) {
diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 3f4911bb06c..8130dfc183e 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -371,6 +371,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
                         context.get(DiagnosticListener.class) != null;
         devVerbose    = options.get("dev") != null;
         processPcks   = options.get("process.packages") != null;
+        werror        = options.get("-Werror")        != null;
 
         verboseCompilePolicy = options.get("verboseCompilePolicy") != null;
 
@@ -434,6 +435,10 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
      */
     protected boolean processPcks;
 
+    /** Switch: treat warnings as errors
+     */
+    protected boolean werror;
+
     /** Switch: is annotation processing requested explitly via
      * CompilationTask.setProcessors?
      */
@@ -471,6 +476,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
         private int value;
     };
     protected class CompileStates extends HashMap,CompileState> {
+        private static final long serialVersionUID = 1812267524140424433L;
         boolean isDone(Env env, CompileState cs) {
             CompileState ecs = get(env);
             return ecs != null && ecs.isDone(cs);
@@ -489,7 +495,11 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
     public int errorCount() {
         if (delegateCompiler != null && delegateCompiler != this)
             return delegateCompiler.errorCount();
-        else
+        else {
+            if (werror && log.nerrors == 0 && log.nwarnings > 0) {
+                log.error("warnings.and.werror");
+            }
+        }
             return log.nerrors;
     }
 
diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java
index e8165090b4e..19f9f6e0e99 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java
@@ -338,13 +338,13 @@ public class Main {
                 return EXIT_CMDERR;
             }
 
-            List filenames;
+            List files;
             try {
-                filenames = processArgs(CommandLine.parse(args));
-                if (filenames == null) {
+                files = processArgs(CommandLine.parse(args));
+                if (files == null) {
                     // null signals an error in options, abort
                     return EXIT_CMDERR;
-                } else if (filenames.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
+                } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
                     // it is allowed to compile nothing if just asking for help or version info
                     if (options.get("-help") != null
                         || options.get("-X") != null
@@ -380,12 +380,14 @@ public class Main {
             comp = JavaCompiler.instance(context);
             if (comp == null) return EXIT_SYSERR;
 
-            if (!filenames.isEmpty()) {
+            Log log = Log.instance(context);
+
+            if (!files.isEmpty()) {
                 // add filenames to fileObjects
                 comp = JavaCompiler.instance(context);
                 List otherFiles = List.nil();
                 JavacFileManager dfm = (JavacFileManager)fileManager;
-                for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(filenames))
+                for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
                     otherFiles = otherFiles.prepend(fo);
                 for (JavaFileObject fo : otherFiles)
                     fileObjects = fileObjects.prepend(fo);
@@ -394,8 +396,17 @@ public class Main {
                          classnames.toList(),
                          processors);
 
-            if (comp.errorCount() != 0 ||
-                options.get("-Werror") != null && comp.warningCount() != 0)
+            if (log.expectDiagKeys != null) {
+                if (log.expectDiagKeys.size() == 0) {
+                    Log.printLines(log.noticeWriter, "all expected diagnostics found");
+                    return EXIT_OK;
+                } else {
+                    Log.printLines(log.noticeWriter, "expected diagnostic keys not found: " + log.expectDiagKeys);
+                    return EXIT_ERROR;
+                }
+            }
+
+            if (comp.errorCount() != 0)
                 return EXIT_ERROR;
         } catch (IOException ex) {
             ioMessage(ex);
diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java b/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java
index 3ffbccdbc35..61a2d1ba98e 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java
@@ -40,6 +40,7 @@ public enum OptionName {
     G_CUSTOM("-g:"),
     XLINT("-Xlint"),
     XLINT_CUSTOM("-Xlint:"),
+    DIAGS("-XDdiags="),
     NOWARN("-nowarn"),
     VERBOSE("-verbose"),
     DEPRECATION("-deprecation"),
diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java b/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java
index 7a2f2c72a06..f69f0c1377e 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java
@@ -145,6 +145,7 @@ public class RecognizedOptions {
         TARGET,
         VERSION,
         FULLVERSION,
+        DIAGS,
         HELP,
         A,
         X,
@@ -372,6 +373,21 @@ public class RecognizedOptions {
                 return super.process(options, option);
             }
         },
+        new HiddenOption(DIAGS) {
+            @Override
+            public boolean process(Options options, String option) {
+                Option xd = getOptions(helper, EnumSet.of(XD))[0];
+                option = option.substring(option.indexOf('=') + 1);
+                String diagsOption = option.contains("%") ?
+                    "-XDdiagsFormat=" :
+                    "-XDdiags=";
+                diagsOption += option;
+                if (xd.matches(diagsOption))
+                    return xd.process(options, diagsOption);
+                else
+                    return false;
+            }
+        },
         new Option(HELP,                                        "opt.help") {
             @Override
             public boolean process(Options options, String option) {
@@ -449,7 +465,7 @@ public class RecognizedOptions {
         },
 
         // treat warnings as errors
-        new HiddenOption(WERROR),
+        new Option(WERROR,                                      "opt.Werror"),
 
         // use complex inference from context in the position of a method call argument
         new HiddenOption(COMPLEXINFERENCE),
diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
index ef48f23984f..a1bd2da6e55 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -863,13 +863,13 @@ public class JavacParser implements Parser {
                         accept(GT);
                         t = F.at(pos1).TypeApply(t, args.toList());
                         checkGenerics();
-                        t = bracketsOpt(toP(t));
                         while (S.token() == DOT) {
                             S.nextToken();
                             mode = TYPE;
                             t = toP(F.at(S.pos()).Select(t, ident()));
                             t = typeArgumentsOpt(t);
                         }
+                        t = bracketsOpt(toP(t));
                     } else if ((mode & EXPR) != 0) {
                         mode = EXPR;
                         t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java b/langtools/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
index a9433585fcb..2c266971c45 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
@@ -125,7 +125,7 @@ public class PrintingProcessor extends AbstractProcessor {
                     return this;
 
                 defaultAction(e, true);
-                printFormalTypeParameters(e);
+                printFormalTypeParameters(e, true);
 
                 switch(kind) {
                     case CONSTRUCTOR:
@@ -207,7 +207,7 @@ public class PrintingProcessor extends AbstractProcessor {
                 writer.print(" ");
                 writer.print(e.getSimpleName());
 
-                printFormalTypeParameters(e);
+                printFormalTypeParameters(e, false);
 
                 // Print superclass information if informative
                 if (kind == CLASS) {
@@ -364,16 +364,9 @@ public class PrintingProcessor extends AbstractProcessor {
             }
         }
 
-        private void printFormalTypeParameters(ExecutableElement executable) {
-            printFormalTypeParameters(executable.getTypeParameters(), true);
-        }
-
-        private void printFormalTypeParameters(TypeElement type) {
-            printFormalTypeParameters(type.getTypeParameters(), false);
-        }
-
-        private void printFormalTypeParameters(List typeParams,
+        private void printFormalTypeParameters(Parameterizable e,
                                                boolean pad) {
+            List typeParams = e.getTypeParameters();
             if (typeParams.size() > 0) {
                 writer.print("<");
 
diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
index 0ea7064f462..d892db06077 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -346,6 +346,9 @@ compiler.err.pkg.annotations.sb.in.package-info.java=\
 compiler.err.pkg.clashes.with.class.of.same.name=\
     package {0} clashes with class of same name
 
+compiler.err.warnings.and.werror=\
+    warnings found and -Werror specified
+
 # Errors related to annotation processing
 
 compiler.err.proc.cant.access=\
@@ -904,16 +907,16 @@ compiler.err.not.within.bounds.explain=\
 
 compiler.err.prob.found.req=\
 {0}\n\
-found   : {1}\n\
-required: {2}
+required: {2}\n\
+found:    {1}
 compiler.warn.prob.found.req=\
 {0}\n\
-found   : {1}\n\
-required: {2}
+required: {2}\n\
+found:    {1}
 compiler.err.prob.found.req.1=\
 {0} {3}\n\
-found   : {1}\n\
-required: {2}
+required: {2}\n\
+found:    {1}
 
 ## The following are all possible strings for the first argument ({0}) of the
 ## above strings.
@@ -948,8 +951,8 @@ compiler.misc.assignment.to.extends-bound=\
 
 compiler.err.type.found.req=\
 unexpected type\n\
-found   : {0}\n\
-required: {1}
+required: {1}\n\
+found:    {0}
 
 ## The following are all possible strings for the first argument ({0}) of the
 ## above string.
@@ -1000,7 +1003,7 @@ compiler.err.non-static.cant.be.ref=\
 compiler.err.unexpected.type=\
 unexpected type\n\
 required: {0}\n\
-found   : {1}
+found:    {1}
 
 ## The first argument {0} is a "kindname" (e.g. 'constructor', 'field', etc.)
 ## The second argument {1} is the non-resolved symbol
@@ -1023,17 +1026,17 @@ compiler.err.cant.resolve.args.params=\
 ## The sixth argument {5} is the location type
 compiler.err.cant.resolve.location=\
     cannot find symbol\n\
-    symbol  : {0} {1}\n\
+    symbol:   {0} {1}\n\
     location: {4} {5}
 
 compiler.err.cant.resolve.location.args=\
     cannot find symbol\n\
-    symbol  : {0} {1}({3})\n\
+    symbol:   {0} {1}({3})\n\
     location: {4} {5}
 
 compiler.err.cant.resolve.location.args.params=\
     cannot find symbol\n\
-    symbol  : {0} <{2}>{1}({3})\n\
+    symbol:   {0} <{2}>{1}({3})\n\
     location: {4} {5}
 
 ## The following are all possible string for "kindname".
diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties
index e0d6d45aa62..4ef8a779c57 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties
@@ -69,6 +69,8 @@ javac.opt.target=\
     Generate class files for specific VM version
 javac.opt.source=\
     Provide source compatibility with specified release
+javac.opt.Werror=\
+    Terminate compilation if warnings occur
 javac.opt.A=\
     Options to pass to annotation processors
 javac.opt.implicit=\
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
index e930c75d67b..179e284a22c 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
@@ -24,16 +24,23 @@
  */
 package com.sun.tools.javac.util;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.api.DiagnosticFormatter;
-import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.DiagnosticPart;
+import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.MultilineLimit;
 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind;
+import com.sun.tools.javac.api.Formattable;
 import com.sun.tools.javac.file.JavacFileManager;
+
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
-import static com.sun.tools.javac.util.LayoutCharacters.*;
 
 /**
  * This abstract class provides a basic implementation of the functionalities that should be provided
@@ -50,35 +57,19 @@ import static com.sun.tools.javac.util.LayoutCharacters.*;
 public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter {
 
     /**
-     * JavacMessages object used by this formatter for i18n
+     * JavacMessages object used by this formatter for i18n.
      */
     protected JavacMessages messages;
-    protected boolean showSource;
+    private SimpleConfiguration config;
+    protected int depth = 0;
 
     /**
-     * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object
+     * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object.
      * @param messages
      */
-    protected AbstractDiagnosticFormatter(JavacMessages messages, Options options, boolean showSource) {
+    protected AbstractDiagnosticFormatter(JavacMessages messages, SimpleConfiguration config) {
         this.messages = messages;
-        this.showSource = options.get("showSource") == null ? showSource :
-                          options.get("showSource").equals("true");
-    }
-
-    protected AbstractDiagnosticFormatter(JavacMessages messages, boolean showSource) {
-        this.messages = messages;
-        this.showSource = showSource;
-    }
-
-    public String formatMessage(JCDiagnostic d, Locale l) {
-        //this code should rely on the locale settings but it's not! See RFE 6443132
-        StringBuilder buf = new StringBuilder();
-        Collection args = formatArguments(d, l);
-        buf.append(localize(l, d.getCode(), args.toArray()));
-        if (d.isMultiline()) {
-            buf.append(formatSubdiagnostics(d, l));
-        }
-        return buf.toString();
+        this.config = config;
     }
 
     public String formatKind(JCDiagnostic d, Locale l) {
@@ -96,8 +87,8 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
         assert (d.getPosition() != Position.NOPOS);
         return String.valueOf(getPosition(d, pk));
     }
-    //WHERE
-    public long getPosition(JCDiagnostic d, PositionKind pk) {
+    //where
+    private long getPosition(JCDiagnostic d, PositionKind pk) {
         switch (pk) {
             case START: return d.getIntStartPosition();
             case END: return d.getIntEndPosition();
@@ -138,8 +129,17 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
      * @return string representation of the diagnostic argument
      */
     protected String formatArgument(JCDiagnostic d, Object arg, Locale l) {
-        if (arg instanceof JCDiagnostic)
-            return format((JCDiagnostic)arg, l);
+        if (arg instanceof JCDiagnostic) {
+            String s = null;
+            depth++;
+            try {
+                s = formatMessage((JCDiagnostic)arg, l);
+            }
+            finally {
+                depth--;
+            }
+            return s;
+        }
         else if (arg instanceof Iterable) {
             return formatIterable(d, (Iterable)arg, l);
         }
@@ -171,45 +171,74 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
     }
 
     /**
-     * Format all the subdiagnostics attached to a given diagnostic
+     * Format all the subdiagnostics attached to a given diagnostic.
      *
      * @param d diagnostic whose subdiagnostics are to be formatted
      * @param l locale object to be used for i18n
+     * @return list of all string representations of the subdiagnostics
+     */
+    protected List formatSubdiagnostics(JCDiagnostic d, Locale l) {
+        List subdiagnostics = List.nil();
+        int maxDepth = config.getMultilineLimit(MultilineLimit.DEPTH);
+        if (maxDepth == -1 || depth < maxDepth) {
+            depth++;
+            try {
+                int maxCount = config.getMultilineLimit(MultilineLimit.LENGTH);
+                int count = 0;
+                for (JCDiagnostic d2 : d.getSubdiagnostics()) {
+                    if (maxCount == -1 || count < maxCount) {
+                        subdiagnostics = subdiagnostics.append(formatSubdiagnostic(d, d2, l));
+                        count++;
+                    }
+                    else
+                        break;
+                }
+            }
+            finally {
+                depth--;
+            }
+        }
+        return subdiagnostics;
+    }
+
+    /**
+     * Format a subdiagnostics attached to a given diagnostic.
+     *
+     * @param parent multiline diagnostic whose subdiagnostics is to be formatted
+     * @param sub subdiagnostic to be formatted
+     * @param l locale object to be used for i18n
      * @return string representation of the subdiagnostics
      */
-    protected String formatSubdiagnostics(JCDiagnostic d, Locale l) {
-        StringBuilder buf = new StringBuilder();
-        for (JCDiagnostic d2 : d.getSubdiagnostics()) {
-            buf.append('\n');
-            String subdiagMsg = format(d2, l);
-            buf.append(indent(subdiagMsg, DiagInc));
-        }
-        return buf.toString();
+    protected String formatSubdiagnostic(JCDiagnostic parent, JCDiagnostic sub, Locale l) {
+        return formatMessage(sub, l);
     }
 
     /** Format the faulty source code line and point to the error.
      *  @param d The diagnostic for which the error line should be printed
      */
-    protected String formatSourceLine(JCDiagnostic d) {
+    protected String formatSourceLine(JCDiagnostic d, int nSpaces) {
         StringBuilder buf = new StringBuilder();
         DiagnosticSource source = d.getDiagnosticSource();
         int pos = d.getIntPosition();
-        if (d.getIntPosition() != Position.NOPOS) {
-            String line = (source == null ? null : source.getLine(pos));
-            if (line == null)
-                return "";
-            buf.append(line+"\n");
-            int col = source.getColumnNumber(pos, false);
+        if (d.getIntPosition() == Position.NOPOS)
+            throw new AssertionError();
+        String line = (source == null ? null : source.getLine(pos));
+        if (line == null)
+            return "";
+        buf.append(indent(line, nSpaces));
+        int col = source.getColumnNumber(pos, false);
+        if (config.isCaretEnabled()) {
+            buf.append("\n");
             for (int i = 0; i < col - 1; i++)  {
                 buf.append((line.charAt(i) == '\t') ? "\t" : " ");
             }
-            buf.append("^");
-         }
-         return buf.toString();
+            buf.append(indent("^", nSpaces));
+        }
+        return buf.toString();
     }
 
     /**
-     * Converts a String into a locale-dependent representation accordingly to a given locale
+     * Converts a String into a locale-dependent representation accordingly to a given locale.
      *
      * @param l locale object to be used for i18n
      * @param key locale-independent key used for looking up in a resource file
@@ -221,7 +250,9 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
     }
 
     public boolean displaySource(JCDiagnostic d) {
-        return showSource && d.getType() != FRAGMENT;
+        return config.getVisible().contains(DiagnosticPart.SOURCE) &&
+                d.getType() != FRAGMENT &&
+                d.getIntPosition() != Position.NOPOS;
     }
 
     /**
@@ -245,7 +276,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
 
     /**
      * Indent a string by prepending a given amount of empty spaces to each line
-     * of the string
+     * of the string.
      *
      * @param s the string to be indented
      * @param nSpaces the amount of spaces that should be prepended to each line
@@ -263,4 +294,114 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
         }
         return buf.toString();
     }
+
+    public SimpleConfiguration getConfiguration() {
+        return config;
+    }
+
+    static public class SimpleConfiguration implements Configuration {
+
+        protected Map multilineLimits;
+        protected EnumSet visibleParts;
+        protected boolean caretEnabled;
+
+        public SimpleConfiguration(Set parts) {
+            multilineLimits = new HashMap();
+            setVisible(parts);
+            setMultilineLimit(MultilineLimit.DEPTH, -1);
+            setMultilineLimit(MultilineLimit.LENGTH, -1);
+            setCaretEnabled(true);
+        }
+
+        @SuppressWarnings("fallthrough")
+        public SimpleConfiguration(Options options, Set parts) {
+            this(parts);
+            String showSource = null;
+            if ((showSource = options.get("showSource")) != null) {
+                if (showSource.equals("true"))
+                    visibleParts.add(DiagnosticPart.SOURCE);
+                else if (showSource.equals("false"))
+                    visibleParts.remove(DiagnosticPart.SOURCE);
+            }
+            String diagOpts = options.get("diags");
+            if (diagOpts != null) {//override -XDshowSource
+                Collection args = Arrays.asList(diagOpts.split(","));
+                if (args.contains("short")) {
+                    visibleParts.remove(DiagnosticPart.DETAILS);
+                    visibleParts.remove(DiagnosticPart.SUBDIAGNOSTICS);
+                }
+                if (args.contains("source"))
+                    visibleParts.add(DiagnosticPart.SOURCE);
+                if (args.contains("-source"))
+                    visibleParts.remove(DiagnosticPart.SOURCE);
+            }
+            String multiPolicy = null;
+            if ((multiPolicy = options.get("multilinePolicy")) != null) {
+                if (multiPolicy.equals("disabled"))
+                    visibleParts.remove(DiagnosticPart.SUBDIAGNOSTICS);
+                else if (multiPolicy.startsWith("limit:")) {
+                    String limitString = multiPolicy.substring("limit:".length());
+                    String[] limits = limitString.split(":");
+                    try {
+                        switch (limits.length) {
+                            case 2: {
+                                if (!limits[1].equals("*"))
+                                    setMultilineLimit(MultilineLimit.DEPTH, Integer.parseInt(limits[1]));
+                            }
+                            case 1: {
+                                if (!limits[0].equals("*"))
+                                    setMultilineLimit(MultilineLimit.LENGTH, Integer.parseInt(limits[0]));
+                            }
+                        }
+                    }
+                    catch(NumberFormatException ex) {
+                        setMultilineLimit(MultilineLimit.DEPTH, -1);
+                        setMultilineLimit(MultilineLimit.LENGTH, -1);
+                    }
+                }
+            }
+            String showCaret = null;
+            if (((showCaret = options.get("showCaret")) != null) &&
+                showCaret.equals("false"))
+                    setCaretEnabled(false);
+            else
+                setCaretEnabled(true);
+        }
+
+        public int getMultilineLimit(MultilineLimit limit) {
+            return multilineLimits.get(limit);
+        }
+
+        public EnumSet getVisible() {
+            return EnumSet.copyOf(visibleParts);
+        }
+
+        public void setMultilineLimit(MultilineLimit limit, int value) {
+            multilineLimits.put(limit, value < -1 ? -1 : value);
+        }
+
+
+        public void setVisible(Set diagParts) {
+            visibleParts = EnumSet.copyOf(diagParts);
+        }
+
+        /**
+         * Shows a '^' sign under the source line displayed by the formatter
+         * (if applicable).
+         *
+         * @param caretEnabled if true enables caret
+         */
+        public void setCaretEnabled(boolean caretEnabled) {
+            this.caretEnabled = caretEnabled;
+        }
+
+        /**
+         * Tells whether the caret display is active or not.
+         *
+         * @param caretEnabled if true the caret is enabled
+         */
+        public boolean isCaretEnabled() {
+            return caretEnabled;
+        }
+    }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
index 345e2628c96..e3cc45c06e4 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java
@@ -25,13 +25,20 @@
 
 package com.sun.tools.javac.util;
 
+import java.util.Collection;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.regex.Matcher;
 import javax.tools.JavaFileObject;
 
-import static com.sun.tools.javac.util.BasicDiagnosticFormatter.BasicFormatKind.*;
+import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
+import com.sun.tools.javac.util.BasicDiagnosticFormatter.BasicConfiguration;
+
 import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
+import static com.sun.tools.javac.util.BasicDiagnosticFormatter.BasicConfiguration.*;
+import static com.sun.tools.javac.util.LayoutCharacters.*;
 
 /**
  * A basic formatter for diagnostic messages.
@@ -53,7 +60,7 @@ import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
  */
 public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
 
-    protected Map availableFormats;
+    protected int currentIndentation = 0;
 
     /**
      * Create a basic formatter based on the supplied options.
@@ -61,21 +68,9 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
      * @param opts list of command-line options
      * @param msgs JavacMessages object used for i18n
      */
-    BasicDiagnosticFormatter(Options opts, JavacMessages msgs) {
-        super(msgs, opts, true);
-        initAvailableFormats();
-        String fmt = opts.get("diags");
-        if (fmt != null) {
-            String[] formats = fmt.split("\\|");
-            switch (formats.length) {
-                case 3:
-                    availableFormats.put(DEFAULT_CLASS_FORMAT, formats[2]);
-                case 2:
-                    availableFormats.put(DEFAULT_NO_POS_FORMAT, formats[1]);
-                default:
-                    availableFormats.put(DEFAULT_POS_FORMAT, formats[0]);
-            }
-        }
+    @SuppressWarnings("fallthrough")
+    public BasicDiagnosticFormatter(Options options, JavacMessages msgs) {
+        super(msgs, new BasicConfiguration(options));
     }
 
     /**
@@ -84,15 +79,7 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
      * @param msgs JavacMessages object used for i18n
      */
     public BasicDiagnosticFormatter(JavacMessages msgs) {
-        super(msgs, true);
-        initAvailableFormats();
-    }
-
-    public void initAvailableFormats() {
-        availableFormats = new HashMap();
-        availableFormats.put(DEFAULT_POS_FORMAT, "%f:%l:%_%t%m");
-        availableFormats.put(DEFAULT_NO_POS_FORMAT, "%p%m");
-        availableFormats.put(DEFAULT_CLASS_FORMAT, "%f:%_%t%m");
+        super(msgs, new BasicConfiguration());
     }
 
     public String format(JCDiagnostic d, Locale l) {
@@ -109,10 +96,55 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
             }
             buf.append(meta ? formatMeta(c, d, l) : String.valueOf(c));
         }
-        if (displaySource(d)) {
-            buf.append("\n" + formatSourceLine(d));
+        if (depth == 0)
+            return addSourceLineIfNeeded(d, buf.toString());
+        else
+            return buf.toString();
+    }
+
+    public String formatMessage(JCDiagnostic d, Locale l) {
+        int prevIndentation = currentIndentation;
+        try {
+            StringBuilder buf = new StringBuilder();
+            Collection args = formatArguments(d, l);
+            String msg = localize(l, d.getCode(), args.toArray());
+            String[] lines = msg.split("\n");
+            if (getConfiguration().getVisible().contains(DiagnosticPart.SUMMARY)) {
+                currentIndentation += getConfiguration().getIndentation(DiagnosticPart.SUMMARY);
+                buf.append(indent(lines[0], currentIndentation)); //summary
+            }
+            if (lines.length > 1 && getConfiguration().getVisible().contains(DiagnosticPart.DETAILS)) {
+                currentIndentation += getConfiguration().getIndentation(DiagnosticPart.DETAILS);
+                for (int i = 1;i < lines.length; i++) {
+                    buf.append("\n" + indent(lines[i], currentIndentation));
+                }
+            }
+            if (d.isMultiline() && getConfiguration().getVisible().contains(DiagnosticPart.SUBDIAGNOSTICS)) {
+                currentIndentation += getConfiguration().getIndentation(DiagnosticPart.SUBDIAGNOSTICS);
+                for (String sub : formatSubdiagnostics(d, l)) {
+                    buf.append("\n" + sub);
+                }
+            }
+            return buf.toString();
+        }
+        finally {
+            currentIndentation = prevIndentation;
+        }
+    }
+
+    protected String addSourceLineIfNeeded(JCDiagnostic d, String msg) {
+        if (!displaySource(d))
+            return msg;
+        else {
+            BasicConfiguration conf = getConfiguration();
+            int indentSource = conf.getIndentation(DiagnosticPart.SOURCE);
+            String sourceLine = "\n" + formatSourceLine(d, indentSource);
+            boolean singleLine = msg.indexOf("\n") == -1;
+            if (singleLine || getConfiguration().getSourcePosition() == SourcePosition.BOTTOM)
+                return msg + sourceLine;
+            else
+                return msg.replaceFirst("\n", Matcher.quoteReplacement(sourceLine) + "\n");
         }
-        return buf.toString();
     }
 
     protected String formatMeta(char c, JCDiagnostic d, Locale l) {
@@ -163,34 +195,199 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
 
     private String selectFormat(JCDiagnostic d) {
         DiagnosticSource source = d.getDiagnosticSource();
-        String format = availableFormats.get(DEFAULT_NO_POS_FORMAT);
+        String format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT);
         if (source != null) {
             if (d.getIntPosition() != Position.NOPOS) {
-                format = availableFormats.get(DEFAULT_POS_FORMAT);
+                format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_POS_FORMAT);
             } else if (source.getFile() != null &&
                        source.getFile().getKind() == JavaFileObject.Kind.CLASS) {
-                format = availableFormats.get(DEFAULT_CLASS_FORMAT);
+                format = getConfiguration().getFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT);
             }
         }
         return format;
     }
 
-    /**
-     * This enum contains all the kinds of formatting patterns supported
-     * by a basic diagnostic formatter.
-     */
-    public enum BasicFormatKind {
+    @Override
+    public BasicConfiguration getConfiguration() {
+        return (BasicConfiguration)super.getConfiguration();
+    }
+
+    static public class BasicConfiguration extends SimpleConfiguration {
+
+        protected Map indentationLevels;
+        protected Map availableFormats;
+        protected SourcePosition sourcePosition;
+
+        @SuppressWarnings("fallthrough")
+        public BasicConfiguration(Options options) {
+            super(options, EnumSet.of(DiagnosticPart.SUMMARY,
+                            DiagnosticPart.DETAILS,
+                            DiagnosticPart.SUBDIAGNOSTICS,
+                            DiagnosticPart.SOURCE));
+            initFormat();
+            initIndentation();
+            String fmt = options.get("diagsFormat");
+            if (fmt != null) {
+                String[] formats = fmt.split("\\|");
+                switch (formats.length) {
+                    case 3:
+                        setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, formats[2]);
+                    case 2:
+                        setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, formats[1]);
+                    default:
+                        setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, formats[0]);
+                }
+            }
+            String sourcePosition = null;
+            if ((((sourcePosition = options.get("sourcePosition")) != null)) &&
+                    sourcePosition.equals("bottom"))
+                    setSourcePosition(SourcePosition.BOTTOM);
+            else
+                setSourcePosition(SourcePosition.AFTER_SUMMARY);
+            String indent = options.get("diagsIndentation");
+            if (indent != null) {
+                String[] levels = indent.split("\\|");
+                try {
+                    switch (levels.length) {
+                        case 5:
+                            setIndentation(DiagnosticPart.JLS,
+                                    Integer.parseInt(levels[4]));
+                        case 4:
+                            setIndentation(DiagnosticPart.SUBDIAGNOSTICS,
+                                    Integer.parseInt(levels[3]));
+                        case 3:
+                            setIndentation(DiagnosticPart.SOURCE,
+                                    Integer.parseInt(levels[2]));
+                        case 2:
+                            setIndentation(DiagnosticPart.DETAILS,
+                                    Integer.parseInt(levels[1]));
+                        default:
+                            setIndentation(DiagnosticPart.SUMMARY,
+                                    Integer.parseInt(levels[0]));
+                    }
+                }
+                catch (NumberFormatException ex) {
+                    initIndentation();
+                }
+            }
+        }
+
+        public BasicConfiguration() {
+            super(EnumSet.of(DiagnosticPart.SUMMARY,
+                  DiagnosticPart.DETAILS,
+                  DiagnosticPart.SUBDIAGNOSTICS,
+                  DiagnosticPart.SOURCE));
+            initFormat();
+            initIndentation();
+        }
+        //where
+        private void initFormat() {
+            availableFormats = new HashMap();
+            setFormat(BasicFormatKind.DEFAULT_POS_FORMAT, "%f:%l:%_%t%m");
+            setFormat(BasicFormatKind.DEFAULT_NO_POS_FORMAT, "%p%m");
+            setFormat(BasicFormatKind.DEFAULT_CLASS_FORMAT, "%f:%_%t%m");
+        }
+        //where
+        private void initIndentation() {
+            indentationLevels = new HashMap();
+            setIndentation(DiagnosticPart.SUMMARY, 0);
+            setIndentation(DiagnosticPart.DETAILS, DetailsInc);
+            setIndentation(DiagnosticPart.SUBDIAGNOSTICS, DiagInc);
+            setIndentation(DiagnosticPart.SOURCE, 0);
+        }
+
         /**
-        * A format string to be used for diagnostics with a given position.
-        */
-        DEFAULT_POS_FORMAT,
+         * Get the amount of spaces for a given indentation kind
+         * @param diagPart the diagnostic part for which the indentation is
+         * to be retrieved
+         * @return the amount of spaces used for the specified indentation kind
+         */
+        public int getIndentation(DiagnosticPart diagPart) {
+            return indentationLevels.get(diagPart);
+        }
+
         /**
-        * A format string to be used for diagnostics without a given position.
-        */
-        DEFAULT_NO_POS_FORMAT,
+         * Set the indentation level for various element of a given diagnostic -
+         * this might lead to more readable diagnostics
+         *
+         * @param indentationKind kind of indentation to be set
+         * @param nSpaces amount of spaces for the specified diagnostic part
+         */
+        public void setIndentation(DiagnosticPart diagPart, int nSpaces) {
+            indentationLevels.put(diagPart, nSpaces);
+        }
+
         /**
-        * A format string to be used for diagnostics regarding classfiles
-        */
-        DEFAULT_CLASS_FORMAT;
+         * Set the source line positioning used by this formatter
+         *
+         * @param sourcePos a positioning value for source line
+         */
+        public void setSourcePosition(SourcePosition sourcePos) {
+            sourcePosition = sourcePos;
+        }
+
+        /**
+         * Get the source line positioning used by this formatter
+         *
+         * @return the positioning value used by this formatter
+         */
+        public SourcePosition getSourcePosition() {
+            return sourcePosition;
+        }
+        //where
+        /**
+         * A source positioning value controls the position (within a given
+         * diagnostic message) in which the source line the diagnostic refers to
+         * should be displayed (if applicable)
+         */
+        public enum SourcePosition {
+            /**
+             * Source line is displayed after the diagnostic message
+             */
+            BOTTOM,
+            /**
+             * Source line is displayed after the first line of the diagnostic
+             * message
+             */
+            AFTER_SUMMARY;
+        }
+
+        /**
+         * Set a metachar string for a specific format
+         *
+         * @param kind the format kind to be set
+         * @param s the metachar string specifying the format
+         */
+        public void setFormat(BasicFormatKind kind, String s) {
+            availableFormats.put(kind, s);
+        }
+
+        /**
+         * Get a metachar string for a specific format
+         *
+         * @param sourcePos a positioning value for source line
+         */
+        public String getFormat(BasicFormatKind kind) {
+            return availableFormats.get(kind);
+        }
+        //where
+        /**
+         * This enum contains all the kinds of formatting patterns supported
+         * by a basic diagnostic formatter.
+         */
+        public enum BasicFormatKind {
+            /**
+            * A format string to be used for diagnostics with a given position.
+            */
+            DEFAULT_POS_FORMAT,
+            /**
+            * A format string to be used for diagnostics without a given position.
+            */
+            DEFAULT_NO_POS_FORMAT,
+            /**
+            * A format string to be used for diagnostics regarding classfiles
+            */
+            DEFAULT_CLASS_FORMAT;
+        }
     }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java b/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java
index 7e332ebc0f8..b6f275f2d46 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java
@@ -39,9 +39,13 @@ public interface LayoutCharacters {
      */
     final static int TabInc = 8;
 
-    /** Diagnostic standard indentation
+    /** Standard indentation for subdiagnostics
      */
-    final static int DiagInc = 2;
+    final static int DiagInc = 4;
+
+    /** Standard indentation for additional diagnostic lines
+     */
+    final static int DetailsInc = 2;
 
     /** Tabulator character.
      */
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java
index e9d21f712d3..e22f615c3a5 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.util;
 
 import java.io.*;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -92,12 +93,17 @@ public class Log extends AbstractLog {
     protected DiagnosticListener diagListener;
 
     /**
-     * Formatter for diagnostics
+     * Formatter for diagnostics.
      */
     private DiagnosticFormatter diagFormatter;
 
     /**
-     * JavacMessages object used for localization
+     * Keys for expected diagnostics.
+     */
+    public Set expectDiagKeys;
+
+    /**
+     * JavacMessages object used for localization.
      */
     private JavacMessages messages;
 
@@ -123,9 +129,13 @@ public class Log extends AbstractLog {
         this.diagFormatter = rawDiagnostics ? new RawDiagnosticFormatter(options) :
                                               new BasicDiagnosticFormatter(options, messages);
         @SuppressWarnings("unchecked") // FIXME
-        DiagnosticListener diagListener =
+        DiagnosticListener dl =
             context.get(DiagnosticListener.class);
-        this.diagListener = diagListener;
+        this.diagListener = dl;
+
+        String ek = options.get("expectKeys");
+        if (ek != null)
+            expectDiagKeys = new HashSet(Arrays.asList(ek.split(", *")));
     }
     // where
         private int getIntOption(Options options, String optionName, int defaultValue) {
@@ -196,6 +206,18 @@ public class Log extends AbstractLog {
         return source == null ? null : source.getFile();
     }
 
+    /** Get the current diagnostic formatter.
+     */
+    public DiagnosticFormatter getDiagnosticFormatter() {
+        return diagFormatter;
+    }
+
+    /** Set the current diagnostic formatter.
+     */
+    public void setDiagnosticFormatter(DiagnosticFormatter diagFormatter) {
+        this.diagFormatter = diagFormatter;
+    }
+
     /** Flush the logs
      */
     public void flush() {
@@ -291,6 +313,9 @@ public class Log extends AbstractLog {
      * reported so far, the diagnostic may be handed off to writeDiagnostic.
      */
     public void report(JCDiagnostic diagnostic) {
+        if (expectDiagKeys != null)
+            expectDiagKeys.remove(diagnostic.getCode());
+
         switch (diagnostic.getType()) {
         case FRAGMENT:
             throw new IllegalArgumentException();
diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java
index 433779764b5..db05a732dfe 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java
@@ -24,9 +24,14 @@
  */
 package com.sun.tools.javac.util;
 
+import java.util.Collection;
+import java.util.EnumSet;
 import java.util.Locale;
 
+import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*;
 import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
+
 import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
 
 /**
@@ -35,14 +40,17 @@ import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
  * or not the source name and position are set. This formatter provides a standardized, localize-independent
  * implementation of a diagnostic formatter; as such, this formatter is best suited for testing purposes.
  */
-public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
+public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
 
     /**
      * Create a formatter based on the supplied options.
      * @param msgs
      */
-    public RawDiagnosticFormatter(Options opts) {
-        super(null, opts, false);
+    public RawDiagnosticFormatter(Options options) {
+        super(null, new SimpleConfiguration(options,
+                EnumSet.of(DiagnosticPart.SUMMARY,
+                        DiagnosticPart.DETAILS,
+                        DiagnosticPart.SUBDIAGNOSTICS)));
     }
 
     //provide common default formats
@@ -62,7 +70,7 @@ public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
             buf.append(' ');
             buf.append(formatMessage(d, null));
             if (displaySource(d))
-                buf.append("\n" + formatSourceLine(d));
+                buf.append("\n" + formatSourceLine(d, 0));
             return buf.toString();
         }
         catch (Exception e) {
@@ -71,6 +79,32 @@ public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
         }
     }
 
+    public String formatMessage(JCDiagnostic d, Locale l) {
+        StringBuilder buf = new StringBuilder();
+        Collection args = formatArguments(d, l);
+        buf.append(d.getCode());
+        String sep = ": ";
+        for (Object o : args) {
+            buf.append(sep);
+            buf.append(o);
+            sep = ", ";
+        }
+        if (d.isMultiline() && getConfiguration().getVisible().contains(DiagnosticPart.SUBDIAGNOSTICS)) {
+            List subDiags = formatSubdiagnostics(d, null);
+            if (subDiags.nonEmpty()) {
+                sep = "";
+                buf.append(",{");
+                for (String sub : formatSubdiagnostics(d, null)) {
+                    buf.append(sep);
+                    buf.append("(" + sub + ")");
+                    sep = ",";
+                }
+                buf.append('}');
+            }
+        }
+        return buf.toString();
+    }
+
     @Override
     protected String formatArgument(JCDiagnostic diag, Object arg, Locale l) {
         String s;
@@ -83,31 +117,4 @@ public class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
         else
             return s;
     }
-
-    @Override
-    protected String formatSubdiagnostics(JCDiagnostic d, Locale l) {
-        StringBuilder buf = new StringBuilder();
-        String sep = "";
-        buf.append(",{");
-        for (JCDiagnostic d2 : d.getSubdiagnostics()) {
-            buf.append(sep);
-            buf.append("(" + format(d2, l) + ")");
-            sep = ",";
-        }
-        buf.append('}');
-        return buf.toString();
-    }
-
-    @Override
-    protected String localize(Locale l, String s, Object... args) {
-        StringBuffer buf = new StringBuffer();
-        buf.append(s);
-        String sep = ": ";
-        for (Object o : args) {
-            buf.append(sep);
-            buf.append(o);
-            sep = ", ";
-        }
-        return buf.toString();
-    }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
index 18328a05396..e3f065650d1 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java
@@ -25,42 +25,48 @@
 
 package com.sun.tools.javadoc;
 
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Set;
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
 import com.sun.javadoc.*;
 
 import static com.sun.javadoc.LanguageVersion.*;
 
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Position;
-
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Kinds;
-import com.sun.tools.javac.code.TypeTags;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.ClassType;
 import com.sun.tools.javac.code.Scope;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.TypeTags;
 
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
 
 import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
 import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.TreeInfo;
 
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
+import com.sun.tools.javac.util.Position;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
 
-import java.io.File;
-import java.util.Set;
-import java.util.HashSet;
-import java.lang.reflect.Modifier;
-
 /**
  * Represents a java class and provides access to information
  * about the class, the class' comment and tags, and the
@@ -271,16 +277,41 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
      */
     public PackageDoc containingPackage() {
         PackageDocImpl p = env.getPackageDoc(tsym.packge());
-        SourcePosition po = position();
-        if (po != null && p.setDocPath == false && p.zipDocPath == null) {
-            //Set the package path if possible
-            File packageDir = po.file().getParentFile();
-            if (packageDir != null
-                && (new File(packageDir, "package.html")).exists()) {
-                p.setDocPath(packageDir.getPath());
-            } else {
-                p.setDocPath(null);
+        if (p.setDocPath == false) {
+            FileObject docPath;
+            try {
+                Location location = env.fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+                    ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+
+                docPath = env.fileManager.getFileForInput(
+                        location, p.qualifiedName(), "package.html");
+            } catch (IOException e) {
+                docPath = null;
             }
+
+            if (docPath == null) {
+                // fall back on older semantics of looking in same directory as
+                // source file for this class
+                SourcePosition po = position();
+                if (env.fileManager instanceof StandardJavaFileManager &&
+                        po instanceof SourcePositionImpl) {
+                    URI uri = ((SourcePositionImpl) po).filename.toUri();
+                    if ("file".equals(uri.getScheme())) {
+                        File f = new File(uri.getPath());
+                        File dir = f.getParentFile();
+                        if (dir != null) {
+                            File pf = new File(dir, "package.html");
+                            if (pf.exists()) {
+                                StandardJavaFileManager sfm = (StandardJavaFileManager) env.fileManager;
+                                docPath = sfm.getJavaFileObjects(pf).iterator().next();
+                            }
+                        }
+
+                    }
+                }
+            }
+
+            p.setDocPath(docPath);
         }
         return p;
     }
@@ -1251,7 +1282,7 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
      */
     public SourcePosition position() {
         if (tsym.sourcefile == null) return null;
-        return SourcePositionImpl.make(tsym.sourcefile.toString(),
+        return SourcePositionImpl.make(tsym.sourcefile,
                                        (tree==null) ? Position.NOPOS : tree.pos,
                                        lineMap);
     }
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/Comment.java b/langtools/src/share/classes/com/sun/tools/javadoc/Comment.java
index af4322e9a3c..6ce71e30600 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Comment.java
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Comment.java
@@ -74,6 +74,7 @@ class Comment {
          * the tag text.
          * 
*/ + @SuppressWarnings("fallthrough") class CommentStringParser { /** * The entry point to the comment string parser diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index d8ddd701be7..aeb39bf2758 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -25,8 +25,9 @@ package com.sun.tools.javadoc; -import java.util.*; import java.lang.reflect.Modifier; +import java.util.*; +import javax.tools.JavaFileManager; import com.sun.javadoc.*; @@ -40,7 +41,6 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Position; - /** * Holds the environment for a run of javadoc. * Holds only the information needed throughout the @@ -103,6 +103,7 @@ public class DocEnv { Check chk; Types types; + JavaFileManager fileManager; /** Allow documenting from class files? */ boolean docClasses = false; @@ -133,6 +134,7 @@ public class DocEnv { externalizableSym = reader.enterClass(names.fromString("java.io.Externalizable")); chk = Check.instance(context); types = Types.instance(context); + fileManager = context.get(JavaFileManager.class); // Default. Should normally be reset with setLocale. this.doclocale = new DocLocale(this, "", breakiterator); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java index 3d3f7c62998..636f9e85211 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java @@ -25,11 +25,13 @@ package com.sun.tools.javadoc; -import com.sun.javadoc.*; - import java.io.InputStream; import java.io.IOException; import java.text.CollationKey; +import javax.tools.FileObject; + +import com.sun.javadoc.*; + import com.sun.tools.javac.util.Position; /** @@ -43,7 +45,7 @@ import com.sun.tools.javac.util.Position; * @author Atul M Dambalkar * @author Neal Gafter (rewrite) */ -abstract class DocImpl implements Doc, Comparable { +public abstract class DocImpl implements Doc, Comparable { /** * Doc environment @@ -163,7 +165,7 @@ abstract class DocImpl implements Doc, Comparable { /** * Utility for subclasses which read HTML documentation files. */ - String readHTMLDocumentation(InputStream input, String filename) throws IOException { + String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException { int filesize = input.available(); byte[] filecontents = new byte[filesize]; input.read(filecontents, 0, filesize); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java index 698b3cfe965..34397953a58 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java @@ -83,7 +83,7 @@ public class DocletInvoker { cpString = appendPath(docletPath, cpString); URL[] urls = pathToURLs(cpString); if (docletParentClassLoader == null) - appClassLoader = new URLClassLoader(urls); + appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName)); else appClassLoader = new URLClassLoader(urls, docletParentClassLoader); @@ -98,6 +98,57 @@ public class DocletInvoker { docletClass = dc; } + /* + * Returns the delegation class loader to use when creating + * appClassLoader (used to load the doclet). The context class + * loader is the best choice, but legacy behavior was to use the + * default delegation class loader (aka system class loader). + * + * Here we favor using the context class loader. To ensure + * compatibility with existing apps, we revert to legacy + * behavior if either or both of the following conditions hold: + * + * 1) the doclet is loadable from the system class loader but not + * from the context class loader, + * + * 2) this.getClass() is loadable from the system class loader but not + * from the context class loader. + */ + private ClassLoader getDelegationClassLoader(String docletClassName) { + ClassLoader ctxCL = Thread.currentThread().getContextClassLoader(); + ClassLoader sysCL = ClassLoader.getSystemClassLoader(); + if (sysCL == null) + return ctxCL; + if (ctxCL == null) + return sysCL; + + // Condition 1. + try { + sysCL.loadClass(docletClassName); + try { + ctxCL.loadClass(docletClassName); + } catch (ClassNotFoundException e) { + return sysCL; + } + } catch (ClassNotFoundException e) { + } + + // Condition 2. + try { + if (getClass() == sysCL.loadClass(getClass().getName())) { + try { + if (getClass() != ctxCL.loadClass(getClass().getName())) + return sysCL; + } catch (ClassNotFoundException e) { + return sysCL; + } + } + } catch (ClassNotFoundException e) { + } + + return ctxCL; + } + /** * Generate documentation here. Return true on success. */ @@ -231,6 +282,8 @@ public class DocletInvoker { docletClassName, methodName); throw new DocletInvokeException(); } + ClassLoader savedCCL = + Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(appClassLoader); return meth.invoke(null , params); @@ -256,6 +309,8 @@ public class DocletInvoker { exc.getTargetException().printStackTrace(); } throw new DocletInvokeException(); + } finally { + Thread.currentThread().setContextClassLoader(savedCCL); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java index 4162db4b1c1..7647ac03211 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java @@ -25,20 +25,18 @@ package com.sun.tools.javadoc; +import java.lang.reflect.Modifier; +import java.text.CollationKey; + import com.sun.javadoc.*; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Position; -import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; - -import java.text.CollationKey; - -import java.lang.reflect.Modifier; /** * Represents a method or constructor of a java class. @@ -267,7 +265,7 @@ public abstract class ExecutableMemberDocImpl */ public SourcePosition position() { if (sym.enclClass().sourcefile == null) return null; - return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(), + return SourcePositionImpl.make(sym.enclClass().sourcefile, (tree==null) ? 0 : tree.pos, lineMap); } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java index 4e7fe4a196e..4da1e1b819b 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java @@ -25,6 +25,8 @@ package com.sun.tools.javadoc; +import java.lang.reflect.Modifier; + import com.sun.javadoc.*; import static com.sun.javadoc.LanguageVersion.*; @@ -38,9 +40,6 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Position; -import java.lang.reflect.Modifier; - - /** * Represents a field in a java class. * @@ -260,7 +259,7 @@ public class FieldDocImpl extends MemberDocImpl implements FieldDoc { */ public SourcePosition position() { if (sym.enclClass().sourcefile == null) return null; - return SourcePositionImpl.make(sym.enclClass().sourcefile.toString(), + return SourcePositionImpl.make(sym.enclClass().sourcefile, (tree==null) ? 0 : tree.pos, lineMap); } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java index 12303e042e6..dbda1435c3b 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java @@ -25,18 +25,13 @@ package com.sun.tools.javadoc; -import com.sun.tools.javac.code.Symbol.PackageSymbol; -import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.file.ZipArchive.ZipFileObject; -import com.sun.tools.javac.file.Old199; -import com.sun.tools.javac.file.ZipFileIndexArchive; -import com.sun.tools.javac.jvm.ClassReader; -import com.sun.tools.javac.util.Context; - -import java.io.File; import java.util.EnumSet; import javax.tools.JavaFileObject; +import com.sun.tools.javac.code.Symbol.PackageSymbol; +import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.util.Context; + /** Javadoc uses an extended class reader that records package.html entries * @author Neal Gafter */ @@ -82,32 +77,7 @@ class JavadocClassReader extends ClassReader { */ @Override protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) { - CharSequence fileName = Old199.getName(fo); - if (docenv != null && fileName.equals("package.html")) { - if (fo instanceof ZipFileObject) { - ZipFileObject zfo = (ZipFileObject) fo; - String zipName = zfo.getZipName(); - String entryName = zfo.getZipEntryName(); - int lastSep = entryName.lastIndexOf("/"); - String classPathName = entryName.substring(0, lastSep + 1); - docenv.getPackageDoc(pack).setDocPath(zipName, classPathName); - } - else if (fo instanceof ZipFileIndexArchive.ZipFileIndexFileObject) { - ZipFileIndexArchive.ZipFileIndexFileObject zfo = (ZipFileIndexArchive.ZipFileIndexFileObject) fo; - String zipName = zfo.getZipName(); - String entryName = zfo.getZipEntryName(); - if (File.separatorChar != '/') { - entryName = entryName.replace(File.separatorChar, '/'); - } - - int lastSep = entryName.lastIndexOf("/"); - String classPathName = entryName.substring(0, lastSep + 1); - docenv.getPackageDoc(pack).setDocPath(zipName, classPathName); - } - else { - File fileDir = new File(Old199.getPath(fo)).getParentFile(); - docenv.getPackageDoc(pack).setDocPath(fileDir.getAbsolutePath()); - } - } + if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) + docenv.getPackageDoc(pack).setDocPath(fo); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java index 30c4c74e56c..2cb3ab3288d 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java @@ -25,17 +25,29 @@ package com.sun.tools.javadoc; -import java.io.*; - +import java.io.File; +import java.io.IOException; import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.comp.*; -import com.sun.tools.javac.file.Paths; +import com.sun.tools.javac.code.Symbol.CompletionFailure; +import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.parser.DocCommentScanner; -import com.sun.tools.javac.tree.*; -import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.util.*; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.util.Abort; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Position; /** @@ -53,7 +65,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { final JavadocClassReader reader; final JavadocEnter enter; final Annotate annotate; - private final Paths paths; /** * Construct a new JavaCompiler processor, using appropriately @@ -66,7 +77,6 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { reader = JavadocClassReader.instance0(context); enter = JavadocEnter.instance0(context); annotate = Annotate.instance(context); - paths = Paths.instance(context); } /** @@ -120,7 +130,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { boolean quiet) throws IOException { docenv = DocEnv.instance(context); docenv.showAccess = filter; - docenv.quiet = quiet; + docenv.quiet = quiet; docenv.breakiterator = breakiterator; docenv.setLocale(doclocale); docenv.setEncoding(encoding); @@ -133,12 +143,14 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { ListBuffer packTrees = new ListBuffer(); try { + StandardJavaFileManager fm = (StandardJavaFileManager) docenv.fileManager; for (List it = javaNames; it.nonEmpty(); it = it.tail) { String name = it.head; if (!docClasses && name.endsWith(".java") && new File(name).exists()) { + JavaFileObject fo = fm.getJavaFileObjects(name).iterator().next(); docenv.notice("main.Loading_source_file", name); - JCCompilationUnit tree = parse(name); - classTrees.append(tree); + JCCompilationUnit tree = parse(fo); + classTrees.append(tree); } else if (isValidPackageName(name)) { names = names.append(name); } else if (name.endsWith(".java")) { @@ -151,12 +163,14 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { if (!docClasses) { // Recursively search given subpackages. If any packages //are found, add them to the list. - searchSubPackages(subPackages, names, excludedPackages); + Map> packageFiles = + searchSubPackages(subPackages, names, excludedPackages); // Parse the packages for (List packs = names.toList(); packs.nonEmpty(); packs = packs.tail) { // Parse sources ostensibly belonging to package. - parsePackageClasses(packs.head, packTrees, excludedPackages); + String packageName = packs.head; + parsePackageClasses(packageName, packageFiles.get(packageName), packTrees, excludedPackages); } if (messager.nerrors() != 0) return null; @@ -167,7 +181,8 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { } } catch (Abort ex) {} - if (messager.nerrors() != 0) return null; + if (messager.nerrors() != 0) + return null; if (docClasses) return new RootDocImpl(docenv, javaNames, options); @@ -185,66 +200,129 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { return isValidClassName(s); } - - private final static char pathSep = File.pathSeparatorChar; - /** * search all directories in path for subdirectory name. Add all * .java files found in such a directory to args. */ private void parsePackageClasses(String name, - ListBuffer trees, - List excludedPackages) - throws IOException { + Iterable files, + ListBuffer trees, + List excludedPackages) + throws IOException { if (excludedPackages.contains(name)) { return; } + boolean hasFiles = false; docenv.notice("main.Loading_source_files_for_package", name); - name = name.replace('.', File.separatorChar); - for (File pathname : paths.sourceSearchPath()) { - File f = new File(pathname, name); - String names[] = f.list(); - // if names not null, then found directory with source files - if (names != null) { - String dir = f.getAbsolutePath(); - if (!dir.endsWith(File.separator)) - dir = dir + File.separator; - for (int j = 0; j < names.length; j++) { - if (isValidJavaSourceFile(names[j])) { - String fn = dir + names[j]; - // messager.notice("main.Loading_source_file", fn); - trees.append(parse(fn)); - hasFiles = true; - } + + if (files == null) { + Location location = docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) + ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH; + ListBuffer lb = new ListBuffer(); + for (JavaFileObject fo: docenv.fileManager.list( + location, name, EnumSet.of(JavaFileObject.Kind.SOURCE), false)) { + String binaryName = docenv.fileManager.inferBinaryName(location, fo); + String simpleName = getSimpleName(binaryName); + if (isValidClassName(simpleName)) { + lb.append(fo); } } + files = lb.toList(); } - if (!hasFiles) + + for (JavaFileObject fo : files) { + // messager.notice("main.Loading_source_file", fn); + trees.append(parse(fo)); + hasFiles = true; + } + + if (!hasFiles) { messager.warning(null, "main.no_source_files_for_package", - name.replace(File.separatorChar, '.')); + name.replace(File.separatorChar, '.')); + } } /** * Recursively search all directories in path for subdirectory name. * Add all packages found in such a directory to packages list. */ - private void searchSubPackages(List subPackages, - ListBuffer packages, - List excludedPackages) { - // FIXME: This search path is bogus. - // Only the effective source path should be searched for sources. - // Only the effective class path should be searched for classes. - // Should the bootclasspath/extdirs also be searched for classes? - java.util.List pathnames = new java.util.ArrayList(); - if (paths.sourcePath() != null) - for (File elt : paths.sourcePath()) - pathnames.add(elt); - for (File elt : paths.userClassPath()) - pathnames.add(elt); + private Map> searchSubPackages( + List subPackages, + ListBuffer packages, + List excludedPackages) + throws IOException { + Map> packageFiles = + new HashMap>(); - for (String subPackage : subPackages) - searchSubPackage(subPackage, packages, excludedPackages, pathnames); + Map includedPackages = new HashMap(); + includedPackages.put("", true); + for (String p: excludedPackages) + includedPackages.put(p, false); + + if (docenv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { + searchSubPackages(subPackages, + includedPackages, + packages, packageFiles, + StandardLocation.SOURCE_PATH, + EnumSet.of(JavaFileObject.Kind.SOURCE)); + searchSubPackages(subPackages, + includedPackages, + packages, packageFiles, + StandardLocation.CLASS_PATH, + EnumSet.of(JavaFileObject.Kind.CLASS)); + } else { + searchSubPackages(subPackages, + includedPackages, + packages, packageFiles, + StandardLocation.CLASS_PATH, + EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS)); + } + return packageFiles; + } + + private void searchSubPackages(List subPackages, + Map includedPackages, + ListBuffer packages, + Map> packageFiles, + StandardLocation location, Set kinds) + throws IOException { + for (String subPackage: subPackages) { + if (!isIncluded(subPackage, includedPackages)) + continue; + + for (JavaFileObject fo: docenv.fileManager.list(location, subPackage, kinds, true)) { + String binaryName = docenv.fileManager.inferBinaryName(location, fo); + String packageName = getPackageName(binaryName); + String simpleName = getSimpleName(binaryName); + if (isIncluded(packageName, includedPackages) && isValidClassName(simpleName)) { + List list = packageFiles.get(packageName); + list = (list == null ? List.of(fo) : list.prepend(fo)); + packageFiles.put(packageName, list); + if (!packages.contains(packageName)) + packages.add(packageName); + } + } + } + } + + private String getPackageName(String name) { + int lastDot = name.lastIndexOf("."); + return (lastDot == -1 ? "" : name.substring(0, lastDot)); + } + + private String getSimpleName(String name) { + int lastDot = name.lastIndexOf("."); + return (lastDot == -1 ? name : name.substring(lastDot + 1)); + } + + private boolean isIncluded(String packageName, Map includedPackages) { + Boolean b = includedPackages.get(packageName); + if (b == null) { + b = isIncluded(getPackageName(packageName), includedPackages); + includedPackages.put(packageName, b); + } + return b; } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java b/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java index 1933862a5c7..4419fc2ea18 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java @@ -111,6 +111,7 @@ public class Messager extends Log implements DocErrorReporter { * @param warnWriter Stream for warnings * @param noticeWriter Stream for other messages */ + @SuppressWarnings("deprecation") protected Messager(Context context, String programName, PrintWriter errWriter, diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java index 426123eba25..97e1b09b66e 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java @@ -25,30 +25,23 @@ package com.sun.tools.javadoc; -import com.sun.javadoc.*; - -import java.io.File; import java.io.InputStream; -import java.io.FileInputStream; import java.io.IOException; -import java.util.zip.ZipFile; -import java.util.zip.ZipEntry; +import javax.tools.FileObject; + +import com.sun.javadoc.*; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; -import com.sun.tools.javac.comp.AttrContext; -import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Position; -import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; - - /** * Represents a java package. Provides access to information * about the package, the package's comment and tags, and the @@ -63,14 +56,10 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; public class PackageDocImpl extends DocImpl implements PackageDoc { - private static final String PACKAGE_HTML_FILE_NAME = "package.html"; - protected PackageSymbol sym; private JCCompilationUnit tree = null; // for source position - public String docPath = null; - public String zipDocPath = null; - public String zipDocEntry = null; + public FileObject docPath = null; private boolean foundDoc; // found a doc comment in either // package.html or package-info.java @@ -108,30 +97,16 @@ public class PackageDocImpl extends DocImpl implements PackageDoc { * Do lazy initialization of "documentation" string. */ String documentation() { - if (documentation != null) return documentation; - if (zipDocPath != null) { - try { - ZipFile f = new ZipFile(zipDocPath); - ZipEntry entry = f.getEntry(zipDocEntry); - if (entry != null) { - InputStream s = f.getInputStream(entry); - return (documentation = readHTMLDocumentation(s, - zipDocPath + File.separatorChar + zipDocEntry)); - } - } catch (IOException exc) { - documentation = ""; - env.error(null, "javadoc.File_Read_Error", - zipDocPath + File.separatorChar + zipDocEntry); - } - } + if (documentation != null) + return documentation; if (docPath != null) { // read from file try { - InputStream s = new FileInputStream(docPath); + InputStream s = docPath.openInputStream(); documentation = readHTMLDocumentation(s, docPath); } catch (IOException exc) { documentation = ""; - env.error(null, "javadoc.File_Read_Error", docPath); + env.error(null, "javadoc.File_Read_Error", docPath.getName()); } } else { // no doc file to be had @@ -363,24 +338,12 @@ public class PackageDocImpl extends DocImpl implements PackageDoc { /** * set doc path for an unzipped directory */ - public void setDocPath(String path) { + public void setDocPath(FileObject path) { setDocPath = true; if (path == null) return; - String newDocPath = path + File.separatorChar + PACKAGE_HTML_FILE_NAME; - if (!newDocPath.equals(docPath)) { - docPath = newDocPath; - checkDoc(); - } - } - - /** - * set the doc path for zipped directory - */ - public void setDocPath(String path, String entry) { - if (!path.equals(zipDocPath)) { - zipDocPath = path; - zipDocEntry = entry + PACKAGE_HTML_FILE_NAME; + if (!path.equals(docPath)) { + docPath = path; checkDoc(); } } @@ -409,7 +372,7 @@ public class PackageDocImpl extends DocImpl implements PackageDoc { */ public SourcePosition position() { return (tree != null) - ? SourcePositionImpl.make(tree.sourcefile + "", tree.pos, tree.lineMap) + ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap) : SourcePositionImpl.make(docPath, Position.NOPOS, null); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java index 8595151cc32..e39f0b3e1d4 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java @@ -26,13 +26,13 @@ package com.sun.tools.javadoc; import java.io.IOException; -import java.io.FileInputStream; -import java.io.File; +import java.util.Locale; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; import com.sun.javadoc.*; import com.sun.tools.javac.tree.JCTree.JCClassDecl; -import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Position; @@ -307,10 +307,13 @@ public class RootDocImpl extends DocImpl implements RootDoc { * Return the path of the overview file and null if it does not exist. * @return the path of the overview file and null if it does not exist. */ - private String getOverviewPath() { + private JavaFileObject getOverviewPath() { for (String[] opt : options) { if (opt[0].equals("-overview")) { - return opt[1]; + if (env.fileManager instanceof StandardJavaFileManager) { + StandardJavaFileManager fm = (StandardJavaFileManager) env.fileManager; + return fm.getJavaFileObjects(opt[1]).iterator().next(); + } } } return null; @@ -322,7 +325,7 @@ public class RootDocImpl extends DocImpl implements RootDoc { protected String documentation() { if (documentation == null) { int cnt = options.length(); - String overviewPath = getOverviewPath(); + JavaFileObject overviewPath = getOverviewPath(); if (overviewPath == null) { // no doc file to be had documentation = ""; @@ -330,11 +333,11 @@ public class RootDocImpl extends DocImpl implements RootDoc { // read from file try { documentation = readHTMLDocumentation( - new FileInputStream(overviewPath), + overviewPath.openInputStream(), overviewPath); } catch (IOException exc) { documentation = ""; - env.error(null, "javadoc.File_Read_Error", overviewPath); + env.error(null, "javadoc.File_Read_Error", overviewPath.getName()); } } } @@ -346,9 +349,16 @@ public class RootDocImpl extends DocImpl implements RootDoc { * no position is available. */ public SourcePosition position() { - String path; + JavaFileObject path; return ((path = getOverviewPath()) == null) ? null : SourcePositionImpl.make(path, Position.NOPOS, null); } + + /** + * Return the locale provided by the user or the default locale value. + */ + public Locale getLocale() { + return env.doclocale.locale; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java index 2225dd5337f..0e666b83f6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java @@ -25,11 +25,12 @@ package com.sun.tools.javadoc; +import java.io.File; +import javax.tools.FileObject; + import com.sun.javadoc.SourcePosition; import com.sun.tools.javac.util.Position; -import java.io.File; - /** * A source position: filename, line number, and column number. * @@ -37,15 +38,21 @@ import java.io.File; * @author Neal M Gafter * @author Michael Van De Vanter (position representation changed to char offsets) */ -class SourcePositionImpl implements SourcePosition { - String filename; +public class SourcePositionImpl implements SourcePosition { + FileObject filename; int position; Position.LineMap lineMap; /** The source file. Returns null if no file information is * available. */ public File file() { - return (filename == null) ? null : new File(filename); + return (filename == null) ? null : new File(filename.getName()); + } + + /** The source file. Returns null if no file information is + * available. */ + public FileObject fileObject() { + return filename; } /** The line in the source file. The first line is numbered 1; @@ -71,7 +78,7 @@ class SourcePositionImpl implements SourcePosition { } } - private SourcePositionImpl(String file, int position, + private SourcePositionImpl(FileObject file, int position, Position.LineMap lineMap) { super(); this.filename = file; @@ -79,16 +86,27 @@ class SourcePositionImpl implements SourcePosition { this.lineMap = lineMap; } - public static SourcePosition make(String file, int pos, + public static SourcePosition make(FileObject file, int pos, Position.LineMap lineMap) { if (file == null) return null; return new SourcePositionImpl(file, pos, lineMap); } public String toString() { + // Backwards compatibility hack. ZipFileObjects use the format + // zipfile(zipentry) but javadoc has been using zipfile/zipentry + String fn = filename.toString(); + if (fn.endsWith(")")) { + int paren = fn.lastIndexOf("("); + if (paren != -1) + fn = fn.substring(0, paren) + + File.separatorChar + + fn.substring(paren + 1, fn.length() - 1); + } + if (position == Position.NOPOS) - return filename; + return fn; else - return filename + ":" + line(); + return fn + ":" + line(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java index 9e1a00ef3fd..ec1bb1e8002 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java @@ -51,6 +51,7 @@ public class TypeMaker { * @param errToClassDoc if true, ERROR type results in a ClassDoc; * false preserves legacy behavior */ + @SuppressWarnings("fallthrough") public static com.sun.javadoc.Type getType(DocEnv env, Type t, boolean errToClassDoc) { if (env.legacyDoclet) { diff --git a/langtools/src/share/classes/com/sun/tools/javah/Gen.java b/langtools/src/share/classes/com/sun/tools/javah/Gen.java index 3ab6f961299..1f0bb5ebd83 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javah/Gen.java @@ -342,6 +342,6 @@ public abstract class Gen { fields.addAll(Arrays.asList(cd.fields())); } - return (FieldDoc[]) fields.toArray(new FieldDoc[fields.size()]); + return fields.toArray(new FieldDoc[fields.size()]); } } diff --git a/langtools/src/share/classes/com/sun/tools/javap/InternalError.java b/langtools/src/share/classes/com/sun/tools/javap/InternalError.java index 5397e7d267d..cc3903e0f1b 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/InternalError.java +++ b/langtools/src/share/classes/com/sun/tools/javap/InternalError.java @@ -32,6 +32,7 @@ package com.sun.tools.javap; * deletion without notice. */ public class InternalError extends Error { + private static final long serialVersionUID = 8114054446416187030L; InternalError(Throwable t, Object... args) { super("Internal error", t); this.args = args; diff --git a/langtools/src/share/classes/javax/lang/model/UnknownEntityException.java b/langtools/src/share/classes/javax/lang/model/UnknownEntityException.java new file mode 100644 index 00000000000..6151927f51f --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/UnknownEntityException.java @@ -0,0 +1,57 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.lang.model; + +/** + * Superclass of exceptions which indicate that an unknown kind of + * entity was encountered. This situation can occur if the language + * evolves and new kinds of constructs are introduced. Subclasses of + * this exception may be thrown by visitors to indicate that the + * visitor was created for a prior version of the language. + * + *

A common superclass for those exceptions allows a single catch + * block to have code handling them uniformly. + * + * @author Joseph D. Darcy + * @see javax.lang.model.element.UnknownElementException + * @see javax.lang.model.element.UnknownAnnotationValueException + * @see javax.lang.model.type.UnknownTypeException + * @since 1.7 + */ +public class UnknownEntityException extends RuntimeException { + + private static final long serialVersionUID = 269L; + + /** + * Creates a new {@code UnknownEntityException} with the specified + * detail message. + * + * @param message the detail message + */ + protected UnknownEntityException(String message) { + super(message); + } +} diff --git a/langtools/src/share/classes/javax/lang/model/element/ExecutableElement.java b/langtools/src/share/classes/javax/lang/model/element/ExecutableElement.java index 180f23b4271..427373fd4d9 100644 --- a/langtools/src/share/classes/javax/lang/model/element/ExecutableElement.java +++ b/langtools/src/share/classes/javax/lang/model/element/ExecutableElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import javax.lang.model.type.*; * @see ExecutableType * @since 1.6 */ -public interface ExecutableElement extends Element { +public interface ExecutableElement extends Element, Parameterizable { /** * Returns the formal type parameters of this executable * in declaration order. diff --git a/langtools/src/share/classes/javax/lang/model/element/PackageElement.java b/langtools/src/share/classes/javax/lang/model/element/PackageElement.java index 56df80ab118..e6b74e2f295 100644 --- a/langtools/src/share/classes/javax/lang/model/element/PackageElement.java +++ b/langtools/src/share/classes/javax/lang/model/element/PackageElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package javax.lang.model.element; - /** * Represents a package program element. Provides access to information * about the package and its members. @@ -36,8 +35,7 @@ package javax.lang.model.element; * @see javax.lang.model.util.Elements#getPackageOf * @since 1.6 */ - -public interface PackageElement extends Element { +public interface PackageElement extends Element, QualifiedNameable { /** * Returns the fully qualified name of this package. diff --git a/langtools/src/share/classes/javax/lang/model/element/Parameterizable.java b/langtools/src/share/classes/javax/lang/model/element/Parameterizable.java new file mode 100644 index 00000000000..cc428b208ea --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/element/Parameterizable.java @@ -0,0 +1,45 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.lang.model.element; + +import java.util.List; + +/** + * A mixin interface for an element that has type parameters. + * + * @author Joseph D. Darcy + * @since 1.7 + */ +public interface Parameterizable extends Element { + /** + * Returns the formal type parameters of the type element in + * declaration order. + * + * @return the formal type parameters, or an empty list + * if there are none + */ + List getTypeParameters(); +} diff --git a/langtools/src/share/classes/javax/lang/model/element/QualifiedNameable.java b/langtools/src/share/classes/javax/lang/model/element/QualifiedNameable.java new file mode 100644 index 00000000000..a6096bf302b --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/element/QualifiedNameable.java @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javax.lang.model.element; + +/** + * A mixin interface for an element that has a qualified name. + * + * @author Joseph D. Darcy + * @since 1.7 + */ +public interface QualifiedNameable extends Element { + /** + * Returns the fully qualified name of an element. + * + * @return the fully qualified name of an element + */ + Name getQualifiedName(); +} diff --git a/langtools/src/share/classes/javax/lang/model/element/TypeElement.java b/langtools/src/share/classes/javax/lang/model/element/TypeElement.java index 235a25285f2..808ac778c23 100644 --- a/langtools/src/share/classes/javax/lang/model/element/TypeElement.java +++ b/langtools/src/share/classes/javax/lang/model/element/TypeElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ import javax.lang.model.util.*; * @see DeclaredType * @since 1.6 */ -public interface TypeElement extends Element { +public interface TypeElement extends Element, Parameterizable, QualifiedNameable { /** * Returns the nesting kind of this type element. diff --git a/langtools/src/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java b/langtools/src/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java index d77f9e84b78..fa2a47882ea 100644 --- a/langtools/src/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java +++ b/langtools/src/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package javax.lang.model.element; +import javax.lang.model.UnknownEntityException; + /** * Indicates that an unknown kind of annotation value was encountered. * This can occur if the language evolves and new kinds of annotation @@ -39,7 +41,7 @@ package javax.lang.model.element; * @see AnnotationValueVisitor#visitUnknown * @since 1.6 */ -public class UnknownAnnotationValueException extends RuntimeException { +public class UnknownAnnotationValueException extends UnknownEntityException { private static final long serialVersionUID = 269L; diff --git a/langtools/src/share/classes/javax/lang/model/element/UnknownElementException.java b/langtools/src/share/classes/javax/lang/model/element/UnknownElementException.java index 8206248478b..911a411e5d8 100644 --- a/langtools/src/share/classes/javax/lang/model/element/UnknownElementException.java +++ b/langtools/src/share/classes/javax/lang/model/element/UnknownElementException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package javax.lang.model.element; +import javax.lang.model.UnknownEntityException; + /** * Indicates that an unknown kind of element was encountered. This * can occur if the language evolves and new kinds of elements are @@ -38,7 +40,7 @@ package javax.lang.model.element; * @see ElementVisitor#visitUnknown * @since 1.6 */ -public class UnknownElementException extends RuntimeException { +public class UnknownElementException extends UnknownEntityException { private static final long serialVersionUID = 269L; diff --git a/langtools/src/share/classes/javax/lang/model/type/MirroredTypeException.java b/langtools/src/share/classes/javax/lang/model/type/MirroredTypeException.java index bf5904b8a61..db729c59550 100644 --- a/langtools/src/share/classes/javax/lang/model/type/MirroredTypeException.java +++ b/langtools/src/share/classes/javax/lang/model/type/MirroredTypeException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package javax.lang.model.type; - +import java.io.ObjectInputStream; +import java.io.IOException; import java.lang.annotation.Annotation; import javax.lang.model.element.Element; @@ -67,4 +68,13 @@ public class MirroredTypeException extends RuntimeException { public TypeMirror getTypeMirror() { return type; } + + /** + * Explicitly set all transient fields. + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + type = null; + } } diff --git a/langtools/src/share/classes/javax/lang/model/type/MirroredTypesException.java b/langtools/src/share/classes/javax/lang/model/type/MirroredTypesException.java index 4ed0383d5ea..54efe41a7c9 100644 --- a/langtools/src/share/classes/javax/lang/model/type/MirroredTypesException.java +++ b/langtools/src/share/classes/javax/lang/model/type/MirroredTypesException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,12 @@ package javax.lang.model.type; - import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; import java.util.Collections; - +import java.io.ObjectInputStream; +import java.io.IOException; import javax.lang.model.element.Element; @@ -49,8 +49,7 @@ public class MirroredTypesException extends RuntimeException { private static final long serialVersionUID = 269; - // Should this be non-final for a custum readObject method? - private final transient List types; // cannot be serialized + private transient List types; // cannot be serialized /** * Constructs a new MirroredTypesException for the specified types. @@ -58,7 +57,9 @@ public class MirroredTypesException extends RuntimeException { * @param types the types being accessed */ public MirroredTypesException(List types) { - super("Attempt to access Class objects for TypeMirrors " + types); + super("Attempt to access Class objects for TypeMirrors " + + (types = // defensive copy + new ArrayList(types)).toString() ); this.types = Collections.unmodifiableList(types); } @@ -72,4 +73,13 @@ public class MirroredTypesException extends RuntimeException { public List getTypeMirrors() { return types; } + + /** + * Explicitly set all transient fields. + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + types = null; + } } diff --git a/langtools/src/share/classes/javax/lang/model/type/UnknownTypeException.java b/langtools/src/share/classes/javax/lang/model/type/UnknownTypeException.java index e4049cf0156..cbca20ce709 100644 --- a/langtools/src/share/classes/javax/lang/model/type/UnknownTypeException.java +++ b/langtools/src/share/classes/javax/lang/model/type/UnknownTypeException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package javax.lang.model.type; +import javax.lang.model.UnknownEntityException; + /** * Indicates that an unknown kind of type was encountered. This can * occur if the language evolves and new kinds of types are added to @@ -38,7 +40,7 @@ package javax.lang.model.type; * @see TypeVisitor#visitUnknown * @since 1.6 */ -public class UnknownTypeException extends RuntimeException { +public class UnknownTypeException extends UnknownEntityException { private static final long serialVersionUID = 269L; diff --git a/langtools/src/share/classes/sun/tools/javap/JavapPrinter.java b/langtools/src/share/classes/sun/tools/javap/JavapPrinter.java index a587ddc5d15..af5978aec26 100644 --- a/langtools/src/share/classes/sun/tools/javap/JavapPrinter.java +++ b/langtools/src/share/classes/sun/tools/javap/JavapPrinter.java @@ -719,6 +719,7 @@ public class JavapPrinter { /** * Print constant pool entry information. */ + @SuppressWarnings("fallthrough") public int PrintlnConstantEntry(int cpx) { int size=1; byte tag=0; @@ -757,6 +758,7 @@ public class JavapPrinter { case CONSTANT_LONG: case CONSTANT_DOUBLE: size=2; + // fall through default: out.println(str+";"); } diff --git a/langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java b/langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java new file mode 100644 index 00000000000..4588d070b7e --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTag/TestHtmlTag.java @@ -0,0 +1,93 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6786682 + * @summary This test verifies the use of lang attribute by . + * @author Bhavesh Patel + * @library ../lib/ + * @build JavadocTester + * @build TestHtmlTag + * @run main TestHtmlTag + */ + +import java.util.Locale; + +public class TestHtmlTag extends JavadocTester { + + private static final String BUG_ID = "6786682"; + private static final String[][] TEST1 = { + {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", ""}}; + private static final String[][] NEGATED_TEST1 = { + {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}}; + private static final String[][] TEST2 = { + {BUG_ID + FS + "pkg2" + FS + "C2.html", ""}, + {BUG_ID + FS + "pkg2" + FS + "package-summary.html", ""}}; + private static final String[][] NEGATED_TEST2 = { + {BUG_ID + FS + "pkg2" + FS + "C2.html", ""}}; + private static final String[][] TEST3 = { + {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}, + {BUG_ID + FS + "pkg1" + FS + "package-summary.html", ""}}; + private static final String[][] NEGATED_TEST3 = { + {BUG_ID + FS + "pkg1" + FS + "C1.html", ""}}; + + private static final String[] ARGS1 = + new String[] { + "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; + private static final String[] ARGS2 = + new String[] { + "-locale", "ja", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg2"}; + private static final String[] ARGS3 = + new String[] { + "-locale", "en_US", "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestHtmlTag tester = new TestHtmlTag(); + run(tester, ARGS1, TEST1, NEGATED_TEST1); + run(tester, ARGS2, TEST2, NEGATED_TEST2); + run(tester, ARGS3, TEST3, NEGATED_TEST3); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTag/pkg1/C1.java b/langtools/test/com/sun/javadoc/testHtmlTag/pkg1/C1.java new file mode 100644 index 00000000000..5fb4bc8a30e --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTag/pkg1/C1.java @@ -0,0 +1,33 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +public class C1 { + + public void method(int param1, int param2) { + + } +} diff --git a/langtools/test/com/sun/javadoc/testHtmlTag/pkg2/C2.java b/langtools/test/com/sun/javadoc/testHtmlTag/pkg2/C2.java new file mode 100644 index 00000000000..2bd9d323be8 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testHtmlTag/pkg2/C2.java @@ -0,0 +1,31 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg2; + +/** + * Comments: Class 2 + */ +public class C2 {} diff --git a/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java new file mode 100644 index 00000000000..d4f5294ba44 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/TestSerializedFormDeprecationInfo.java @@ -0,0 +1,151 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6802694 + * @summary This test verifies deprecation info in serialized-form.html. + * @author Bhavesh Patel + * @library ../lib/ + * @build JavadocTester + * @build TestSerializedFormDeprecationInfo + * @run main TestSerializedFormDeprecationInfo + */ + +public class TestSerializedFormDeprecationInfo extends JavadocTester { + + private static final String BUG_ID = "6802694"; + + // Test for normal run of javadoc. The serialized-form.html should + // display the inline comments, tags and deprecation information if any. + private static final String[][] TEST_CMNT_DEPR = { + {BUG_ID + FS + "serialized-form.html", "

" + NL + "
" + NL + NL + + "
Throws:" + NL + "
" + + "java.io.IOException
See Also:" + + "
" + + "C1.setUndecorated(boolean)
" + NL + + "
" + NL + "
"}, + {BUG_ID + FS + "serialized-form.html", "
" + NL + + "
Deprecated. As of JDK version" + + " 1.5, replaced by" + NL + + " " + + "setUndecorated(boolean)." + + "
This field indicates whether the C1 is undecorated." + NL + + "

" + NL + "

 
" + NL + + "
Since:
" + NL + + "
1.4
" + NL + "
See Also:" + + "
" + + "C1.setUndecorated(boolean)
" + NL + + "
"}, + {BUG_ID + FS + "serialized-form.html", "
" + NL + + "
Deprecated. As of JDK version" + + " 1.5, replaced by" + NL + + " " + + "setUndecorated(boolean)." + NL + "

" + NL + + "

Reads the object stream." + NL + "

" + NL + + "

" + NL + NL + "
Throws:" + + "" + NL + "
" + + "IOException" + NL + + "
java.io.IOException
" + NL + + "
" + NL + "
"}, + {BUG_ID + FS + "serialized-form.html", "
" + NL + + "
Deprecated. 
" + + "The name for this class." + NL + "

" + NL + + "

 
" + NL + "
" + NL + "
"}}; + + // Test with -nocomment option. The serialized-form.html should + // not display the inline comments and tags but should display deprecation + // information if any. + private static final String[][] TEST_NOCMNT = { + {BUG_ID + FS + "serialized-form.html", "
" + NL + "boolean " +
+                 "undecorated
" + NL + "
" + NL + "
" + + "Deprecated. As of JDK version 1.5, replaced by" + NL + + " " + + "setUndecorated(boolean).
"}, + {BUG_ID + FS + "serialized-form.html", "
" + NL + "
" + + "Deprecated. As of JDK version" + + " 1.5, replaced by" + NL + + " " + + "setUndecorated(boolean)." + NL + "

" + NL + + "

"}, + {BUG_ID + FS + "serialized-form.html", "
" + NL + "int " +
+                 "publicKey
" + NL + "
" + NL + "
" + + "Deprecated. 
"}}; + + // Test with -nodeprecated option. The serialized-form.html should + // ignore the -nodeprecated tag and display the deprecation info. This + // test is similar to the normal run of javadoc in which inline comment, tags + // and deprecation information will be displayed. + private static final String[][] TEST_NODEPR = TEST_CMNT_DEPR; + + // Test with -nodeprecated and -nocomment options. The serialized-form.html should + // ignore the -nodeprecated tag and display the deprecation info but should not + // display the inline comments and tags. This test is similar to the test with + // -nocomment option. + private static final String[][] TEST_NOCMNT_NODEPR = TEST_NOCMNT; + + private static final String[] ARGS1 = + new String[] { + "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg1"}; + + private static final String[] ARGS2 = + new String[] { + "-d", BUG_ID, "-nocomment", "-sourcepath", SRC_DIR, "pkg1"}; + + private static final String[] ARGS3 = + new String[] { + "-d", BUG_ID, "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + + private static final String[] ARGS4 = + new String[] { + "-d", BUG_ID, "-nocomment", "-nodeprecated", "-sourcepath", SRC_DIR, "pkg1"}; + + /** + * The entry point of the test. + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestSerializedFormDeprecationInfo tester = new TestSerializedFormDeprecationInfo(); + run(tester, ARGS1, TEST_CMNT_DEPR, TEST_NOCMNT); + run(tester, ARGS2, TEST_NOCMNT, TEST_CMNT_DEPR); + run(tester, ARGS3, TEST_NODEPR, TEST_NOCMNT_NODEPR); + run(tester, ARGS4, TEST_NOCMNT_NODEPR, TEST_NODEPR); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C1.java b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C1.java new file mode 100644 index 00000000000..a3dbc13e629 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C1.java @@ -0,0 +1,108 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +import java.io.IOException; +import java.io.Serializable; + +/** + * A class comment for testing. + * + * @author Bhavesh Patel + * @see C2 + * @since JDK1.0 + */ + +public class C1 implements Serializable { + + /** + * This field indicates whether the C1 is undecorated. + * + * @see #setUndecorated(boolean) + * @since 1.4 + * @serial + * @deprecated As of JDK version 1.5, replaced by + * {@link C1#setUndecorated(boolean) setUndecorated(boolean)}. + */ + @Deprecated + public boolean undecorated = false; + + private String title; + + /** + * This enum specifies the possible modal exclusion types. + * + * @since 1.6 + */ + public static enum ModalExclusionType { + /** + * No modal exclusion. + */ + NO_EXCLUDE, + /** + * APPLICATION_EXCLUDE indicates that a top-level window + * won't be blocked by any application-modal dialogs. Also, it isn't + * blocked by document-modal dialogs from outside of its child hierarchy. + */ + APPLICATION_EXCLUDE + }; + + /** + * Constructor. + * + * @param title the title + * @param test boolean value + * @exception IllegalArgumentException if the owner's + * GraphicsConfiguration is not from a screen device + * @exception HeadlessException + */ + public C1(String title, boolean test) { + + } + + public C1(String title) { + + } + + /** + * Method comments. + * @param undecorated true if no decorations are + * to be enabled; + * false if decorations are to be enabled. + * @see #readObject() + * @since 1.4 + */ + public void setUndecorated(boolean undecorated) { + /* Make sure we don't run in the middle of peer creation.*/ + } + + /** + * @see #setUndecorated(boolean) + */ + public void readObject() throws IOException { + + } +} diff --git a/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C2.java b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C2.java new file mode 100644 index 00000000000..b0e098d1e63 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C2.java @@ -0,0 +1,86 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +import java.io.ObjectInputStream; +import java.io.IOException; +import java.io.Serializable; + +/** + * A class comment for testing. + * + * @author Bhavesh Patel + * @see C1 + * @since JDK1.0 + */ + +public class C2 implements Serializable { + + /** + * This field indicates title. + */ + String title; + + public static enum ModalType { + NO_EXCLUDE + }; + + /** + * Constructor. + * + */ + public C2() { + + } + + public C2(String title) { + + } + + /** + * Set visible. + * + * @param set boolean + * @since 1.4 + * @deprecated As of JDK version 1.5, replaced by + * {@link C1#setUndecorated(boolean) setUndecorated(boolean)}. + */ + @Deprecated + public void setVisible(boolean set) { + } + + /** + * Reads the object stream. + * + * @param s ObjectInputStream + * @throws IOException + * @deprecated As of JDK version 1.5, replaced by + * {@link C1#setUndecorated(boolean) setUndecorated(boolean)}. + */ + @Deprecated + public void readObject(ObjectInputStream s) throws IOException { + } +} diff --git a/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C3.java b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C3.java new file mode 100644 index 00000000000..918a674a0f6 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testSerializedFormDeprecationInfo/pkg1/C3.java @@ -0,0 +1,65 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package pkg1; + +import java.io.Serializable; + +/** + * Test for Serializable + * + * @author Bhavesh Patel + * @deprecated This class is no longer used. + */ +@Deprecated +public abstract class C3 implements Serializable { + + /** + * The name for this class. + * + * @serial + */ + private String name; + + /** + * @serial + */ + private int publicKey; + + /** + * Constructor for serialization only. + */ + protected C3() { + + } + + /** + * Prints general information. + * + */ + public void printInfo() { + + } +} diff --git a/langtools/test/tools/javac/6304921/T6304921.out b/langtools/test/tools/javac/6304921/T6304921.out index 27b869deaef..7a18b056006 100644 --- a/langtools/test/tools/javac/6304921/T6304921.out +++ b/langtools/test/tools/javac/6304921/T6304921.out @@ -1,25 +1,20 @@ T6304921.java:671/671/680: warning: [rawtypes] found raw type: java.util.ArrayList -missing type parameters for generic class java.util.ArrayList List list = new ArrayList(); ^ + missing type parameters for generic class java.util.ArrayList T6304921.java:667/667/682: warning: [unchecked] unchecked conversion -found : java.util.ArrayList -required: java.util.List List list = new ArrayList(); ^ -T6304921.java:445/445/453: warning: [fallthrough] possible fall-through into case - default: - ^ -T6304921.java:522/613/614: warning: [finally] finally clause cannot complete normally - } - ^ + required: java.util.List + found: java.util.ArrayList +error: warnings found and -Werror specified T6304921.java:727/733/737: cannot find symbol -symbol : variable orr -location: class java.lang.System System.orr.println("abc"); // name not found ^ + symbol: variable orr + location: class java.lang.System T6304921.java:812/816/822: operator + cannot be applied to int,boolean return 123 + true; // bad binary expression ^ -2 errors -4 warnings +3 errors +2 warnings diff --git a/langtools/test/tools/javac/6668794/badClass/Test.java b/langtools/test/tools/javac/6668794/badClass/Test.java index 40e514f89a5..e78ce5fcc3d 100644 --- a/langtools/test/tools/javac/6668794/badClass/Test.java +++ b/langtools/test/tools/javac/6668794/badClass/Test.java @@ -54,8 +54,8 @@ public class Test { throw new Error("no diagnostics generated"); String expected = "B.java:6:6: compiler.err.cant.access: p.A, " + - "(- compiler.misc.bad.class.file.header: A.class, " + - "(- compiler.misc.class.file.wrong.class: q.A))"; + "(compiler.misc.bad.class.file.header: A.class, " + + "(compiler.misc.class.file.wrong.class: q.A))"; if (!out[0].equals(expected)) { System.err.println("expected: " + expected); diff --git a/langtools/test/tools/javac/6668794/badSource/Test.out b/langtools/test/tools/javac/6668794/badSource/Test.out index e9fbdf99bda..94e1416d7a7 100644 --- a/langtools/test/tools/javac/6668794/badSource/Test.out +++ b/langtools/test/tools/javac/6668794/badSource/Test.out @@ -1 +1 @@ -Test.java:10:6: compiler.err.cant.access: p.A, (- compiler.misc.bad.source.file.header: A.java, (- compiler.misc.file.doesnt.contain.class: p.A)) +Test.java:10:6: compiler.err.cant.access: p.A, (compiler.misc.bad.source.file.header: A.java, (compiler.misc.file.doesnt.contain.class: p.A)) diff --git a/langtools/test/tools/javac/6758789/T6758789b.out b/langtools/test/tools/javac/6758789/T6758789b.out index 2ff12ec5e28..af29552ca25 100644 --- a/langtools/test/tools/javac/6758789/T6758789b.out +++ b/langtools/test/tools/javac/6758789/T6758789b.out @@ -1,3 +1,5 @@ -T6758789b.java:39:11: compiler.warn.prob.found.req: (- compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo +T6758789b.java:39:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo T6758789b.java:39:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo, T6758789a.Foo, kindname.class, T6758789a +- compiler.err.warnings.and.werror +1 error 2 warnings diff --git a/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java new file mode 100644 index 00000000000..6ede4dce723 --- /dev/null +++ b/langtools/test/tools/javac/Diagnostics/6769027/T6769027.java @@ -0,0 +1,499 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6769027 + * @summary Source line should be displayed immediately after the first diagnostic line + * @author Maurizio Cimadamore + * @run main/othervm T6769027 + */ +import java.net.URI; +import java.util.regex.Matcher; +import javax.tools.*; +import com.sun.tools.javac.util.*; + +public class T6769027 { + + enum OutputKind { + RAW("rawDiagnostics","rawDiagnostics"), + BASIC("",""); + + String key; + String value; + + void init(Options opts) { + opts.put(key, value); + } + + OutputKind(String key, String value) { + this.key = key; + this.value = value; + } + } + + enum CaretKind { + DEFAULT("", ""), + SHOW("showCaret","true"), + HIDE("showCaret","false"); + + String key; + String value; + + void init(Options opts) { + opts.put(key, value); + } + + CaretKind(String key, String value) { + this.key = key; + this.value = value; + } + + boolean isEnabled() { + return this == DEFAULT || this == SHOW; + } + } + + enum SourceLineKind { + DEFAULT("", ""), + AFTER_SUMMARY("sourcePosition", "top"), + BOTTOM("sourcePosition", "bottom"); + + String key; + String value; + + void init(Options opts) { + opts.put(key, value); + } + + SourceLineKind(String key, String value) { + this.key = key; + this.value = value; + } + + boolean isAfterSummary() { + return this == DEFAULT || this == AFTER_SUMMARY; + } + } + + enum XDiagsSource { + DEFAULT(""), + SOURCE("source"), + NO_SOURCE("-source"); + + String flag; + + void init(Options opts) { + if (this != DEFAULT) { + String flags = opts.get("diags"); + flags = flags == null ? flag : flags + "," + flag; + opts.put("diags", flags); + } + } + + XDiagsSource(String flag) { + this.flag = flag; + } + + String getOutput(CaretKind caretKind, IndentKind indent, OutputKind outKind) { + String spaces = (outKind == OutputKind.BASIC) ? indent.string : ""; + return "\n" + spaces + "This is a source line" + + (caretKind.isEnabled() ? "\n" + spaces + " ^" : ""); + } + } + + enum XDiagsCompact { + DEFAULT(""), + COMPACT("short"), + NO_COMPACT("-short"); + + String flag; + + void init(Options opts) { + if (this != DEFAULT) { + String flags = opts.get("diags"); + flags = flags == null ? flag : flags + "," + flag; + opts.put("diags", flags); + } + } + + XDiagsCompact(String flag) { + this.flag = flag; + } + } + + enum ErrorKind { + SINGLE("single", + "compiler.err.single: Hello!", + "KXThis is a test error message Hello!"), + DOUBLE("double", + "compiler.err.double: Hello!", + "KXThis is a test error message.\n" + + "KXYThis is another line of the above error message Hello!"); + + String key; + String rawOutput; + String nonRawOutput; + + String key() { + return key; + } + + ErrorKind(String key, String rawOutput, String nonRawOutput) { + this.key = key; + this.rawOutput = rawOutput; + this.nonRawOutput = nonRawOutput; + } + + String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent) { + return outKind == OutputKind.RAW ? + rawOutput : + nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", ""); + } + + String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent, String indent) { + return outKind == OutputKind.RAW ? + rawOutput : + nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", indent); + } + } + + enum MultilineKind { + NONE(0), + DOUBLE(1), + NESTED(2), + DOUBLE_NESTED(3); + + static String[][] rawTemplates = { + {"", ",{(E),(E)}", ",{(E,{(E)})}", ",{(E,{(E)}),(E,{(E)})}"}, //ENABLED + {"", "", "", "",""}, //DISABLED + {"", ",{(E)}", ",{(E,{(E)})}", ",{(E,{(E)})}"}, //LIMIT_LENGTH + {"", ",{(E),(E)}", ",{(E)}", ",{(E),(E)}"}, //LIMIT_DEPTH + {"", ",{(E)}", ",{(E)}", ",{(E)}"}}; //LIMIT_BOTH + + static String[][] basicTemplates = { + {"", "\nE\nE", "\nE\nQ", "\nE\nQ\nE\nQ"}, //ENABLED + {"", "", "", "",""}, //DISABLED + {"", "\nE", "\nE\nQ", "\nE\nQ"}, //LIMIT_LENGTH + {"", "\nE\nE", "\nE", "\nE\nE"}, //LIMIT_DEPTH + {"", "\nE", "\nE", "\nE"}}; //LIMIT_BOTH + + + int index; + + MultilineKind (int index) { + this.index = index; + } + + boolean isDouble() { + return this == DOUBLE || this == DOUBLE_NESTED; + } + + boolean isNested() { + return this == NESTED || this == DOUBLE_NESTED; + } + + String getOutput(OutputKind outKind, ErrorKind errKind, MultilinePolicy policy, + IndentKind summaryIndent, IndentKind detailsIndent, IndentKind multiIndent) { + String constIndent = (errKind == ErrorKind.DOUBLE) ? + summaryIndent.string + detailsIndent.string : + summaryIndent.string; + constIndent += multiIndent.string; + + String errMsg1 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent); + String errMsg2 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent + constIndent); + + errMsg1 = errMsg1.replaceAll("compiler.err", "compiler.misc"); + errMsg1 = errMsg1.replaceAll("error message", "subdiagnostic"); + errMsg2 = errMsg2.replaceAll("compiler.err", "compiler.misc"); + errMsg2 = errMsg2.replaceAll("error message", "subdiagnostic"); + + String template = outKind == OutputKind.RAW ? + rawTemplates[policy.index][index] : + basicTemplates[policy.index][index]; + + template = template.replaceAll("E", errMsg1); + return template.replaceAll("Q", errMsg2); + } + } + + enum MultilinePolicy { + ENABLED(0, "multilinePolicy", "enabled"), + DISABLED(1, "multilinePolicy", "disabled"), + LIMIT_LENGTH(2, "multilinePolicy", "limit:1:*"), + LIMIT_DEPTH(3, "multilinePolicy", "limit:*:1"), + LIMIT_BOTH(4, "multilinePolicy", "limit:1:1"); + + String name; + String value; + int index; + + MultilinePolicy(int index, String name, String value) { + this.name = name; + this.value = value; + this.index = index; + } + + void init(Options options) { + options.put(name, value); + } + } + + enum PositionKind { + NOPOS(Position.NOPOS, "- ", "error: "), + POS(5, "/Test.java:1:6: ", "myfo:/Test.java:1: "); + + int pos; + String rawOutput; + String nonRawOutput; + + PositionKind(int pos, String rawOutput, String nonRawOutput) { + this.pos = pos; + this.rawOutput = rawOutput; + this.nonRawOutput = nonRawOutput; + } + + JCDiagnostic.DiagnosticPosition pos() { + return new JCDiagnostic.SimpleDiagnosticPosition(pos); + } + + String getOutput(OutputKind outputKind) { + return outputKind == OutputKind.RAW ? + rawOutput : + nonRawOutput; + } + } + + static class MyFileObject extends SimpleJavaFileObject { + private String text; + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } + + enum IndentKind { + NONE(""), + CUSTOM(" "); + + String string; + + IndentKind(String indent) { + string = indent; + } + } + + class MyLog extends Log { + MyLog(Context ctx) { + super(ctx); + } + + @Override + protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) { + return new java.io.PrintWriter(System.out); + } + + @Override + protected boolean shouldReport(JavaFileObject jfo, int pos) { + return true; + } + } + + int nerrors = 0; + + void exec(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind, + MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource, + XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind, + IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent, + IndentKind subdiagsIndent) { + Context ctx = new Context(); + Options options = Options.instance(ctx); + outputKind.init(options); + multiPolicy.init(options); + xdiagsSource.init(options); + xdiagsCompact.init(options); + caretKind.init(options); + sourceLineKind.init(options); + String indentString = ""; + indentString = (summaryIndent == IndentKind.CUSTOM) ? "3" : "0"; + indentString += (detailsIndent == IndentKind.CUSTOM) ? "|3" : "|0"; + indentString += (sourceIndent == IndentKind.CUSTOM) ? "|3" : "|0"; + indentString += (subdiagsIndent == IndentKind.CUSTOM) ? "|3" : "|0"; + options.put("diagsIndentation", indentString); + MyLog log = new MyLog(ctx); + JavacMessages messages = JavacMessages.instance(ctx); + messages.add("tester"); + JCDiagnostic.Factory diags = JCDiagnostic.Factory.instance(ctx); + log.useSource(new MyFileObject("This is a source line")); + JCDiagnostic d = diags.error(log.currentSource(), + posKind.pos(), + errorKind.key(), "Hello!"); + if (multiKind != MultilineKind.NONE) { + JCDiagnostic sub = diags.fragment(errorKind.key(), "Hello!"); + if (multiKind.isNested()) + sub = new JCDiagnostic.MultilineDiagnostic(sub, List.of(sub)); + List subdiags = multiKind.isDouble() ? + List.of(sub, sub) : + List.of(sub); + d = new JCDiagnostic.MultilineDiagnostic(d, subdiags); + } + String diag = log.getDiagnosticFormatter().format(d, messages.getCurrentLocale()); + checkOutput(diag, + outputKind, + errorKind, + multiKind, + multiPolicy, + posKind, + xdiagsSource, + xdiagsCompact, + caretKind, + sourceLineKind, + summaryIndent, + detailsIndent, + sourceIndent, + subdiagsIndent); + } + + void test() { + for (OutputKind outputKind : OutputKind.values()) { + for (ErrorKind errKind : ErrorKind.values()) { + for (MultilineKind multiKind : MultilineKind.values()) { + for (MultilinePolicy multiPolicy : MultilinePolicy.values()) { + for (PositionKind posKind : PositionKind.values()) { + for (XDiagsSource xdiagsSource : XDiagsSource.values()) { + for (XDiagsCompact xdiagsCompact : XDiagsCompact.values()) { + for (CaretKind caretKind : CaretKind.values()) { + for (SourceLineKind sourceLineKind : SourceLineKind.values()) { + for (IndentKind summaryIndent : IndentKind.values()) { + for (IndentKind detailsIndent : IndentKind.values()) { + for (IndentKind sourceIndent : IndentKind.values()) { + for (IndentKind subdiagsIndent : IndentKind.values()) { + exec(outputKind, + errKind, + multiKind, + multiPolicy, + posKind, + xdiagsSource, + xdiagsCompact, + caretKind, + sourceLineKind, + summaryIndent, + detailsIndent, + sourceIndent, + subdiagsIndent); + } + } + } + } + } + } + } + } + } + } + } + } + } + if (nerrors != 0) + throw new AssertionError(nerrors + " errors found"); + } + + void printInfo(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind, + MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource, + XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind, + IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent, + IndentKind subdiagsIndent, String errorLine) { + String sep = "*********************************************************"; + String desc = "raw=" + outputKind + " pos=" + posKind + " key=" + errorKind.key() + + " multiline=" + multiKind +" multiPolicy=" + multiPolicy.value + + " diags= " + java.util.Arrays.asList(xdiagsSource.flag, xdiagsCompact.flag) + + " caret=" + caretKind + " sourcePosition=" + sourceLineKind + + " summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent + + " sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent; + System.out.println(sep); + System.out.println(desc); + System.out.println(sep); + System.out.println(msg); + System.out.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine); + } + + void checkOutput(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind, + MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource, + XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind, + IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent, + IndentKind subdiagsIndent) { + boolean shouldPrintSource = posKind == PositionKind.POS && + xdiagsSource != XDiagsSource.NO_SOURCE && + (xdiagsSource == XDiagsSource.SOURCE || + outputKind == OutputKind.BASIC); + String errorLine = posKind.getOutput(outputKind) + + errorKind.getOutput(outputKind, summaryIndent, detailsIndent); + if (xdiagsCompact != XDiagsCompact.COMPACT) + errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy, summaryIndent, detailsIndent, subdiagsIndent); + String[] lines = errorLine.split("\n"); + if (xdiagsCompact == XDiagsCompact.COMPACT) { + errorLine = lines[0]; + lines = new String[] {errorLine}; + } + if (shouldPrintSource) { + if (sourceLineKind.isAfterSummary()) { + String sep = "\n"; + if (lines.length == 1) { + errorLine += "\n"; + sep = ""; + } + errorLine = errorLine.replaceFirst("\n", + Matcher.quoteReplacement(xdiagsSource.getOutput(caretKind, sourceIndent, outputKind) + sep)); + } + else + errorLine += xdiagsSource.getOutput(caretKind, sourceIndent, outputKind); + } + + if (!msg.equals(errorLine)) { + printInfo(msg, + outputKind, + errorKind, + multiKind, + multiPolicy, + posKind, + xdiagsSource, + xdiagsCompact, + caretKind, + sourceLineKind, + summaryIndent, + detailsIndent, + sourceIndent, + subdiagsIndent, + errorLine); + nerrors++; + } + } + + public static void main(String... args) throws Exception { + new T6769027().test(); + } +} diff --git a/langtools/test/tools/javac/Diagnostics/6769027/tester.properties b/langtools/test/tools/javac/Diagnostics/6769027/tester.properties new file mode 100644 index 00000000000..666a52eb198 --- /dev/null +++ b/langtools/test/tools/javac/Diagnostics/6769027/tester.properties @@ -0,0 +1,13 @@ +compiler.err.single=\ + This is a test error message {0} + +compiler.err.double=\ + This is a test error message.\n\ + This is another line of the above error message {0} + +compiler.misc.single=\ + This is a test subdiagnostic {0} + +compiler.misc.double=\ + This is a test subdiagnostic.\n\ + This is another line of the above subdiagnostic {0} diff --git a/langtools/test/tools/javac/ExtendArray.out b/langtools/test/tools/javac/ExtendArray.out index 86878431daa..ad5d8877c71 100644 --- a/langtools/test/tools/javac/ExtendArray.out +++ b/langtools/test/tools/javac/ExtendArray.out @@ -1,6 +1,6 @@ ExtendArray.java:11: unexpected type -found : java.lang.Object[] -required: class public class ExtendArray extends Object[] {} ^ + required: class + found: java.lang.Object[] 1 error diff --git a/langtools/test/tools/javac/T5048776b.out b/langtools/test/tools/javac/T5048776b.out index 5eb9b79ef59..ab9688edb01 100644 --- a/langtools/test/tools/javac/T5048776b.out +++ b/langtools/test/tools/javac/T5048776b.out @@ -1,3 +1,3 @@ -T5048776.java:12:10: compiler.warn.override.varargs.missing: (- compiler.misc.varargs.override: foo(java.lang.Object...), A1a, foo(java.lang.Object[]), A1) -T5048776.java:20:10: compiler.warn.override.varargs.extra: (- compiler.misc.varargs.override: foo(java.lang.Object[]), A2a, foo(java.lang.Object...), A2) +T5048776.java:12:10: compiler.warn.override.varargs.missing: (compiler.misc.varargs.override: foo(java.lang.Object...), A1a, foo(java.lang.Object[]), A1) +T5048776.java:20:10: compiler.warn.override.varargs.extra: (compiler.misc.varargs.override: foo(java.lang.Object[]), A2a, foo(java.lang.Object...), A2) 2 warnings diff --git a/langtools/test/tools/javac/T6214885a.out b/langtools/test/tools/javac/T6214885a.out index f09fff67b0e..8ca1aaced2d 100644 --- a/langtools/test/tools/javac/T6214885a.out +++ b/langtools/test/tools/javac/T6214885a.out @@ -1,6 +1,6 @@ T6214885.java:11 cannot find symbol -symbol : variable x -location: class T6214885 x = 1; ^ + symbol: variable x + location: class T6214885 1 error diff --git a/langtools/test/tools/javac/T6214885b.out b/langtools/test/tools/javac/T6214885b.out index 1ee86363a12..4dc30190da0 100644 --- a/langtools/test/tools/javac/T6214885b.out +++ b/langtools/test/tools/javac/T6214885b.out @@ -1,6 +1,6 @@ T6214885.java:11:9 cannot find symbol -symbol : variable x -location: class T6214885 x = 1; ^ + symbol: variable x + location: class T6214885 1 error diff --git a/langtools/test/tools/javac/T6230128.out b/langtools/test/tools/javac/T6230128.out index d6a08595385..32863533ef1 100644 --- a/langtools/test/tools/javac/T6230128.out +++ b/langtools/test/tools/javac/T6230128.out @@ -1,2 +1,2 @@ -T6230128.java:11:10: compiler.err.override.weaker.access: (- compiler.misc.cant.override: foo(java.lang.Object...), A1a, foo(java.lang.Object[]), A1), public +T6230128.java:11:10: compiler.err.override.weaker.access: (compiler.misc.cant.override: foo(java.lang.Object...), A1a, foo(java.lang.Object[]), A1), public 1 error diff --git a/langtools/test/tools/javac/T6241723.out b/langtools/test/tools/javac/T6241723.out index 32eabe43656..2391e4394b8 100644 --- a/langtools/test/tools/javac/T6241723.out +++ b/langtools/test/tools/javac/T6241723.out @@ -2,4 +2,6 @@ T6241723.java:21:5: compiler.warn.has.been.deprecated: A1, unnamed package T6241723.java:23:7: compiler.warn.has.been.deprecated: A2.A21, A2 T6241723.java:26:5: compiler.warn.has.been.deprecated: Z1, unnamed package T6241723.java:28:7: compiler.warn.has.been.deprecated: Z2.Z21, Z2 +- compiler.err.warnings.and.werror +1 error 4 warnings diff --git a/langtools/test/tools/javac/T6595666.java b/langtools/test/tools/javac/T6595666.java new file mode 100644 index 00000000000..009d4a32059 --- /dev/null +++ b/langtools/test/tools/javac/T6595666.java @@ -0,0 +1,68 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6595666 + * @summary fix -Werror + */ + +import java.io.*; +import java.util.*; + +public class T6595666 { + void m() { + // the following line must create warnings with -Xlint, because of unchecked conversion + List list = new ArrayList(); + } + + public static void main(String... args) throws Exception { + File testSrc = new File(System.getProperty("test.src", ".")); + + String basename = T6595666.class.getName(); + File srcFile = new File(testSrc, basename+".java"); + File classFile = new File(basename+".class"); + classFile.delete(); + if (classFile.exists()) + throw new Exception("setup error, can't delete " + classFile); + + compile(1, "-d", ".", "-Xlint", "-Werror", srcFile.getPath()); + if (classFile.exists()) + throw new Exception("failed: found " + classFile); + + compile(0, "-d", ".", "-Xlint", srcFile.getPath()); + if (!classFile.exists()) + throw new Exception("failed: " + classFile + " not found"); + } + + private static void compile(int rc, String... args) throws Exception { + System.err.println("compile: " + Arrays.asList(args)); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc2 = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + System.err.println(sw); + if (rc != rc2) + throw new Exception("bad exit code; expected " + rc + ", found " + rc2); + } +} diff --git a/langtools/test/tools/javac/T6794959.java b/langtools/test/tools/javac/T6794959.java new file mode 100644 index 00000000000..d2ca623c9c1 --- /dev/null +++ b/langtools/test/tools/javac/T6794959.java @@ -0,0 +1,36 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6794959 + * @summary add new switch -XDexpectKeys=key,key,... + * @compile T6794959.java + * @compile/fail -XDfailcomplete=java.lang.String T6794959.java + * @compile -XDfailcomplete=java.lang.String -XDexpectKeys=compiler.err.cant.resolve.location T6794959.java + * @compile/fail -XDexpectKeys=compiler.err.cant.resolve.location T6794959.java + */ + +class T6794959 { + String s; +} diff --git a/langtools/test/tools/javac/annotations/6365854/test1.out b/langtools/test/tools/javac/annotations/6365854/test1.out index ed81b94111b..00eaf216db2 100644 --- a/langtools/test/tools/javac/annotations/6365854/test1.out +++ b/langtools/test/tools/javac/annotations/6365854/test1.out @@ -1,2 +1,2 @@ -- compiler.warn.annotation.method.not.found.reason: test.annotation.TestAnnotation, test, (- compiler.misc.class.file.not.found: test.annotation.TestAnnotation) +- compiler.warn.annotation.method.not.found.reason: test.annotation.TestAnnotation, test, (compiler.misc.class.file.not.found: test.annotation.TestAnnotation) 1 warning diff --git a/langtools/test/tools/javac/cast/6557182/T6557182.java b/langtools/test/tools/javac/cast/6557182/T6557182.java new file mode 100644 index 00000000000..56bbe702f5e --- /dev/null +++ b/langtools/test/tools/javac/cast/6557182/T6557182.java @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @author Maurizio Cimadamore + * @bug 6557182 + * @summary Unchecked warning *and* inconvertible types + * @compile/fail/ref=T6557182.out -XDrawDiagnostics -Xlint:unchecked T6557182.java + */ + +class T6557182 { + + > void test1(T t) { + Comparable ci = (Comparable) t; + } + + > void test2(T t) { + Comparable ci = (Comparable) t; + } +} diff --git a/langtools/test/tools/javac/cast/6557182/T6557182.out b/langtools/test/tools/javac/cast/6557182/T6557182.out new file mode 100644 index 00000000000..5f25497ace2 --- /dev/null +++ b/langtools/test/tools/javac/cast/6557182/T6557182.out @@ -0,0 +1,4 @@ +T6557182.java:35:56: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T, java.lang.Comparable +T6557182.java:39:56: compiler.warn.prob.found.req: (compiler.misc.unchecked.cast.to.type), T, java.lang.Comparable +1 error +1 warning diff --git a/langtools/test/tools/javac/cast/6665356/T6665356.out b/langtools/test/tools/javac/cast/6665356/T6665356.out index 029c66400a2..1db10c64ca4 100644 --- a/langtools/test/tools/javac/cast/6665356/T6665356.out +++ b/langtools/test/tools/javac/cast/6665356/T6665356.out @@ -1,8 +1,8 @@ -T6665356.java:54:55: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:58:58: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:62:65: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:66:57: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:70:60: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:74:55: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner -T6665356.java:78:58: compiler.err.prob.found.req: (- compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:54:55: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:58:58: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:62:65: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:66:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:70:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:74:55: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner +T6665356.java:78:58: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6665356.Outer.Inner, T6665356.Outer.Inner 7 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/cast/6795580/T6795580.java b/langtools/test/tools/javac/cast/6795580/T6795580.java new file mode 100644 index 00000000000..9539e32e0df --- /dev/null +++ b/langtools/test/tools/javac/cast/6795580/T6795580.java @@ -0,0 +1,80 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @author Maurizio Cimadamore + * @bug 6795580 + * @summary parser confused by square brackets in qualified generic cast + * @compile/fail/ref=T6795580.out -XDrawDiagnostics T6795580.java + */ + +class T6795580 { + class Outer { + class Inner {} + } + + void cast1(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast2(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast3(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast4(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast5(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast6(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast7(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast8(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast9(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast10(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } + + void cast11(Outer.Inner[] p) { + Object o = (Outer.Inner[])p; + } +} \ No newline at end of file diff --git a/langtools/test/tools/javac/cast/6795580/T6795580.out b/langtools/test/tools/javac/cast/6795580/T6795580.out new file mode 100644 index 00000000000..a5d70401650 --- /dev/null +++ b/langtools/test/tools/javac/cast/6795580/T6795580.out @@ -0,0 +1,8 @@ +T6795580.java:54:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:58:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:62:67: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:66:59: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:70:62: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:74:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +T6795580.java:78:60: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), T6795580.Outer.Inner[], T6795580.Outer.Inner[] +7 errors diff --git a/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.out b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.out index e3cb33f72f8..2b3f2b6b267 100644 --- a/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.out +++ b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment.out @@ -1,4 +1,6 @@ DeprecatedDocComment.java:27:28: compiler.warn.has.been.deprecated: deprecatedTest1(), DeprecatedDocComment2 DeprecatedDocComment.java:31:28: compiler.warn.has.been.deprecated: deprecatedTest5(), DeprecatedDocComment2 DeprecatedDocComment.java:32:28: compiler.warn.has.been.deprecated: deprecatedTest6(), DeprecatedDocComment2 +- compiler.err.warnings.and.werror +1 error 3 warnings diff --git a/langtools/test/tools/javac/generics/6207386/T6207386.out b/langtools/test/tools/javac/generics/6207386/T6207386.out index bd98d3123c8..768c5c2d341 100644 --- a/langtools/test/tools/javac/generics/6207386/T6207386.out +++ b/langtools/test/tools/javac/generics/6207386/T6207386.out @@ -1,2 +1,2 @@ -T6207386.java:13:30: compiler.err.prob.found.req: (- compiler.misc.incompatible.types), X, T6207386.F +T6207386.java:13:30: compiler.err.prob.found.req: (compiler.misc.incompatible.types), X, T6207386.F 1 error diff --git a/langtools/test/tools/javac/generics/6729401/T6729401.java b/langtools/test/tools/javac/generics/6729401/T6729401.java new file mode 100644 index 00000000000..dc7be410bfc --- /dev/null +++ b/langtools/test/tools/javac/generics/6729401/T6729401.java @@ -0,0 +1,46 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6729401 + * + * @summary Compiler error when using F-bounded generics with free type variables + * @author Maurizio Cimadamore + * @compile T6729401.java + * + */ + +class T6729401 { + + interface I { + > void m(I x); + } + + ,Y extends I> void test(I x, I y) { + x.m(y); + x.m(y); + y.m(x); + y.m(x); + } +} diff --git a/langtools/test/tools/javac/generics/inference/6315770/T6315770.java b/langtools/test/tools/javac/generics/inference/6315770/T6315770.java new file mode 100644 index 00000000000..2bee9a14a8f --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.java @@ -0,0 +1,42 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6315770 + * @summary javac inference allows creation of strange types: Integer & Runnable + * @author Maurizio Cimadamore + * + * @compile/fail/ref=T6315770.out T6315770.java -XDrawDiagnostics + */ + +class T6315770 { + T6315770 m() { + return null; + } + void test() { + T6315770 c1 = m(); + T6315770 c2 = m(); + T6315770 c3 = m(); + } +} diff --git a/langtools/test/tools/javac/generics/inference/6315770/T6315770.out b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out new file mode 100644 index 00000000000..dd1fdb9e3d3 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/6315770/T6315770.out @@ -0,0 +1,3 @@ +T6315770.java:39:42: compiler.err.undetermined.type.1: T6315770, (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable) +T6315770.java:40:40: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.conforming.instance.exists: T, T6315770, T6315770)), T6315770, T6315770 +2 errors diff --git a/langtools/test/tools/javac/generics/inference/6718364/T6718364.out b/langtools/test/tools/javac/generics/inference/6718364/T6718364.out index e049269d284..1b5ed9ad241 100644 --- a/langtools/test/tools/javac/generics/inference/6718364/T6718364.out +++ b/langtools/test/tools/javac/generics/inference/6718364/T6718364.out @@ -1,3 +1,3 @@ -T6718364.java:36:32: compiler.warn.prob.found.req: (- compiler.misc.unchecked.assign), T6718364.X, T6718364.X +T6718364.java:36:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6718364.X, T6718364.X T6718364.java:36:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6718364.X,T, T6718364.X>,T6718364.X, kindname.class, T6718364 2 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/generics/typevars/6680106/T6680106.out b/langtools/test/tools/javac/generics/typevars/6680106/T6680106.out index 06f1eaf100f..f26d2a47c23 100644 --- a/langtools/test/tools/javac/generics/typevars/6680106/T6680106.out +++ b/langtools/test/tools/javac/generics/typevars/6680106/T6680106.out @@ -1,13 +1,13 @@ -T6680106.java:34:25: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) -T6680106.java:35:25: compiler.err.type.found.req: S[], (- compiler.misc.type.req.class) -T6680106.java:35:40: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) -T6680106.java:36:25: compiler.err.type.found.req: S[], (- compiler.misc.type.req.class) -T6680106.java:36:40: compiler.err.type.found.req: U[], (- compiler.misc.type.req.class) -T6680106.java:36:55: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) -T6680106.java:37:30: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) -T6680106.java:38:30: compiler.err.type.found.req: S[], (- compiler.misc.type.req.class) -T6680106.java:38:50: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) -T6680106.java:39:30: compiler.err.type.found.req: S[], (- compiler.misc.type.req.class) -T6680106.java:39:50: compiler.err.type.found.req: U[], (- compiler.misc.type.req.class) -T6680106.java:39:70: compiler.err.type.found.req: T[], (- compiler.misc.type.req.class) +T6680106.java:34:25: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) +T6680106.java:35:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) +T6680106.java:35:40: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) +T6680106.java:36:25: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) +T6680106.java:36:40: compiler.err.type.found.req: U[], (compiler.misc.type.req.class) +T6680106.java:36:55: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) +T6680106.java:37:30: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) +T6680106.java:38:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) +T6680106.java:38:50: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) +T6680106.java:39:30: compiler.err.type.found.req: S[], (compiler.misc.type.req.class) +T6680106.java:39:50: compiler.err.type.found.req: U[], (compiler.misc.type.req.class) +T6680106.java:39:70: compiler.err.type.found.req: T[], (compiler.misc.type.req.class) 12 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.out b/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.out index 94a21c0ae5f..b049ccd5aab 100644 --- a/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.out +++ b/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.out @@ -1,5 +1,5 @@ MissingSuperRecovery.java:15: cannot access base -class file for base not found public class MissingSuperRecovery extends impl { ^ + class file for base not found 1 error diff --git a/langtools/test/tools/javac/processing/model/TestExceptions.java b/langtools/test/tools/javac/processing/model/TestExceptions.java new file mode 100644 index 00000000000..0d746886b1b --- /dev/null +++ b/langtools/test/tools/javac/processing/model/TestExceptions.java @@ -0,0 +1,55 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6794071 + * @summary Test that exceptions have a proper parent class + * @author Joseph D. Darcy + */ + +import javax.lang.model.UnknownEntityException; +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +/* + * Verify UnknownFooExceptions can be caught with a common parent + * exception. + */ +public class TestExceptions { + public static void main(String... args) { + RuntimeException[] exceptions = { + new UnknownElementException((Element)null, (Object)null), + new UnknownAnnotationValueException((AnnotationValue) null, (Object) null), + new UnknownTypeException((TypeMirror)null, (Object)null) + }; + + for(RuntimeException exception : exceptions) { + try { + throw exception; + } catch (UnknownEntityException uee) { + ; + } + } + } +} diff --git a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java index c77ac09d2a2..e783d29264f 100644 --- a/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java +++ b/langtools/test/tools/javac/processing/model/testgetallmembers/Main.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6374357 6308351 + * @bug 6374357 6308351 6707027 * @summary PackageElement.getEnclosedElements() throws ClassReader$BadClassFileException * @author Peter von der Ah\u00e9 * @run main/othervm -Xmx256m Main @@ -118,7 +118,7 @@ public class Main { packages.size(), classes, nestedClasses); if (classes < 9000) throw new AssertionError("Too few classes in PLATFORM_CLASS_PATH ;-)"); - if (packages.size() < 545) + if (packages.size() < 530) throw new AssertionError("Too few packages in PLATFORM_CLASS_PATH ;-)"); if (nestedClasses < 3000) throw new AssertionError("Too few nested classes in PLATFORM_CLASS_PATH ;-)"); diff --git a/langtools/test/tools/javac/unicode/UnicodeNewline.out b/langtools/test/tools/javac/unicode/UnicodeNewline.out index 366d8c6eb0a..5b71702fb4d 100644 --- a/langtools/test/tools/javac/unicode/UnicodeNewline.out +++ b/langtools/test/tools/javac/unicode/UnicodeNewline.out @@ -1,6 +1,6 @@ UnicodeNewline.java:11: cannot find symbol -symbol : class xyzzy -location: class UnicodeNewline xyzzy plugh; // error should be HERE ^ + symbol: class xyzzy + location: class UnicodeNewline 1 error diff --git a/langtools/test/tools/javadoc/6176978/T6176978.java b/langtools/test/tools/javadoc/6176978/T6176978.java new file mode 100644 index 00000000000..892271a8e3c --- /dev/null +++ b/langtools/test/tools/javadoc/6176978/T6176978.java @@ -0,0 +1,80 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6176978 + * @summary current Javadoc's invocation and extension (Doclet) mechanisms are problematic + * @build T6176978 + * @run main T6176978 + */ + +import java.io.*; +import java.net.*; + +public class T6176978 +{ + public static void main(String[] args) throws Exception { + // create and use a temp dir that will not be on jtreg's + // default class path + File tmpDir = new File("tmp"); + tmpDir.mkdirs(); + + File testSrc = new File(System.getProperty("test.src", ".")); + String[] javac_args = { + "-d", + "tmp", + new File(testSrc, "X.java").getPath() + }; + + int rc = com.sun.tools.javac.Main.compile(javac_args); + if (rc != 0) + throw new Error("javac exit code: " + rc); + + String[] jdoc_args = { + "-doclet", + "X", + new File(testSrc, "T6176978.java").getPath() + }; + + rc = com.sun.tools.javadoc.Main.execute(jdoc_args); + if (rc == 0) + throw new Error("javadoc unexpectedly succeeded"); + + + + Thread currThread = Thread.currentThread(); + ClassLoader saveClassLoader = currThread.getContextClassLoader(); + URLClassLoader urlCL = new URLClassLoader(new URL[] { tmpDir.toURL() }); + currThread.setContextClassLoader(urlCL); + + try { + rc = com.sun.tools.javadoc.Main.execute(jdoc_args); + if (rc != 0) + throw new Error("javadoc exit: " + rc); + } + finally { + currThread.setContextClassLoader(saveClassLoader); + } + } +} diff --git a/langtools/test/tools/javadoc/6176978/X.java b/langtools/test/tools/javadoc/6176978/X.java new file mode 100644 index 00000000000..2eb5bf4335b --- /dev/null +++ b/langtools/test/tools/javadoc/6176978/X.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import com.sun.javadoc.*; + +public class X { + public static boolean start(RootDoc root) { + System.out.println("X.start"); + return true; + } +}